From 3683e8cc7a7b492c2ea2fd565d0473b2911bcf40 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Fri, 14 Jul 2023 18:22:24 +0000 Subject: [PATCH] AyaNova CE Archive added as recovered from storage during attempt to upgrade a customer from v1.7 to v8! --- AyaNovaSolution.sln | 1 + .../sp/ArasClientRequests.cpp | 1024 +++ .../sp/ArasClientRequests.h | 84 + .../sp/AyaSysInfo.cpp | 593 ++ .../sp/AyaSysInfo.h | 30 + .../sp/CheckComboBox.cpp | 425 + .../sp/CheckComboBox.h | 63 + .../sp/ClientsDlg.cpp | 2570 ++++++ .../sp/ClientsDlg.h | 225 + .../sp/ClientsRA.cpp | 546 ++ .../sp/ClientsRA.h | 91 + .../sp/Common.h | 23 + .../sp/ConsolidateDlg.cpp | 196 + .../sp/ConsolidateDlg.h | 56 + .../sp/ContactDlg.cpp | 212 + .../sp/ContactDlg.h | 64 + .../sp/ContactsViewDlg.cpp | 225 + .../sp/ContactsViewDlg.h | 63 + .../sp/ContractsDlg.cpp | 300 + .../sp/ContractsDlg.h | 65 + .../sp/Crc32Static.cpp | 435 + .../sp/Crc32Static.h | 25 + .../sp/DBUtils.cpp | 7325 +++++++++++++++++ .../sp/DBUtils.h | 143 + .../sp/DIBSectionLite.cpp | 1666 ++++ .../sp/DIBSectionLite.h | 243 + .../sp/DefaultsDlg.cpp | 245 + .../sp/DefaultsDlg.h | 62 + .../sp/DispatchFieldsDlg.cpp | 1381 ++++ .../sp/DispatchFieldsDlg.h | 154 + .../sp/DispatchView.cpp | 96 + .../sp/DispatchView.h | 113 + .../sp/DlgDispStatPopup.cpp | 263 + .../sp/DlgDispStatPopup.h | 81 + .../sp/DlgSchedMarkers.cpp | 503 ++ .../sp/DlgSchedMarkers.h | 91 + .../sp/DlgStartUp.cpp | 51 + .../sp/DlgStartUp.h | 46 + .../sp/DlgTasks.cpp | 446 + .../sp/DlgTasks.h | 77 + .../sp/FindClientDlg.cpp | 206 + .../sp/FindClientDlg.h | 64 + .../sp/FlatHeaderCtrl.cpp | 1440 ++++ .../sp/FlatHeaderCtrl.h | 279 + .../sp/GZK.cpp | 395 + .../sp/GZK.h | 62 + .../sp/GZRset.cpp | 2220 +++++ .../sp/GZRset.h | 135 + .../sp/GZRsetPool.cpp | 867 ++ .../sp/GZRsetPool.h | 67 + .../sp/GenericPopupList.cpp | 103 + .../sp/GenericPopupList.h | 54 + .../sp/GetAllOrXValue.cpp | 82 + .../sp/GetAllOrXValue.h | 52 + .../sp/GetStringDlg.cpp | 94 + .../sp/GetStringDlg.h | 52 + .../sp/GroupsDlg.cpp | 803 ++ .../sp/GroupsDlg.h | 153 + .../sp/KD.cpp | 226 + .../sp/KD.h | 56 + .../sp/Label.cpp | 276 + .../sp/Label.h | 79 + .../sp/LoanersDlg.cpp | 823 ++ .../sp/LoanersDlg.h | 94 + .../sp/LoanersEditDlg.cpp | 476 ++ .../sp/LoanersEditDlg.h | 83 + .../sp/LogTrace.cpp | 169 + .../sp/LogTrace.h | 53 + .../sp/LoginDlg.cpp | 525 ++ .../sp/LoginDlg.h | 71 + .../sp/MSJRO.tlh | 344 + .../sp/MSJRO.tli | 230 + .../sp/MailMsgDlg.cpp | 318 + .../sp/MailMsgDlg.h | 71 + .../sp/MailReaderDlg.cpp | 511 ++ .../sp/MailReaderDlg.h | 68 + .../sp/MainFrm.cpp | 96 + .../sp/MainFrm.h | 53 + .../sp/MakeHelp.bat | 39 + .../sp/MemDC.h | 93 + .../sp/ModelCatsDlg.cpp | 337 + .../sp/ModelCatsDlg.h | 72 + .../sp/ModelsDlg.cpp | 951 +++ .../sp/ModelsDlg.h | 115 + .../sp/ModulVer.cpp | 135 + .../sp/ModulVer.h | 63 + .../sp/NonClientsDlg.cpp | 677 ++ .../sp/NonClientsDlg.h | 103 + .../sp/NullForm.cpp | 72 + .../sp/NullForm.h | 65 + .../sp/PM.cpp | 2275 +++++ .../sp/PM.h | 184 + .../sp/PMCheckDlg.cpp | 1239 +++ .../sp/PMCheckDlg.h | 73 + .../sp/PMDlg.cpp | 952 +++ .../sp/PMDlg.h | 121 + .../sp/PMViewPrompt.cpp | 94 + .../sp/PMViewPrompt.h | 57 + .../sp/PWDlg.cpp | 76 + .../sp/PWDlg.h | 53 + .../sp/Parseit.cpp | 253 + .../sp/Parseit.h | 98 + .../sp/PartsDlg.cpp | 801 ++ .../sp/PartsDlg.h | 105 + .../sp/PerfTimer.cpp | 38 + .../sp/PerfTimer.h | 403 + .../sp/ProbStatDlg.cpp | 342 + .../sp/ProbStatDlg.h | 70 + .../sp/ProjectsDlg.cpp | 476 ++ .../sp/ProjectsDlg.h | 79 + .../sp/RPTS.cpp | 1640 ++++ .../sp/RPTS.h | 167 + .../sp/RatesDlg.cpp | 650 ++ .../sp/RatesDlg.h | 95 + .../sp/ReadMe.txt | 114 + .../sp/ReportCtrl.cpp | 4371 ++++++++++ .../sp/ReportCtrl.h | 818 ++ .../sp/ReportViewerDlg.cpp | 108 + .../sp/ReportViewerDlg.h | 30 + .../sp/ResizeCtrl.cpp | 696 ++ .../sp/ResizeCtrl.h | 187 + .../sp/RptSetDlg.cpp | 739 ++ .../sp/RptSetDlg.h | 101 + .../sp/SRCH.cpp | 2644 ++++++ .../sp/SRCH.h | 130 + .../sp/STAT.cpp | 2216 +++++ .../sp/STAT.h | 150 + .../sp/Scdata.sc | Bin 0 -> 2457600 bytes .../sp/SchedGrps.cpp | 387 + .../sp/SchedGrps.h | 72 + .../sp/Schedule.cpp | 90 + .../sp/Schedule.h | 52 + .../sp/ScheduleFrm.cpp | 2105 +++++ .../sp/ScheduleFrm.h | 166 + .../sp/ScheduleTimeBarData.cpp | 27 + .../sp/ScheduleTimeBarData.h | 35 + .../sp/SimpleDate.cpp | 1091 +++ .../sp/SimpleDate.h | 138 + .../sp/SimpleWODlg.cpp | 2534 ++++++ .../sp/SimpleWODlg.h | 179 + .../sp/SnR.cpp | 465 ++ .../sp/SnR.h | 86 + .../sp/SnREdit.cpp | 585 ++ .../sp/SnREdit.h | 93 + .../sp/SrchView.cpp | 214 + .../sp/SrchView.h | 62 + .../sp/StatusDlg.cpp | 143 + .../sp/StatusDlg.h | 61 + .../sp/StdAfx.cpp | 8 + .../sp/StdAfx.h | 42 + .../sp/StringParser.cpp | 488 ++ .../sp/StringParser.h | 67 + .../sp/TED.cpp | 66 + .../sp/TED.h | 49 + .../sp/UnitsDlg.cpp | 1678 ++++ .../sp/UnitsDlg.h | 157 + .../sp/UserPrefsDlg.cpp | 260 + .../sp/UserPrefsDlg.h | 65 + .../sp/UsersDlg.cpp | 1231 +++ .../sp/UsersDlg.h | 103 + .../sp/WODlg.cpp | 531 ++ .../sp/WODlg.h | 75 + .../sp/WOHeaderDlg.cpp | 3132 +++++++ .../sp/WOHeaderDlg.h | 249 + .../sp/WOTABLabour.cpp | 428 + .../sp/WOTABLabour.h | 82 + .../sp/WOTABParts.cpp | 577 ++ .../sp/WOTABParts.h | 100 + .../sp/WOTABProblem.cpp | 799 ++ .../sp/WOTABProblem.h | 108 + .../sp/WOTABSubRepair.cpp | 426 + .../sp/WOTABSubRepair.h | 89 + .../sp/WOTypesDlg.cpp | 323 + .../sp/WOTypesDlg.h | 68 + .../sp/WoTabLabourEntryDlg.cpp | 1068 +++ .../sp/WoTabLabourEntryDlg.h | 113 + .../sp/XTabCtrl.cpp | 399 + .../sp/XTabCtrl.h | 83 + .../sp/XXXOLDcrpe.hX | 2373 ++++++ .../sp/XXXXOLDcrpe32m.libX | Bin 0 -> 343254 bytes .../sp/XXXXcrpe.hX | 2569 ++++++ .../sp/XXXXcrpe32m.libX | Bin 0 -> 171192 bytes .../sp/XXXXpeplus.cppX | 2292 ++++++ .../sp/XXXXpeplus.hX | 2873 +++++++ .../sp/XferDlg.cpp | 1118 +++ .../sp/XferDlg.h | 85 + .../sp/ZTestDlg.cpp | 191 + .../sp/ZTestDlg.h | 50 + .../sp/ZonesDlg.cpp | 306 + .../sp/ZonesDlg.h | 69 + .../sp/crviewer1.cpp | 19 + .../sp/crviewer1.h | 537 ++ .../sp/ctschedule.cpp | 2461 ++++++ .../sp/ctschedule.h | 401 + .../sp/default.pal | Bin 0 -> 1048 bytes .../sp/empty.sc | Bin 0 -> 106496 bytes .../sp/font.cpp | 111 + .../sp/font.h | 48 + .../sp/gzCombo.cpp | 490 ++ .../sp/gzCombo.h | 131 + .../sp/gzCurrencyFormatter.cpp | 51 + .../sp/gzCurrencyFormatter.h | 21 + .../sp/gzListBox.cpp | 282 + .../sp/gzListBox.h | 75 + .../sp/gzRightsButton.cpp | 230 + .../sp/gzRightsButton.h | 66 + .../sp/hlp/sc.hm | 233 + .../sp/msado15.tlh | 2993 +++++++ .../sp/msado15.tli | 2095 +++++ .../sp/picture.cpp | 55 + .../sp/picture.h | 39 + .../sp/res/HAND-L.CUR | Bin 0 -> 326 bytes .../sp/res/Image2.bmp | Bin 0 -> 98698 bytes .../sp/res/bitmap1.bmp | Bin 0 -> 1014 bytes .../sp/res/bmp00001.bmp | Bin 0 -> 1014 bytes .../sp/res/bmp00002.bmp | Bin 0 -> 34202 bytes .../sp/res/icon1.ico | Bin 0 -> 766 bytes .../sp/res/icon2.ico | Bin 0 -> 766 bytes .../sp/res/icon3.ico | Bin 0 -> 766 bytes .../sp/res/icon4.ico | Bin 0 -> 766 bytes .../sp/res/icon5.ico | Bin 0 -> 12214 bytes .../sp/res/idr_dbut.ico | Bin 0 -> 1078 bytes .../sp/res/idr_evnt.ico | Bin 0 -> 1078 bytes .../sp/res/idr_main.ico | Bin 0 -> 1078 bytes .../sp/res/idr_mgr_.ico | Bin 0 -> 1078 bytes .../sp/res/idr_rpts.ico | Bin 0 -> 1078 bytes .../sp/res/idr_sets.ico | Bin 0 -> 1078 bytes .../sp/res/idr_snr_.ico | Bin 0 -> 1078 bytes .../sp/res/idr_srch.ico | Bin 0 -> 1078 bytes .../sp/res/idr_stat.ico | Bin 0 -> 1078 bytes .../sp/res/sc.bmp | Bin 0 -> 75682 bytes .../sp/res/sp.ico | Bin 0 -> 1078 bytes .../sp/res/sp.rc2 | 13 + .../sp/res/spDoc.ico | Bin 0 -> 1078 bytes .../sp/res/splash1.bmp | Bin 0 -> 34202 bytes .../sp/resource.h | 987 +++ .../sp/resource.hm | 10 + .../sp/sdi.ico | Bin 0 -> 1078 bytes .../sp/sp.aps | Bin 0 -> 366892 bytes .../sp/sp.clw | 2496 ++++++ .../sp/sp.cpp | 3047 +++++++ .../sp/sp.dep | 784 ++ .../sp/sp.dsp | 1181 +++ .../sp/sp.dsw | 30 + .../sp/sp.h | 286 + .../sp/sp.mak | 988 +++ .../sp/sp.ncb | Bin 0 -> 4467712 bytes .../sp/sp.opt | Bin 0 -> 60928 bytes .../sp/sp.plg | 129 + .../sp/sp.rc | 3623 ++++++++ .../sp/sp.sln | 21 + .../sp/sp.sln.old | 21 + .../sp/sp.stt | 3 + .../sp/sp.suo | Bin 0 -> 14848 bytes .../sp/sp.vcproj | 889 ++ .../sp/sp.vcproj.old | 870 ++ .../sp/spDoc.cpp | 465 ++ .../sp/spDoc.h | 101 + .../sp/spView.cpp | 908 ++ .../sp/spView.h | 89 + source/WinFormApp/config.txt | 8 +- utils/AyaImport/Form1.cs | 1 + 262 files changed, 118078 insertions(+), 4 deletions(-) create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Common.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tlh create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tli create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MakeHelp.bat create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/MemDC.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ReadMe.txt create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Scdata.sc create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/UnitsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/UnitsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/UserPrefsDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/UserPrefsDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/UsersDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/UsersDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WODlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WODlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOHeaderDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOHeaderDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABLabour.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABLabour.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABParts.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABParts.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABProblem.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABProblem.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABSubRepair.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTABSubRepair.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTypesDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WOTypesDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WoTabLabourEntryDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/WoTabLabourEntryDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XTabCtrl.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XTabCtrl.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XXXOLDcrpe.hX create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XXXXOLDcrpe32m.libX create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XXXXcrpe.hX create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XXXXcrpe32m.libX create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XXXXpeplus.cppX create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XXXXpeplus.hX create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XferDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/XferDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ZTestDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ZTestDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ZonesDlg.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ZonesDlg.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/crviewer1.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/crviewer1.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ctschedule.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/ctschedule.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/default.pal create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/empty.sc create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/font.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/font.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzCombo.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzCombo.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzCurrencyFormatter.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzCurrencyFormatter.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzListBox.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzListBox.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzRightsButton.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/gzRightsButton.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/hlp/sc.hm create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/msado15.tlh create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/msado15.tli create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/picture.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/picture.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/HAND-L.CUR create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/Image2.bmp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/bitmap1.bmp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/bmp00001.bmp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/bmp00002.bmp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/icon1.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/icon2.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/icon3.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/icon4.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/icon5.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_dbut.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_evnt.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_main.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_mgr_.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_rpts.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_sets.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_snr_.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_srch.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/idr_stat.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/sc.bmp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/sp.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/sp.rc2 create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/spDoc.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/res/splash1.bmp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/resource.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/resource.hm create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sdi.ico create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.aps create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.clw create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.dep create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.dsp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.dsw create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.mak create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.ncb create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.opt create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.plg create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.rc create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.sln create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.sln.old create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.stt create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.suo create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.vcproj create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/sp.vcproj.old create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/spDoc.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/spDoc.h create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/spView.cpp create mode 100644 archive/ayanova 1.9.4 CE final release db schema 171/sp/spView.h diff --git a/AyaNovaSolution.sln b/AyaNovaSolution.sln index fdc70ea..181848e 100644 --- a/AyaNovaSolution.sln +++ b/AyaNovaSolution.sln @@ -462,6 +462,7 @@ Global {3EF693E1-F60E-4D0F-929C-CBF8BEF96F12}.ReleaseX86AyaNova|x86.Build.0 = Release|x86 {3A426361-1480-49A3-B596-53ABB98087F9}.Debug|.NET.ActiveCfg = Debug|Any CPU {3A426361-1480-49A3-B596-53ABB98087F9}.Debug|Any CPU.ActiveCfg = Debug|x86 + {3A426361-1480-49A3-B596-53ABB98087F9}.Debug|Any CPU.Build.0 = Debug|x86 {3A426361-1480-49A3-B596-53ABB98087F9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {3A426361-1480-49A3-B596-53ABB98087F9}.Debug|WBI.ActiveCfg = Debug|Any CPU {3A426361-1480-49A3-B596-53ABB98087F9}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.cpp new file mode 100644 index 0000000..412e5ff --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.cpp @@ -0,0 +1,1024 @@ +// ArasClientRequests.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ArasClientRequests.h" +#include "WOHeaderDlg.h" +#include ".\arasclientrequests.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CArasClientRequests dialog + + +CArasClientRequests::CArasClientRequests(CWnd* pParent /*=NULL*/) + : CDialog(CArasClientRequests::IDD, pParent) + , m_bReadOnly(false) +{ + //{{AFX_DATA_INIT(CArasClientRequests) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + + rsPrint=m_pApp->rsPool->GetRSPrint("CArasClientRequests rsPrint"); + + + rs=m_pApp->rsPool->GetRS("CArasClientRequests"); + + m_strCriteria="WHERE (((client_requests.workorderid)=0))"; + m_strOrderBy="ORDER BY client_requests.created DESC , client_requests.urgency, clients.company"; + + +} + +CArasClientRequests::~CArasClientRequests() +{ + +m_pApp->rsPool->ReleaseRS(&rsPrint->m_nID); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} +void CArasClientRequests::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CArasClientRequests) + DDX_Control(pDX, IDC_LBL_DETAILS, m_lblDetails); + DDX_Control(pDX, IDC_LBL_BRIEF, m_lblBrief); + DDX_Control(pDX, IDC_EDDETAILS, m_edDetails); + DDX_Control(pDX, IDC_EDBRIEF, m_edBrief); + DDX_Control(pDX, IDOK, m_btnOK); + DDX_Control(pDX, IDC_REPORT, m_rc); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CArasClientRequests, CDialog) + //{{AFX_MSG_MAP(CArasClientRequests) + ON_COMMAND(ID_ARAS_REQUESTS_CLOSE, OnArasRequestsClose) + ON_NOTIFY(RVN_COLUMNCLICK, IDC_REPORT, OnColumnClick) + ON_NOTIFY(RVN_ITEMDBCLICK, IDC_REPORT, OnRvnItemDbClick) + ON_NOTIFY(RVN_ITEMCLICK, IDC_REPORT, OnRvnItemClick) + ON_COMMAND(ID_ARAS_REQUESTS_MAKE_WORKORDER, OnArasRequestsMakeWorkorder) + ON_COMMAND(ID_ARAS_REQUESTS_REJECT, OnArasRequestsReject) + //}}AFX_MSG_MAP + ON_COMMAND(ID_ARAS_REQUESTS_REFRESH, OnArasRequestsRefresh) + ON_WM_TIMER() + ON_WM_INITMENUPOPUP() + ON_UPDATE_COMMAND_UI(ID_ARAS_REQUESTS_MAKE_WORKORDER, OnUpdateArasRequestsMakeWorkorder) + ON_UPDATE_COMMAND_UI(ID_ARAS_REQUESTS_REJECT, OnUpdateArasRequestsReject) + +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CArasClientRequests message handlers + +void CArasClientRequests::OnOK() +{} + +void CArasClientRequests::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu) +{ + ASSERT(pPopupMenu != NULL); + // Check the enabled state of various menu items. + + CCmdUI state; + state.m_pMenu = pPopupMenu; + ASSERT(state.m_pOther == NULL); + ASSERT(state.m_pParentMenu == NULL); + + // Determine if menu is popup in top-level menu and set m_pOther to + // it if so (m_pParentMenu == NULL indicates that it is secondary popup). + HMENU hParentMenu; + if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu) + state.m_pParentMenu = pPopupMenu; // Parent == child for tracking popup. + else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL) + { + CWnd* pParent = this; + // Child windows don't have menus--need to go to the top! + if (pParent != NULL && + (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL) + { + int nIndexMax = ::GetMenuItemCount(hParentMenu); + for (int nIndex = 0; nIndex < nIndexMax; nIndex++) + { + if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu) + { + // When popup is found, m_pParentMenu is containing menu. + state.m_pParentMenu = CMenu::FromHandle(hParentMenu); + break; + } + } + } + } + + state.m_nIndexMax = pPopupMenu->GetMenuItemCount(); + for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; + state.m_nIndex++) + { + state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex); + if (state.m_nID == 0) + continue; // Menu separator or invalid cmd - ignore it. + + ASSERT(state.m_pOther == NULL); + ASSERT(state.m_pMenu != NULL); + if (state.m_nID == (UINT)-1) + { + // Possibly a popup menu, route to first item of that popup. + state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex); + if (state.m_pSubMenu == NULL || + (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 || + state.m_nID == (UINT)-1) + { + continue; // First item of popup can't be routed to. + } + state.DoUpdate(this, TRUE); // Popups are never auto disabled. + } + else + { + // Normal menu item. + // Auto enable/disable if frame window has m_bAutoMenuEnable + // set and command is _not_ a system command. + state.m_pSubMenu = NULL; + state.DoUpdate(this, FALSE); + } + + // Adjust for menu deletions and additions. + UINT nCount = pPopupMenu->GetMenuItemCount(); + if (nCount < state.m_nIndexMax) + { + state.m_nIndex -= (state.m_nIndexMax - nCount); + while (state.m_nIndex < nCount && + pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID) + { + state.m_nIndex++; + } + } + state.m_nIndexMax = nCount; + } +} + +//DO NOTHING FOR NOW BUT LEFT IN CASE NEEDED IN FUTURE +void CArasClientRequests::OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + /* + CLoanersEditDlg d; + CString item=m_rc.GetItemText(lpnmrv->iItem,6); + d.SetRentalID(&item); + if(d.DoModal()==IDOK) + FillView(); + */ + + + } + + *pResult = FALSE; +} + +//clicked on an item to view it in fields on this screen +void CArasClientRequests::OnRvnItemClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + + m_lCurrentItem=atol(m_rc.GetItemText(lpnmrv->iItem,6)); + FillFields(); + + + } + + *pResult = FALSE; +} +void CArasClientRequests::Security() +{ + m_bReadOnly=false; + int x=m_pApp->Allowed(RARASREQUESTS,true); + + if(x==2)//read only + { + m_bReadOnly=true; + CMenu* pMenu=this->GetMenu(); + pMenu->EnableMenuItem(ID_ARAS_REQUESTS_MAKE_WORKORDER,MF_DISABLED | MF_GRAYED); + pMenu->EnableMenuItem(ID_ARAS_REQUESTS_REJECT,MF_DISABLED | MF_GRAYED); + +this->DrawMenuBar(); + + } + + + if(x==0) + { + m_bReadOnly=true; + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + +} + + +BOOL CArasClientRequests::OnInitDialog() +{ + CDialog::OnInitDialog(); + ShowWindow(SW_HIDE); + Security(); + CWaitCursor wait; + //defaults + + CString profile,q; + q.Format("SELECT users.aras_req_profile " + "FROM users WHERE (((users.id)=%u));",m_pApp->m_lusrID); + rs->Query(q); + rs->FetchField("aras_req_profile",&profile); + + + + m_ilReport.Create(IDB_BM2, 16, 1, RGB(255,0,255)); + m_rc.SetImageList(&m_ilReport); + + //ShowWindow(SW_MAXIMIZE); + + m_rc.InsertColor(0, 0x00C0D8C0); + m_rc.InsertColor(1, ::GetSysColor(COLOR_GRAYTEXT)); + m_rc.InsertColor(2, 0x00D0C0C0); + m_rc.InsertColor(3, 0x00804000); + + + RVCOLUMN rvc; + + rvc.nFormat = RVCF_TEXT|RVCF_EX_AUTOWIDTH|RVCF_EX_FIXEDWIDTH|RVCF_SUBITEM_IMAGE; + rvc.iImage = 1; + rvc.lpszText = _T("Urgency"); + rvc.iWidth = 60; + m_rc.DefineColumn(0, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Date"; + rvc.iWidth = 60; + m_rc.DefineColumn(1, &rvc); + + rvc.lpszText = "Client"; + rvc.iWidth = 60; + m_rc.DefineColumn(2, &rvc); + + rvc.lpszText = "User"; + rvc.iWidth = 60; + m_rc.DefineColumn(3, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Problem"; + rvc.iWidth = 60; + m_rc.DefineColumn(4, &rvc); + + rvc.lpszText = "Ref#"; + rvc.iWidth = 60; + m_rc.DefineColumn(5, &rvc); + + rvc.nFormat = RVCF_TEXT | RVCF_EX_FIXEDWIDTH; + rvc.lpszText = "id"; + rvc.iWidth = 0; + m_rc.DefineColumn(6, &rvc); + /* + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Ref"; + rvc.iWidth = 60; + m_rc.DefineColumn(7, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Desc."; + rvc.iWidth = 60; + m_rc.DefineColumn(8, &rvc); + */ + + //setup according to users preferences + if(!profile.IsEmpty()) + m_rc.GetProfile(&profile); + else + { + + //not needed when setting by pref + //but if there are no preferences then you would need it + + m_rc.ActivateColumn(0, 0); + m_rc.ActivateColumn(1, 1); + m_rc.ActivateColumn(2, 2); + m_rc.ActivateColumn(3, 3); + m_rc.ActivateColumn(4, 4); + m_rc.ActivateColumn(5, 5); + m_rc.ActivateColumn(6, 6); + //m_rc.ActivateColumn(7, 7); + //m_rc.ActivateColumn(8, 8); + + + } + + + + m_rc.ModifyStyle(0, RVS_SINGLESELECT); + //m_rc.ModifyStyle(0, RVS_SHOWCOLORALTERNATE); + + + //turn off the grids + m_rc.ModifyStyle(RVS_SHOWVGRID, 0); + m_rc.ModifyStyle(RVS_SHOWHGRID, 0); + + + + //retrieve the loaner items and display them + FillView(); + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + LayoutControls(); + + + //AUTOREFRESH TIMER + if(m_pApp->m_lSchedRefreshSecs!=0) + m_nTimer = SetTimer(2, 1000*m_pApp->m_lSchedRefreshSecs, 0); + + + //ShowWindow(SW_MAXIMIZE); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + + +void CArasClientRequests::FillView() +{ + CWaitCursor cw; + CString q; + COleDateTime dtDefault; + dtDefault.SetDate(1968,03,12); + int x=0; + q.Format("SELECT client_requests.*, clients.company, clients_aras.loginid " + "FROM (client_requests LEFT JOIN clients ON client_requests.clientlink = clients.id) LEFT JOIN clients_aras ON client_requests.requestor_id = clients_aras.id " + "%s %s;",m_strCriteria,m_strOrderBy); + + + + rs->Query(q); + //m_pApp->ShowStuff(q); + m_rc.DeleteAllItems(); + m_lCurrentItem=-1; + + if(rs->IsEmpty()) + return; + + + + + CString strData; + COleDateTime dtData; + long lData; + rs->MoveFirst(); + + + do + { + + + + //Set the look of the row and insert it + + //urgency + rs->FetchField("urgency",&lData); + RVITEM rvi; + rvi.iItem = x; + rvi.iSubItem = 0; + rvi.nMask = RVIM_IMAGE|RVIM_PREVIEW|RVIM_STATE|RVIM_LPARAM; + rvi.nState = 0; + rvi.nPreview = 0;//no preview necessary + + switch(lData) + { + case 0: + rvi.iImage=0;//green + break; + case 1://asap + rvi.iImage=1;//orange light + break; + case 2://emergency + rvi.iImage=2;//redlight + break; + } + + + rvi.lParam = x; + m_rc.InsertItem(&rvi); + + + //Date + rs->FetchField("created",&dtData); + strData=dtData.Format(); + rvi.iSubItem = 1; + rvi.nMask = RVIM_TEXT; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //Client + rs->FetchField("company",&strData); + rvi.iSubItem = 2; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //Requestor + rs->FetchField("loginid",&strData); + rvi.iSubItem = 3; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //problem + rs->FetchField("request",&strData); + rvi.iSubItem = 4; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //refnum + rs->FetchField("refnum",&strData); + rvi.iSubItem = 5; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + + //ID + rs->FetchField("id",&lData); + strData.Format("%u",lData); + rvi.iSubItem = 6; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + + + x++; + + }while(rs->MoveForward()); + + +} + +/* +//********************************************* +void CLoanersDlg::OnBtndone() +{ + CString profile,q; + //save to user prefs. + m_rc.WriteProfile(&profile); + q.Format("UPDATE users SET users.rentalprofile = \"%s\" " + "WHERE (((users.id)=%u));",profile,m_pApp->m_lusrID); + rs->Ex(q); + CDialog::OnOK(); + +} + +void CLoanersDlg::OnBtnadd() +{ + + CLoanersEditDlg d; + if(d.DoModal()==IDOK) + FillView(); + +} + +void CLoanersDlg::OnBtndelete() +{ + int x; + CString q,strID; + x=m_rc.GetFirstSelectedItem(); + if(x<0) return;//no selection + if(AfxMessageBox("Delete the highlighted item? Are you sure?",MB_YESNO)==IDNO) + return; + + strID=m_rc.GetItemText(x,6); + + q.Format("DELETE rentals.* FROM rentals WHERE (((rentals.id)=%s));",strID); + rs->Ex(q); + FillView(); + + +} + + +//SET CRITERIA FOR QUERY: +//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +void CLoanersDlg::OnCkanydate() +{ + m_nDateCriteriaX=0; + ShowDateFields(false); + Criteria(); +} + +void CLoanersDlg::OnCksentdate() +{ + ShowDateFields(true); + m_nDateCriteriaX=(1); + Criteria(); +} + +void CLoanersDlg::OnCkduedate() +{ + ShowDateFields(true); + m_nDateCriteriaX=(2); + Criteria(); +} + +void CLoanersDlg::OnCkreceiveddate() +{ + + ShowDateFields(true); + m_nDateCriteriaX=(3); + Criteria(); + +} + +void CLoanersDlg::OnDatetimechangeDtto(NMHDR* pNMHDR, LRESULT* pResult) +{ + + Criteria(); + *pResult = 0; +} + + +//set date and type criteria and rebuild list +void CLoanersDlg::Criteria() +{ + CString strFrom,strTo,strDatePart,strTypePart; + COleDateTime dtData; + m_ckAnyDate.SetCheck(FALSE); + m_ckDueDate.SetCheck(FALSE); + m_ckSentDate.SetCheck(FALSE); + m_ckShowAll.SetCheck(FALSE); + m_ckShowOut.SetCheck(FALSE); + m_ckShowReturned.SetCheck(FALSE); + m_ckReceivedDate.SetCheck(FALSE); + + m_dtFrom.GetTime(dtData); + strFrom=dtData.Format(_T("%m/%d/%Y")); + + m_dtTo.GetTime(dtData); + strTo=dtData.Format(_T("%m/%d/%Y")); + + m_strCriteria.Empty(); + + switch(m_nDateCriteriaX) + { + + case 1://sent date + m_ckSentDate.SetCheck(TRUE); + strDatePart.Format("((rentals.dateout) Between #%s# And #%s#)",strFrom,strTo); + break; + + case 2://due date + m_ckDueDate.SetCheck(TRUE); + strDatePart.Format("((rentals.datedue) Between #%s# And #%s#)",strFrom,strTo); + break; + + case 3://received date + m_ckReceivedDate.SetCheck(TRUE); + strDatePart.Format("((rentals.datereturn) Between #%s# And #%s#) AND ((rentals.returned)=True)",strFrom,strTo); + break; + + default://any date + strDatePart.Empty(); + m_ckAnyDate.SetCheck(TRUE); + break; + } + + + switch(m_nTypeCriteriaX) + { + + case 1://returned + strTypePart=" ((rentals.returned)=True)"; + + m_ckShowReturned.SetCheck(TRUE); + break; + + case 2://out + + m_ckShowOut.SetCheck(TRUE); + strTypePart=" ((rentals.returned)=False)"; + break; + + default://all + m_ckShowAll.SetCheck(TRUE); + strTypePart.Empty(); + break; + + } + + + + //No criteria + if(strDatePart.IsEmpty() && strTypePart.IsEmpty()) + { + m_strCriteria.Empty(); + FillView(); + return; + } + + //both criteria + if(!strDatePart.IsEmpty() && !strTypePart.IsEmpty() ) + { + + m_strCriteria=" WHERE (" + strTypePart + " AND " + strDatePart + ")"; + FillView(); + return; + } + + //only one criteria + if(!strTypePart.IsEmpty()) + { + m_strCriteria = " WHERE (" + strTypePart+ ")"; + FillView(); + return; + } + else + { + m_strCriteria=" WHERE (" + strDatePart+ ")"; + FillView(); + return; + } + + + + + +} + + +void CLoanersDlg::OnBtnprint() +{ + CString q; + COleDateTime dtDefault; + dtDefault.SetDate(1968,03,12); + q.Format("SELECT rentals.*, IIf(IsNull([sn]),[rentals].[description] & [parts].[description],[company_person] & " + "\" \" & [unitmodels].[description] & \" \" & [unitmodels].[model]) AS [desc], [rentals]![description] & " + "IIf(IsNull([parts]![partnumber]),\"\",\"part:\" & [parts]![partnumber]) & " + "IIf(IsNull([units]![sn]),\"\",\"unit:\" & [units]![sn]) AS item, [loanedto] & " + "IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) " + "AS rentor, Format([dateout],\"Short Date\") AS outdate, IIf([datedue]=#%s#,\"na\",Format([datedue], " + "\"Short Date\")) AS duedate, IIf([datereturn]=#%s#,\"Out\",Format([datereturn],\"Short Date\")) " + "AS retdate, DateDiff(\"d\",Now(),[datedue]) AS duedays " + "FROM ((((rentals LEFT JOIN clients ON rentals.clientlink = clients.id) LEFT JOIN " + "units ON rentals.unitlink = units.id) LEFT JOIN parts ON rentals.partlink = parts.id) " + "LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "%s %s;",dtDefault.Format(_T("%m/%d/%Y")), + dtDefault.Format(_T("%m/%d/%Y")),m_strCriteria,m_strOrderBy); + + rsPrint->QueryReadOnly(q); + if(rsPrint->IsEmpty()) + { + AfxMessageBox("Nothing to print!"); + return; + } + + + //m_pApp->CreateTTX("loaners.ttx",rsPrint->RecordSetPointer()); + m_pApp->PrintCMReport("loaners",rsPrint->RecordSetPointer()); + + +} +*/ + + +void CArasClientRequests::OnArasRequestsClose() +{ + KillTimer(2); + CString profile,q; + //save to user prefs. + m_rc.WriteProfile(&profile); + q.Format("UPDATE users SET users.aras_req_profile = \"%s\" " + "WHERE (((users.id)=%u));",profile,m_pApp->m_lusrID); + rs->Ex(q); + CDialog::OnOK(); + +} + + +//SET ORDER BY CLAUSE DEPENDING ON CLICK HERE +void CArasClientRequests::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + int x; + CString str; + CFlatHeaderCtrl* header; + header=m_rc.GetHeaderCtrl(); + + + //FIND CLICKED COLUMN + + str=header->m_szHotItemText; + + if(str=="Urgency"){x=0;goto OUTTAHERE;} + if(str=="Date"){x=1;goto OUTTAHERE;} + if(str=="Client"){x=2;goto OUTTAHERE;} + if(str=="User"){x=3;goto OUTTAHERE;} + if(str=="Problem"){x=4;goto OUTTAHERE;} + if(str=="Ref#"){x=5;goto OUTTAHERE;} + + + +OUTTAHERE: + + + bColumnSortAsc[x]=!bColumnSortAsc[x]; + switch(x) + {//DESC + case 0://urgency + m_strOrderBy="ORDER BY client_requests.urgency"; + break; + case 1://Date + m_strOrderBy="ORDER BY client_requests.created"; + break; + case 2://Client + m_strOrderBy="ORDER BY clients.company"; + break; + case 3://User + m_strOrderBy="ORDER BY clients_aras.loginid"; + break; + + case 4://Problem + m_strOrderBy="ORDER BY client_requests.request"; + break; + + case 5://Ref# + m_strOrderBy="ORDER BY client_requests.refnum"; + break; + + //case 6: is id number so not sortable + + + + + } + + if(!bColumnSortAsc[x]) + m_strOrderBy+=" DESC"; + + + header->SetSortColumn(header->GetHotIndex(),bColumnSortAsc[x]); + + *pResult = TRUE;//TRUE means we handled it here thanks anyway + FillView(); +} + + +//response to a single click on an item +//fill work request and details boxes +void CArasClientRequests::FillFields() +{ + if(m_lCurrentItem<1) return; + CString q; + long lUnitID=0; + + q.Format("SELECT client_requests.request, client_requests.probdetails, client_requests.unitid " + "FROM client_requests WHERE (((client_requests.id)=%u));",m_lCurrentItem); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + { + m_edBrief.SetWindowText("?"); + m_edDetails.SetWindowText("?"); + return; + } + + rs->FetchField("request",&q); + m_edBrief.SetWindowText(q); + + rs->FetchField("probdetails",&q); + m_edDetails.SetWindowText(q); + + + + +} + + +void CArasClientRequests::LayoutControls() +{ + + + int nLeft,nTop,nWidth,nHeight; + CRect rectCtl1,rectCtl2,rectDlg; + GetClientRect(rectDlg);//client area needed for movewindow + //get client screen coordinates + nLeft=rectDlg.left; + nTop=rectDlg.top; + nWidth=rectDlg.Width(); + nHeight=rectDlg.Height(); + + +//MOVE and RESIZE CONTROLS STARTING FROM BOTTOM UP + + //DETAILS EDIT BOX FIRST AS IS AT BOTTOM OF SCREEN + m_edDetails.GetWindowRect(rectCtl1); + m_edDetails.MoveWindow(nLeft,(nHeight-rectCtl1.Height()),nWidth,rectCtl1.Height(),TRUE); + + //Details Label + m_edDetails.GetWindowRect(rectCtl1); + ScreenToClient(rectCtl1);//convert whole screen co-ords to client area + m_lblDetails.GetWindowRect(rectCtl2); + ScreenToClient(rectCtl2);//convert whole screen co-ords to client area + m_lblDetails.MoveWindow(nLeft,(rectCtl1.top-rectCtl2.Height()),rectCtl2.Width(),rectCtl2.Height(),TRUE); + + //Brief box + m_lblDetails.GetWindowRect(rectCtl1); + ScreenToClient(rectCtl1);//convert whole screen co-ords to client area + m_edBrief.GetWindowRect(rectCtl2); + ScreenToClient(rectCtl2);//convert whole screen co-ords to client area + m_edBrief.MoveWindow(nLeft,(rectCtl1.top-rectCtl2.Height())-10,nWidth,rectCtl2.Height(),TRUE); + + //Brief Label + m_edBrief.GetWindowRect(rectCtl1); + ScreenToClient(rectCtl1);//convert whole screen co-ords to client area + m_lblBrief.GetWindowRect(rectCtl2); + ScreenToClient(rectCtl2);//convert whole screen co-ords to client area + m_lblBrief.MoveWindow(nLeft,(rectCtl1.top-rectCtl2.Height()),rectCtl2.Width(),rectCtl2.Height(),TRUE); + + //REPORT CONTROL + m_rc.GetWindowRect(rectCtl1);//windowrect is based on whole screen + m_lblBrief.GetWindowRect(rectCtl2);//based on upper left corner of screen not client area + ScreenToClient(rectCtl2);//convert whole screen co-ords to client area + nHeight=(rectDlg.top+rectCtl2.top)-10;//calculate height + m_rc.MoveWindow(rectDlg.left,rectDlg.top+10,rectDlg.Width(),nHeight-10,TRUE); + + + +} + + +void CArasClientRequests::OnArasRequestsMakeWorkorder() +{ + CString q; + long lWOID; + long lRequestedTech; + long lClient; + long lUnitID=0; + CString strBrief; + CString strDetails; + CString strRefNum; + + + COleDateTime dtNow; + dtNow=COleDateTime::GetCurrentTime(); + + //m_pApp->m_lDefNewWOStatus; + + if(m_lCurrentItem >=0)//-1 if clicked on invalid + { + + if(AfxMessageBox("Are you sure you want to accept this request\r\nand make a new workorder?",MB_YESNO)==IDNO) + return; + //Get data + q.Format("SELECT client_requests.* FROM client_requests WHERE (((client_requests.id)=%u));",m_lCurrentItem); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + { + AfxMessageBox("No can do...problem finding request record"); + return; + + } + + rs->FetchField("clientlink",&lClient); + rs->FetchField("request",&strBrief); + rs->FetchField("probdetails",&strDetails); + rs->FetchField("prefertech",&lRequestedTech); + rs->FetchField("refnum",&strRefNum); + rs->FetchField("unitid",&lUnitID); + + + //1.9.3.0 + if(strBrief.IsEmpty()) strBrief="Not provided by client"; + if(strDetails.IsEmpty()) strDetails="No details provided"; + if(strRefNum.IsEmpty()) strRefNum="na"; + + //Insert wo header + q.Format("INSERT INTO wo ( client, onsite, notes, assigntech, starttime, stoptime, creator, " + "created, ourref, status, clientrefnum ) " + "SELECT %u, %s, \"%s\",%i, #%s#, #%s#, %u, #%s#, \"%s\", %u, \"%s\";", + lClient, m_pApp->m_bDefOnsite ? "True" : "False", strBrief,lRequestedTech, + dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), + m_pApp->m_lusrID,dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),"Via ARAS",m_pApp->m_lDefNewWOStatus, strRefNum); + + if(!rs->Ex(q,&lWOID)) + { + AfxMessageBox("Problem inserting workorder header"); + return; + } + + + //insert wo problem + q.Format("INSERT INTO probs ( wolink, brief, notes, unit, creator, created ) " + "SELECT %u, \"%s\", \"%s\", %u, %u, #%s#;", + lWOID,strBrief,strDetails, lUnitID,m_pApp->m_lusrID,dtNow.Format(_T("%m/%d/%Y %H:%M:%S"))); + + if(!rs->Ex(q)) + { + AfxMessageBox("Problem inserting wo problem record"); + return; + } + + + + //update wo id number of request + q.Format("UPDATE client_requests SET client_requests.workorderid = %u " + "WHERE (((client_requests.id)=%u));",lWOID,m_lCurrentItem); + + if(!rs->Ex(q)) + { + AfxMessageBox("Problem updating request record with workorder ID number"); + + } + + + + //Show Workorder + rs->Close(); + m_pApp->m_bRefreshStatScreen=true;//bug bug, doesn't cause a refresh when return to STAT + CWOHeaderDlg wo; + q.Format("%u",lWOID); + wo.SetWorkorderID(q); + wo.DoModal(); + + + FillView(); + + } + +} + +void CArasClientRequests::OnArasRequestsReject() +{ +CString q; + if(m_lCurrentItem >=0)//-1 if clicked on invalid + { + + if(AfxMessageBox("Are you sure you want to reject this request?",MB_YESNO)==IDNO) + return; + + //They're sure..delete it. Well not actually, just set woid to -1 to exclude from view + q.Format("UPDATE client_requests SET client_requests.workorderid = -1 " + "WHERE (((client_requests.id)=%u));",m_lCurrentItem); + rs->Ex(q); + FillView(); + + } + +} + +void CArasClientRequests::OnArasRequestsRefresh() +{ + + KillTimer(2); + FillView(); + if(m_pApp->m_lSchedRefreshSecs!=0) + m_nTimer = SetTimer(2, 1000*m_pApp->m_lSchedRefreshSecs, 0); +} + +void CArasClientRequests::OnTimer(UINT nIDEvent) +{ + if(nIDEvent==2) + { + CWaitCursor cw; + KillTimer(2); + FillView(); + if(m_pApp->m_lSchedRefreshSecs!=0) + m_nTimer = SetTimer(2, 1000*m_pApp->m_lSchedRefreshSecs, 0); + + } + + CDialog::OnTimer(nIDEvent); +} + +void CArasClientRequests::OnUpdateArasRequestsMakeWorkorder(CCmdUI *pCmdUI) +{ + //pCmdUI->Enable(m_bReadOnly?FALSE:TRUE); +} + +void CArasClientRequests::OnUpdateArasRequestsReject(CCmdUI *pCmdUI) +{ + //pCmdUI->Enable(m_bReadOnly?FALSE:TRUE); +} + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.h new file mode 100644 index 0000000..7b4809b --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ArasClientRequests.h @@ -0,0 +1,84 @@ +#if !defined(AFX_ARASCLIENTREQUESTS_H__261CC395_46C3_4AB5_9BD8_2048C6FC98E0__INCLUDED_) +#define AFX_ARASCLIENTREQUESTS_H__261CC395_46C3_4AB5_9BD8_2048C6FC98E0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ArasClientRequests.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CArasClientRequests dialog +#include "ReportCtrl.h" +#include "gzrset.h" +class CArasClientRequests : public CDialog +{ +// Construction +public: + CArasClientRequests(CWnd* pParent = NULL); // standard constructor +BOOL bColumnSortAsc[7];//<---COLUMN COUNT HERE MUST BE UPDATED WHEN NEW ONES ADDED + CString m_strOrderBy; + void Security(); + ~CArasClientRequests(); + + CString m_strCriteria; + void Criteria(); + void FillView(); +// Dialog Data + //{{AFX_DATA(CArasClientRequests) + enum { IDD = IDD_ARAS_CLIENT_REQUESTS }; + CStatic m_lblDetails; + CStatic m_lblBrief; + CEdit m_edDetails; + CEdit m_edBrief; + CButton m_btnOK; + CReportCtrl m_rc; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CArasClientRequests) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CArasClientRequests) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnArasRequestsClose(); + afx_msg void OnArasRequestsMakeWorkorder(); + afx_msg void OnArasRequestsReject(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + int m_nTimer; + long m_lCurrentItem; + void LayoutControls(); + void FillFields(); + GZRset* rs; +GZRset* rsPrint; + CSpApp* m_pApp; + void OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnRvnItemClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult); + CImageList m_ilReport; +public: + afx_msg void OnArasRequestsRefresh(); + afx_msg void OnTimer(UINT nIDEvent); + void OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu); + afx_msg void OnUpdateArasRequestsMakeWorkorder(CCmdUI *pCmdUI); + afx_msg void OnUpdateArasRequestsReject(CCmdUI *pCmdUI); + // used to limit access for security + bool m_bReadOnly; + afx_msg void OnArasRequestsAccept(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ARASCLIENTREQUESTS_H__261CC395_46C3_4AB5_9BD8_2048C6FC98E0__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.cpp new file mode 100644 index 0000000..257a6e9 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.cpp @@ -0,0 +1,593 @@ +// AyaSysInfo.cpp: implementation of the CAyaSysInfo class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "AyaSysInfo.h" +#include "crc32static.h" + + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +#define MAXNETLOOP 20 +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CAyaSysInfo::CAyaSysInfo() +{ + +} + +CAyaSysInfo::~CAyaSysInfo() +{ + +} + + +//return basic system information +CString CAyaSysInfo::GetSysInfo() +{ + CString strTemp,strReturn; + DWORD dwWhatever=255; + char chBuff[255]; + char ch; + int x=0; + long lDriveType; + memset(chBuff,0,sizeof(int)); + + strReturn.Empty(); + strReturn="SYSTEM INFORMATION:\r\n"; + //computer name + if(GetComputerName(chBuff,&dwWhatever)) + strTemp.Format("Computer name: [%s]\r\n",chBuff); + strReturn+=strTemp; + + strReturn += GetOpSysVersion() + "\r\n"; + + + + //local drive letters + if(GetLogicalDriveStrings(255,chBuff)) + { + strReturn+="Drive information:\r\n"; + strTemp.Empty(); + ch=chBuff[x]; + do{ + + strTemp+=ch; + strTemp+=":\\"; + lDriveType=GetDriveType(strTemp); + + switch (lDriveType) + { + case DRIVE_NO_ROOT_DIR: + strTemp+=" - No root path determinable. Invalid\r\n"; + break; + case DRIVE_REMOVABLE: + strTemp+=" - Removable drive\r\n"; + break; + case DRIVE_FIXED: + strTemp+=" - Fixed drive\r\n"; + break; + case DRIVE_REMOTE: + strTemp+=" - remote network drive\r\n"; + break; + case DRIVE_CDROM: + strTemp+=" - CDROM drive\r\n"; + break; + case DRIVE_RAMDISK: + strTemp+=" - RAM drive\r\n"; + break; + default: + strTemp+=" - Unknown type\r\n"; + + + } + strReturn+= "\t" + strTemp; + strTemp.Empty(); + x+=4; + ch=chBuff[x]; + }while(ch!=0); + + + } + + //memory + strReturn+="\r\n"; + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + + strTemp.Format("RAM: %ld kb of physical memory\r\n",ms.dwTotalPhys/1024); + strReturn+=strTemp; + + strTemp.Format("RAM: %ld percent of memory is in use\r\n",ms.dwMemoryLoad); + strReturn+=strTemp; + + return strReturn; +} + + +//Get locale information +CString CAyaSysInfo::GetLocalInfo() +{ + CString strTemp,strReturn; + char chBuff[50]; + memset(chBuff,0,sizeof(int)); + + strReturn.Empty(); + strReturn="LOCALE INFORMATION:\r\n"; + + //short date format + if(GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SSHORTDATE,chBuff,50)) + strTemp.Format("Short date format: [%s]\r\n",chBuff); + strReturn+=strTemp; + + //Currency symbol + if(GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SCURRENCY,chBuff,50)) + strTemp.Format("Currency symbol: [%s]\r\n",chBuff); + strReturn+=strTemp; + + //language + if(GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SENGLANGUAGE ,chBuff,50)) + strTemp.Format("Language: [%s]\r\n",chBuff); + strReturn+=strTemp; + + //Country + if(GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SCOUNTRY,chBuff,50)) + strTemp.Format("Country: [%s]\r\n",chBuff); + strReturn+=strTemp; + + return strReturn; +} + + +//Get info from every function and return it all +CString CAyaSysInfo::GetAllInfo() +{ + CString strReturn; + strReturn.Empty(); + + //Local info + strReturn=GetLocalInfo(); + strReturn+="\r\n" + GetSysInfo(); + + return strReturn; +} + + + +//os version info +CString CAyaSysInfo::GetOpSysVersion() +{ + CString strReturn, strTemp; + strReturn="Operating system: ["; + OSVERSIONINFOEX osvi; + BOOL bOsVersionInfoEx; + + // Try calling GetVersionEx using the OSVERSIONINFOEX structure, + // which is supported on Windows 2000. + // + // If that fails, try using the OSVERSIONINFO structure. + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) ) + { + // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. + + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) + return "OS VERSION UNKNOWN"; + } + + switch (osvi.dwPlatformId) + { + case VER_PLATFORM_WIN32_NT: + + if(osvi.dwMajorVersion < 4) + strReturn+="Windows NT pre v4.0 "; + + if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion== 0) + strReturn+="Windows NT 4.0 "; + + if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion== 0) + strReturn+="Windows 2000 "; + + if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion== 1) + strReturn+="Windows XP "; + + if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion== 2) + strReturn+="Windows server 2003 family "; + + // Test for specific product on Windows NT 4.0 SP6 and later. + if( bOsVersionInfoEx ) + { + // Test for the workstation type. + if ( osvi.wProductType == VER_NT_WORKSTATION ) + { + if( osvi.dwMajorVersion == 4 ) + strReturn+= "Workstation 4.0 " ; + else if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) + strReturn+="Home Edition "; + else + strReturn+="Professional "; + } + + // Test for the server type. + else if ( osvi.wProductType == VER_NT_SERVER ) + { + if( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) + { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + strReturn+="Datacenter Edition " ; + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strReturn+="Enterprise Edition "; + else if ( osvi.wSuiteMask == VER_SUITE_BLADE ) + strReturn+="Web Edition "; + else + strReturn+="Standard Edition "; + } + + else if( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) + { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + strReturn+="Datacenter Server "; + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strReturn+="Advanced Server "; + else + strReturn+="Server "; + } + + else // Windows NT 4.0 + { + if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + strReturn+="Server 4.0, Enterprise Edition "; + else + strReturn+="Server 4.0 "; + } + } + } + + + strTemp.Format("%s",osvi.szCSDVersion); + strTemp.TrimLeft(" "); + if(strTemp.IsEmpty()) + strTemp="n/a"; + strReturn+= " Version: " + strTemp; + + + + + break; + + case VER_PLATFORM_WIN32_WINDOWS: + if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion== 0) + strReturn+="Windows 95"; + + if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion== 10) + strReturn+="Windows 98"; + + if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion== 90) + strReturn+="Windows ME"; + + strTemp.Format("%s",osvi.szCSDVersion); + strTemp.TrimLeft(" "); + if(strTemp.IsEmpty()) + strTemp="n/a"; + strReturn+= " Version: " + strTemp; + + + break; + + case VER_PLATFORM_WIN32s: + + strReturn+="Microsoft Win32s \r\n"; + break; + } + strReturn+="]\r\n"; + return strReturn; +} + +//usage: pass in a path or file name +//returns all files if just a path +//or details on the one file if a single file +//with crc32 checksums +//does *not* recurse +CString CAyaSysInfo::GetFilesInfo(CString strStartPath) +{ + CString strReturn, strTemp, strSize; + CFileFind ff; + CTime ct,wt; + CCrc32Static crc; + DWORD dwcheck=0; + + + + unsigned int uiFileSize; + bool bGotPath=false; + BOOL bWorking = ff.FindFile(strStartPath); + + //Change 02/20/2003 + if(!bWorking) + strReturn.Format("File not found",strStartPath); + + while (bWorking) + { + bWorking = ff.FindNextFile(); + + // skip . and .. files; otherwise, we'd + // recurse infinitely! + + if (ff.IsDots()) + continue; + if(ff.IsDirectory()) + { if(bGotPath==false) + { + strTemp.Format("\r\n",ff.GetRoot()); + strReturn+=strTemp; + bGotPath=true; + } + ff.GetCreationTime(ct); + strTemp.Format("\r\n\\%-45s\t%s\t\r\n",ff.GetFileName(),ct.Format("%b.%d.%Y %H:%M:%S")); + strReturn+=strTemp; + + } + else //it's a file, get file info + { + if(bGotPath==false) + { + strTemp.Format("\r\n",ff.GetRoot()); + strReturn+=strTemp; + bGotPath=true; + } + ff.GetCreationTime(ct); + ff.GetLastWriteTime(wt); + uiFileSize=(UINT)ff.GetLength(); + if(uiFileSize < 1024) + strSize.Format("%u bytes",uiFileSize); + else + { + //convert to KB + uiFileSize=uiFileSize/1024; + strSize.Format("%u KB",uiFileSize); + + } + + crc.FileCrc32Assembly(ff.GetFilePath(),dwcheck); + + strTemp.Format("%-35s\tC:%-15s\tW:%-15s\t%-8s\tcrc: %08x\r\n",ff.GetFileName(), + ct.Format("%b.%d.%Y %H:%M:%S"),wt.Format("%b.%d.%Y %H:%M:%S"),strSize,dwcheck); + strReturn+=strTemp; + + + } + + + } + + ff.Close(); + return strReturn; + +} + + + +/* + + CString CAyaSysInfo::GetNetworkResources(LPNETRESOURCE lpnr) + { + m_lLoop++; + m_lDepth++; + if(m_lLoop>MAXNETLOOP) + return "Overflow"; + CString strTemp, strReturn, strLastResource, strThisResource; + + + DWORD dwResult, dwResultEnum; + HANDLE hEnum; + DWORD cbBuffer = 16384; // 16K is a good size + DWORD cEntries = -1; // enumerate all possible entries + LPNETRESOURCE lpnrLocal; // pointer to enumerated structures + DWORD i; + + + // + // Call the WNetOpenEnum function to begin the enumeration. + // + dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, // all network resources + RESOURCETYPE_ANY, // all resources + 0, // enumerate all resources + lpnr, // NULL first time the function is called + &hEnum); // handle to the resource + + if (dwResult != NO_ERROR) + { + // + // Process errors with an application-defined error handler. + // + //NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetOpenEnum"); + return "Network resources - FAIL"; + } + // + // Call the GlobalAlloc function to allocate resources. + // + lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer); + + do + { + //strReturn+="Calling Enumerate from master...\r\n"; + // + // Initialize the buffer. + // + ZeroMemory(lpnrLocal, cbBuffer); + // + // Call the WNetEnumResource function to continue + // the enumeration. + // + dwResultEnum = WNetEnumResource(hEnum, // resource handle + &cEntries, // defined locally as -1 + lpnrLocal, // LPNETRESOURCE + &cbBuffer); // buffer size + // + // If the call succeeds, loop through the structures. + // + strTemp.Format("\r\n\tdwResult=%i, loop=%u, CEntries=%i",dwResultEnum,m_lLoop, cEntries); + strReturn+=strTemp; + if (dwResultEnum == NO_ERROR) + { + strReturn+="\r\n\tNoError\r\n"; + //strTemp.Format("CEntries=%i\r\n",cEntries); + //strReturn+=strTemp; + for(i = 0; i < cEntries; i++) + { + + + if(RESOURCEUSAGE_CONTAINER != (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER)) + { + if(i==0) + { + strTemp.Format("%s",lpnrLocal[i].lpProvider); + if(!strTemp.IsEmpty() && strTemp!="(null)") + strReturn+= "Provider: " + strTemp + ""; + } + + strTemp.Format("%s",lpnrLocal[i].lpLocalName); + if(!strTemp.IsEmpty() && strTemp!="(null)") + strReturn+= "Local name: " + strTemp + " "; + + strTemp.Format("%s",lpnrLocal[i].lpRemoteName); + if(!strTemp.IsEmpty() && strTemp!="(null)") + { + strReturn+= "\r\n\tRemote name: " + strTemp + " "; + strThisResource=strTemp; + } + strTemp.Format("%s",lpnrLocal[i].lpComment); + if(!strTemp.IsEmpty() && strTemp!="(null)") + strReturn+= " (Comment: " + strTemp + ")\r\n"; + + } + // If the NETRESOURCE structure represents a container resource, + // call the EnumerateFunc function recursively. + + if(RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER)) + if(lpnrLocal[i].lpProvider!="HP Network Printers") + strReturn+=GetNetworkResources(&lpnrLocal[i]); + + + + } + } + // Process errors. + // + + } + // + // End do. + // + while(dwResultEnum != ERROR_NO_MORE_ITEMS); + // + // Call the GlobalFree function to free the memory. + // + GlobalFree((HGLOBAL)lpnrLocal); + // + // Call WNetCloseEnum to end the enumeration. + // + dwResult = WNetCloseEnum(hEnum); + + if(dwResult != NO_ERROR) + { + // + // Process errors. + // + //NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetCloseEnum"); + return "Network resources - FAIL"; + } + + //returning + // m_lLoop--; + m_lDepth--; + strTemp.Format("\r\nDepth=%u\r\n",m_lDepth); + strReturn+=strTemp; + return strReturn; + + + } +*/ +/* +//usage: pass in a path or file name +//returns all files if just a path +//or details on the one file if a single file +//does *not* recurse +CString CAyaSysInfo::GetFilesInfo(CString strStartPath) +{ + CString strReturn, strTemp, strSize; + CFileFind ff; + CTime ct,wt; + unsigned int uiFileSize; + bool bGotPath=false; + BOOL bWorking = ff.FindFile(strStartPath); + + while (bWorking) + { + bWorking = ff.FindNextFile(); + + // skip . and .. files; otherwise, we'd + // recur infinitely! + + if (ff.IsDots()) + continue; + if(ff.IsDirectory()) + { if(bGotPath==false) + { + strTemp.Format("\r\n",ff.GetRoot()); + strReturn+=strTemp; + bGotPath=true; + } + ff.GetCreationTime(ct); + strTemp.Format("%-45s\t%s\t\r\n",ff.GetFileName(),ct.Format("%b.%d.%Y %H:%M:%S")); + strReturn+=strTemp; + + } + else //it's a file, get file info + { + if(bGotPath==false) + { + strTemp.Format("\r\n",ff.GetRoot()); + strReturn+=strTemp; + bGotPath=true; + } + ff.GetCreationTime(ct); + ff.GetLastWriteTime(wt); + uiFileSize=ff.GetLength(); + if(uiFileSize < 1024) + strSize.Format("%u bytes",uiFileSize); + else + { + //convert to KB + uiFileSize=uiFileSize/1024; + strSize.Format("%u KB",uiFileSize); + + } + + + strTemp.Format("%-45s\tC:%s\tW:%s\t%s\r\n",ff.GetFileName(), + ct.Format("%b.%d.%Y %H:%M:%S"),wt.Format("%b.%d.%Y %H:%M:%S"),strSize); + strReturn+=strTemp; + + + } + + + } + + ff.Close(); + return strReturn; + +} +*/ \ No newline at end of file diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.h new file mode 100644 index 0000000..8ec3032 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/AyaSysInfo.h @@ -0,0 +1,30 @@ +// AyaSysInfo.h: interface for the CAyaSysInfo class. +// +////////////////////////////////////////////////////////////////////// + + +#if !defined(AFX_AYASYSINFO_H__E479F057_0490_40CF_B505_663BE21084D4__INCLUDED_) +#define AFX_AYASYSINFO_H__E479F057_0490_40CF_B505_663BE21084D4__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CAyaSysInfo +{ +public: + CString GetFilesInfo(CString strStartPath); + long m_lLoop; + long m_lDepth; + + //CString GetNetworkResources(LPNETRESOURCE lpnr); + CString GetAllInfo(); + CString GetLocalInfo(); + CString GetSysInfo(); + CString GetOpSysVersion(); + CAyaSysInfo(); + virtual ~CAyaSysInfo(); + +}; + +#endif // !defined(AFX_AYASYSINFO_H__E479F057_0490_40CF_B505_663BE21084D4__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.cpp new file mode 100644 index 0000000..dd4d636 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.cpp @@ -0,0 +1,425 @@ +// CheckComboBox.cpp +// +// Written by Magnus Egelberg (magnus.egelberg@lundalogik.se) +// +// Copyright (C) 1999, Lundalogik AB, Sweden. All rights reserved. +// +// + +#include "stdafx.h" +//#include "CheckCombo.h" +#include "CheckComboBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static WNDPROC m_pWndProc = 0; +static CCheckComboBox *m_pComboBox = 0; + + +BEGIN_MESSAGE_MAP(CCheckComboBox, CComboBox) + //{{AFX_MSG_MAP(CCheckComboBox) + ON_MESSAGE(WM_CTLCOLORLISTBOX, OnCtlColorListBox) + ON_MESSAGE(WM_GETTEXT, OnGetText) + ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength) + ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropDown) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +// +// The subclassed COMBOLBOX message handler +// +extern "C" LRESULT FAR PASCAL ComboBoxListBoxProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + + switch (nMsg) { + + + case WM_RBUTTONDOWN: { + // If you want to select all/unselect all using the + // right button, remove this ifdef. Personally, I don't really like it + #if FALSE + + if (m_pComboBox != 0) { + INT nCount = m_pComboBox->GetCount(); + INT nSelCount = 0; + + for (INT i = 0; i < nCount; i++) { + if (m_pComboBox->GetCheck(i)) + nSelCount++; + } + + + m_pComboBox->SelectAll(nSelCount != nCount); + + // Make sure to invalidate this window as well + InvalidateRect(hWnd, 0, FALSE); + m_pComboBox->GetParent()->SendMessage(WM_COMMAND, MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd); + + } + #endif + + break; + } + + // Make the combobox always return -1 as the current selection. This + // causes the lpDrawItemStruct->itemID in DrawItem() to be -1 + // when the always-visible-portion of the combo is drawn + case LB_GETCURSEL: { + return -1; + } + + + case WM_CHAR: { + if (wParam == VK_SPACE) { + // Get the current selection + INT nIndex = CallWindowProcA(m_pWndProc, hWnd, LB_GETCURSEL, wParam, lParam); + + CRect rcItem; + SendMessage(hWnd, LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem); + InvalidateRect(hWnd, rcItem, FALSE); + + // Invert the check mark + m_pComboBox->SetCheck(nIndex, !m_pComboBox->GetCheck(nIndex)); + + // Notify that selection has changed + m_pComboBox->GetParent()->SendMessage(WM_COMMAND, MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd); + return 0; + } + + break; + } + + + case WM_LBUTTONDOWN: { + + CRect rcClient; + GetClientRect(hWnd, rcClient); + + CPoint pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + + + if (PtInRect(rcClient, pt)) { + INT nItemHeight = SendMessage(hWnd, LB_GETITEMHEIGHT, 0, 0); + INT nTopIndex = SendMessage(hWnd, LB_GETTOPINDEX, 0, 0); + + // Compute which index to check/uncheck + INT nIndex = nTopIndex + pt.y / nItemHeight; + + CRect rcItem; + SendMessage(hWnd, LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem); + + if (PtInRect(rcItem, pt)) { + // Invalidate this window + InvalidateRect(hWnd, rcItem, FALSE); + m_pComboBox->SetCheck(nIndex, !m_pComboBox->GetCheck(nIndex)); + + // Notify that selection has changed + m_pComboBox->GetParent()->SendMessage(WM_COMMAND, MAKELONG(GetWindowLong(m_pComboBox->m_hWnd, GWL_ID), CBN_SELCHANGE), (LPARAM)m_pComboBox->m_hWnd); + + + } + } + + // Do the default handling now (such as close the popup + // window when clicked outside) + break; + } + + case WM_LBUTTONUP: { + // Don't do anything here. This causes the combobox popup + // windows to remain open after a selection has been made + return 0; + } + } + + return CallWindowProc(m_pWndProc, hWnd, nMsg, wParam, lParam); +} + + + + + +CCheckComboBox::CCheckComboBox() +{ + m_hListBox = 0; + m_bTextUpdated = FALSE; + m_bItemHeightSet = FALSE; +} + + +CCheckComboBox::~CCheckComboBox() +{ +} + + +BOOL CCheckComboBox::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) +{ + + // Remove the CBS_SIMPLE and CBS_DROPDOWN styles and add the one I'm designed for + dwStyle &= ~0xF; + dwStyle |= CBS_DROPDOWNLIST; + + // Make sure to use the CBS_OWNERDRAWVARIABLE style + dwStyle |= CBS_OWNERDRAWVARIABLE; + + // Use default strings. We need the itemdata to store checkmarks + dwStyle |= CBS_HASSTRINGS; + + return CComboBox::Create(dwStyle, rect, pParentWnd, nID); +} + + +LRESULT CCheckComboBox::OnCtlColorListBox(WPARAM wParam, LPARAM lParam) +{ + // If the listbox hasn't been subclassed yet, do so... + if (m_hListBox == 0) { + HWND hWnd = (HWND)lParam; + + if (hWnd != 0 && hWnd != m_hWnd) { + // Save the listbox handle + m_hListBox = hWnd; + + // Do the subclassing + m_pWndProc = (WNDPROC)GetWindowLong(m_hListBox, GWL_WNDPROC); + SetWindowLong(m_hListBox, GWL_WNDPROC, (LONG)ComboBoxListBoxProc); + } + } + + + return DefWindowProc(WM_CTLCOLORLISTBOX, wParam, lParam); +} + + +void CCheckComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + HDC dc = lpDrawItemStruct->hDC; + + CRect rcBitmap = lpDrawItemStruct->rcItem; + CRect rcText = lpDrawItemStruct->rcItem; + + CString strText; + + // 0 - No check, 1 - Empty check, 2 - Checked + INT nCheck = 0; + + // Check if we are drawing the static portion of the combobox + if ((LONG)lpDrawItemStruct->itemID < 0) { + // Make sure the m_strText member is updated + RecalcText(); + + // Get the text + strText = m_strText; + + // Don't draw any boxes on this item + nCheck = 0; + } + + // Otherwise it is one of the items + else { + GetLBText(lpDrawItemStruct->itemID, strText); + nCheck = 1 + (GetItemData(lpDrawItemStruct->itemID) != 0); + + TEXTMETRIC metrics; + GetTextMetrics(dc, &metrics); + + rcBitmap.left = 0; + rcBitmap.right = rcBitmap.left + metrics.tmHeight + metrics.tmExternalLeading + 6; + rcBitmap.top += 1; + rcBitmap.bottom -= 1; + + rcText.left = rcBitmap.right; + } + + + + if (nCheck > 0) { + SetBkColor(dc, GetSysColor(COLOR_WINDOW)); + SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT)); + + UINT nState = DFCS_BUTTONCHECK; + + if (nCheck > 1) + nState |= DFCS_CHECKED; + + // Draw the checkmark using DrawFrameControl + DrawFrameControl(dc, rcBitmap, DFC_BUTTON, nState); + } + + if (lpDrawItemStruct->itemState & ODS_SELECTED) { + SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); + SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else { + SetBkColor(dc, GetSysColor(COLOR_WINDOW)); + SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT)); + } + + // Erase and draw + ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rcText, 0, 0, 0); + DrawText(dc, ' ' + strText, strText.GetLength() + 1, &rcText, DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS); + + if ((lpDrawItemStruct->itemState & (ODS_FOCUS|ODS_SELECTED)) == (ODS_FOCUS|ODS_SELECTED)) + DrawFocusRect(dc, &rcText); + +} + + +void CCheckComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) +{ + CClientDC dc(this); + CFont *pFont = dc.SelectObject(GetFont()); + + if (pFont != 0) { + + TEXTMETRIC metrics; + dc.GetTextMetrics(&metrics); + + lpMeasureItemStruct->itemHeight = metrics.tmHeight + metrics.tmExternalLeading; + + // An extra height of 2 looks good I think. + // Otherwise the list looks a bit crowded... + lpMeasureItemStruct->itemHeight += 2; + + + // This is needed since the WM_MEASUREITEM message is sent before + // MFC hooks everything up if used in i dialog. So adjust the + // static portion of the combo box now + if (!m_bItemHeightSet) { + m_bItemHeightSet = TRUE; + SetItemHeight(-1, lpMeasureItemStruct->itemHeight); + } + + dc.SelectObject(pFont); + } +} + + +// +// Make sure the combobox window handle is updated since +// there may be many CCheckComboBox windows active +// +void CCheckComboBox::OnDropDown() +{ + m_pComboBox = this; + +} + + +// +// Selects/unselects all items in the list +// +void CCheckComboBox::SelectAll(BOOL bCheck) +{ + INT nCount = GetCount(); + + for (INT i = 0; i < nCount; i++) + SetCheck(i, bCheck); + +} + + +// +// By adding this message handler, we may use CWnd::GetText() +// +LRESULT CCheckComboBox::OnGetText(WPARAM wParam, LPARAM lParam) +{ + // Make sure the text is updated + RecalcText(); + + if (lParam == 0) + return 0; + + // Copy the 'fake' window text + lstrcpyn((LPSTR)lParam, m_strText, (INT)wParam); + return m_strText.GetLength(); +} + + +// +// By adding this message handler, we may use CWnd::GetTextLength() +// +LRESULT CCheckComboBox::OnGetTextLength(WPARAM, LPARAM) +{ + // Make sure the text is updated + RecalcText(); + return m_strText.GetLength(); +} + + +// +// This routine steps thru all the items and builds +// a string containing the checked items +// +void CCheckComboBox::RecalcText() +{ + if (!m_bTextUpdated) { + CString strText; + + // Get the list count + INT nCount = GetCount(); + + // Get the list separator + TCHAR szBuffer[10] = {0}; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, szBuffer, sizeof(szBuffer)); + + CString strSeparator = szBuffer; + + // If none found, the the ';' + if (strSeparator.GetLength() == 0) + strSeparator = ';'; + + // Trim extra spaces + strSeparator.TrimRight(); + + // And one... + strSeparator += ' '; + + for (INT i = 0; i < nCount; i++) { + + if (GetItemData(i)) { + CString strItem; + GetLBText(i, strItem); + + if (!strText.IsEmpty()) + strText += strSeparator; + + strText += strItem; + } + } + + // Set the text + m_strText = strText; + + m_bTextUpdated = TRUE; + } +} + +INT CCheckComboBox::SetCheck(INT nIndex, BOOL bFlag) +{ + INT nResult = SetItemData(nIndex, bFlag); + + if (nResult < 0) + return nResult; + + // Signal that the text need updating + m_bTextUpdated = FALSE; + + // Redraw the window + Invalidate(FALSE); + + return nResult; +} + +BOOL CCheckComboBox::GetCheck(INT nIndex) +{ + return GetItemData(nIndex); +} + + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.h new file mode 100644 index 0000000..18ba1ad --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/CheckComboBox.h @@ -0,0 +1,63 @@ +#if !defined(AFX_CHECKCOMBOBOX_H__66750D93_95DB_11D3_9325_444553540000__INCLUDED_) +#define AFX_CHECKCOMBOBOX_H__66750D93_95DB_11D3_9325_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +class CCheckComboBox : public CComboBox +{ +public: + CCheckComboBox(); + virtual ~CCheckComboBox(); + + BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID); + + // Selects all/unselects the specified item + INT SetCheck(INT nIndex, BOOL bFlag); + + // Returns checked state + BOOL GetCheck(INT nIndex); + + // Selects all/unselects all + void SelectAll(BOOL bCheck = TRUE); + +protected: + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCheckComboBox) + protected: + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); + //}}AFX_VIRTUAL + + //{{AFX_MSG(CCheckComboBox) + afx_msg LRESULT OnCtlColorListBox(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnGetText(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnGetTextLength(WPARAM wParam, LPARAM lParam); + afx_msg void OnDropDown(); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() + +protected: + // Routine to update the text + void RecalcText(); + + // The subclassed COMBOLBOX window (notice the 'L') + HWND m_hListBox; + + // The string containing the text to display + CString m_strText; + BOOL m_bTextUpdated; + + // A flag used in MeasureItem, see comments there + BOOL m_bItemHeightSet; +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHECKCOMBOBOX_H__66750D93_95DB_11D3_9325_444553540000__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.cpp new file mode 100644 index 0000000..6f0a6ee --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.cpp @@ -0,0 +1,2570 @@ +// ClientsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ClientsDlg.h" +#include "ClientsRA.h" +#include "ZonesDlg.h" +#include "contractsdlg.h" +#include "PM.h" +#include "ContactsViewDlg.h" +#include "ConsolidateDlg.h" +#include "UnitsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CClientsDlg dialog + + +CClientsDlg::CClientsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CClientsDlg::IDD, pParent) +, m_bPMAllowed(false) +, m_strDefaultCity(_T("")) +, m_strDefaultStateProv(_T("")) +, m_strDefaultPostal(_T("")) +, m_strDefaultCountry(_T("")) +{ + //{{AFX_DATA_INIT(CClientsDlg) + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Clients dialog"); + rs->SetConnect(m_pApp->strConnectString); + rs2=new GZRset("Error: Clients dialog defaults r.s."); + rs2->SetConnect(m_pApp->strConnectString); + */ + + rs=m_pApp->rsPool->GetRS("CClientsDlg (RS)"); + rs2=m_pApp->rsPool->GetRS("CClientsDlg (RS2)"); + + m_pstrReturnValue=NULL; + + m_strForceSelection.Empty(); + + //Added 8/28/00 prompt on very first edit + //and as long as you say yes to edit prompt + //used by savefield functions + m_bEditPrompt=true; + + //v1.9.4.5 + lPreferredTech=0; +} + +CClientsDlg::~CClientsDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs2->m_nID); +} + +void CClientsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CClientsDlg) + DDX_Control(pDX, IDC_BTNNOTES, m_btnNotes); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_EDACCTNUM, m_edAcctNum); + DDX_Control(pDX, IDC_CBDEFTRAVEL, m_cbDefTravelRate); + DDX_Control(pDX, IDC_CBDEFRATE, m_cbRate); + DDX_Control(pDX, IDC_BTNPM, m_btnPM); + DDX_Control(pDX, IDC_HISTORY, m_lblHist); + DDX_Control(pDX, IDC_ZONELABEL, m_lblZone); + DDX_Control(pDX, IDC_ZONE, m_cbZone); + DDX_Control(pDX, IDC_BILLHEAD, m_ckBillHead); + DDX_Control(pDX, IDC_ALERTLABEL, m_lblAlert); + DDX_Control(pDX, IDC_ALERT, m_edAlert); + DDX_Control(pDX, IDC_TECHNOTESLABEL, m_lblTechNotes); + DDX_Control(pDX, IDC_TECHNOTES, m_edTechNotes); + DDX_Control(pDX, IDC_STREETLABEL, m_lblStreet); + DDX_Control(pDX, IDC_STREET, m_edStreet); + DDX_Control(pDX, IDC_STATEPROVINCELABEL, m_lblStateProv); + DDX_Control(pDX, IDC_STATEPROVINCE, m_edStateProv); + DDX_Control(pDX, IDC_PREFERTECHLABEL, m_lblPreferTech); + DDX_Control(pDX, IDC_PREFERTECH, m_cbPreferTech); + DDX_Control(pDX, IDC_POSTALLABEL, m_lblPostal); + DDX_Control(pDX, IDC_POSTAL, m_edPostal); + DDX_Control(pDX, IDC_PHONELABEL, m_lblPhone); + DDX_Control(pDX, IDC_PHONE, m_edPhone); + DDX_Control(pDX, IDC_MAILADDRESSLABEL, m_lblMail); + DDX_Control(pDX, IDC_MAILADDRESS, m_edMail); + DDX_Control(pDX, IDC_LASTNAMELABEL, m_lblLast); + DDX_Control(pDX, IDC_LASTNAME, m_edLast); + DDX_Control(pDX, IDC_HEADOFFICEPICKERLABEL, m_lblHeadOffice); + DDX_Control(pDX, IDC_HEADOFFICEPICKER, m_cbHeadOffice); + DDX_Control(pDX, IDC_GENERALNOTESLABEL, m_lblGenNotes); + DDX_Control(pDX, IDC_GENERALNOTES, m_edGenNotes); + DDX_Control(pDX, IDC_FIRSTNAMELABEL, m_lblFirst); + DDX_Control(pDX, IDC_FIRSTNAME, m_edFirst); + DDX_Control(pDX, IDC_FAXLABEL, m_lblFax); + DDX_Control(pDX, IDC_FAX, m_edFax); + DDX_Control(pDX, IDC_EXTENSIONLABEL, m_lblExtension); + DDX_Control(pDX, IDC_EXTENSION, m_edExtension); + DDX_Control(pDX, IDC_EMAILLABEL, m_lblEmail); + DDX_Control(pDX, IDC_EMAIL, m_edEmail); + DDX_Control(pDX, IDC_DELETE, m_btnDelete); + DDX_Control(pDX, IDC_COUNTRYLABEL, m_lblCountry); + DDX_Control(pDX, IDC_COUNTRY, m_edCountry); + DDX_Control(pDX, IDC_CONTRACTLABEL, m_lblContract); + DDX_Control(pDX, IDC_CONTRACTEXPIRYLABEL, m_lblContractExpiry); + DDX_Control(pDX, IDC_CONTRACTEXPIRYDATE, m_dtContractExpiryDate); + DDX_Control(pDX, IDC_CONTRACT, m_cbContract); + DDX_Control(pDX, IDC_CONSOLIDATE, m_btnConsolidate); + DDX_Control(pDX, IDC_COMPANY_LABEL, m_lblCompany); + DDX_Control(pDX, IDC_COMPANY, m_edCompany); + DDX_Control(pDX, IDC_CITYLABEL, m_lblCity); + DDX_Control(pDX, IDC_CITY, m_edCity); + DDX_Control(pDX, IDC_ADDHEAD, m_btnAddHead); + DDX_Control(pDX, IDC_ADD, m_btnAdd); + DDX_Control(pDX, IDC_HEADOFFICE, m_ckShowHeadOfficeCheck); + DDX_Control(pDX, IDC_CLIENTLIST_LABEL, m_lblClientListLabel); + DDX_Control(pDX, IDC_CLIENTLIST, m_cbClientList); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_PHONE2, m_edPhone2); + DDX_Control(pDX, IDC_PHONE3, m_edPhone3); + /*DDX_Control(pDX, IDC_CK_INACTIVE, m_ckInactive);*/ + DDX_Control(pDX, IDC_CB_UNITS, m_cbUnits); + DDX_Control(pDX, IDC_LBL_UNITS, m_lblUnits); +} + + +BEGIN_MESSAGE_MAP(CClientsDlg, CDialog) +//{{AFX_MSG_MAP(CClientsDlg) +ON_CBN_CLOSEUP(IDC_CLIENTLIST, OnCloseupClientlist) +ON_BN_CLICKED(IDC_HEADOFFICE, OnHeadoffice) +ON_CBN_CLOSEUP(IDC_CONTRACT, OnCloseupContract) +ON_BN_CLICKED(IDC_DELETE, OnDelete) +ON_BN_CLICKED(IDC_ADD, OnAdd) +ON_BN_CLICKED(IDC_ADDHEAD, OnAddhead) +ON_EN_KILLFOCUS(IDC_FIRSTNAME, OnKillfocusFirstname) +ON_EN_KILLFOCUS(IDC_COMPANY, OnKillfocusCompany) +ON_EN_KILLFOCUS(IDC_LASTNAME, OnKillfocusLastname) +ON_EN_KILLFOCUS(IDC_MAILADDRESS, OnKillfocusMailaddress) +ON_EN_KILLFOCUS(IDC_STREET, OnKillfocusStreet) +ON_EN_KILLFOCUS(IDC_CITY, OnKillfocusCity) +ON_EN_KILLFOCUS(IDC_STATEPROVINCE, OnKillfocusStateprovince) +ON_EN_KILLFOCUS(IDC_POSTAL, OnKillfocusPostal) +ON_EN_KILLFOCUS(IDC_COUNTRY, OnKillfocusCountry) +ON_EN_KILLFOCUS(IDC_PHONE, OnKillfocusPhone) +ON_EN_KILLFOCUS(IDC_EXTENSION, OnKillfocusExtension) +ON_EN_KILLFOCUS(IDC_EMAIL, OnKillfocusEmail) +ON_EN_KILLFOCUS(IDC_FAX, OnKillfocusFax) +ON_CBN_CLOSEUP(IDC_HEADOFFICEPICKER, OnCloseupHeadofficepicker) +ON_BN_CLICKED(IDC_BILLHEAD, OnBillhead) +ON_EN_KILLFOCUS(IDC_TECHNOTES, OnKillfocusTechnotes) +ON_EN_KILLFOCUS(IDC_GENERALNOTES, OnKillfocusGeneralnotes) +ON_CBN_CLOSEUP(IDC_ZONE, OnCloseupZone) +ON_CBN_CLOSEUP(IDC_PREFERTECH, OnCloseupPrefertech) +ON_NOTIFY(DTN_DATETIMECHANGE, IDC_CONTRACTEXPIRYDATE, OnDatetimechangeContractexpirydate) +ON_EN_KILLFOCUS(IDC_ALERT, OnKillfocusAlert) +ON_BN_CLICKED(IDC_ZONELABEL, OnZonelabel) +ON_BN_CLICKED(IDC_CONTRACTLABEL, OnContractlabel) +ON_BN_CLICKED(IDC_HISTORY, OnHistory) +ON_BN_CLICKED(IDC_BTNPM, OnBtnpm) +ON_CBN_CLOSEUP(IDC_CBDEFRATE, OnCloseupCbdefrate) +ON_CBN_CLOSEUP(IDC_CBDEFTRAVEL, OnCloseupCbdeftravel) +ON_BN_CLICKED(IDC_BTNNOTES, OnBtnnotes) +ON_BN_CLICKED(IDC_CONSOLIDATE, OnConsolidate) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_EN_KILLFOCUS(IDC_EDACCTNUM, OnKillfocusEdacctnum) + ON_COMMAND(ID_CLIENTS_ARAS, OnClientsAras) + //}}AFX_MSG_MAP + ON_WM_INITMENUPOPUP() + ON_COMMAND(ID_NEW_CLIENTRECORD, OnNewClientrecord) + ON_UPDATE_COMMAND_UI(ID_NEW_CLIENTRECORD, OnUpdateNewClientrecord) + ON_COMMAND(ID_NEW_HEADOFFICERECORD, OnNewHeadofficerecord) + ON_UPDATE_COMMAND_UI(ID_NEW_HEADOFFICERECORD, OnUpdateNewHeadofficerecord) + ON_COMMAND(ID_EDIT_DELETETHISRECORD, OnEditDeletethisrecord) + ON_UPDATE_COMMAND_UI(ID_EDIT_DELETETHISRECORD, OnUpdateEditDeletethisrecord) + ON_COMMAND(ID_EDIT_CONSOLIDATETWOCLIENTSTOGETHER, OnEditConsolidatetwoclientstogether) + ON_UPDATE_COMMAND_UI(ID_EDIT_CONSOLIDATETWOCLIENTSTOGETHER, OnUpdateEditConsolidatetwoclientstogether) + ON_UPDATE_COMMAND_UI(ID_CLIENTS_ARAS, OnUpdateClientsAras) + ON_COMMAND(ID_TOOLS_OPENCLIENTNOTEBOOK, OnToolsOpenclientnotebook) + ON_UPDATE_COMMAND_UI(ID_TOOLS_OPENCLIENTNOTEBOOK, OnUpdateToolsOpenclientnotebook) + ON_COMMAND(ID_TOOLS_SCHEDULEPREVENTIVEMAINTENANCEFORTHISCLIENT, OnToolsSchedulepreventivemaintenanceforthisclient) + ON_UPDATE_COMMAND_UI(ID_TOOLS_SCHEDULEPREVENTIVEMAINTENANCEFORTHISCLIENT, OnUpdateToolsSchedulepreventivemaintenanceforthisclient) + ON_COMMAND(ID_TOOLS_DISPLAYRECORDHISTORY, OnToolsDisplayrecordhistory) + ON_UPDATE_COMMAND_UI(ID_TOOLS_DISPLAYRECORDHISTORY, OnUpdateToolsDisplayrecordhistory) + ON_COMMAND(ID_CLOSETHISSCREEN, OnClosethisscreen) + ON_UPDATE_COMMAND_UI(ID_CLOSETHISSCREEN, OnUpdateClosethisscreen) + ON_COMMAND(ID_CLIENT_MENU_HELP, OnClientMenuHelp) + ON_EN_KILLFOCUS(IDC_PHONE2, OnEnKillfocusPhone2) + ON_EN_KILLFOCUS(IDC_PHONE3, OnEnKillfocusPhone3) + ON_BN_CLICKED(IDC_EMAILLABEL, OnEmaillabel) + ON_COMMAND(ID_TOOLS_SETADDRESSDEFAULTS, OnToolsSetaddressdefaults) + /*ON_BN_CLICKED(IDC_CK_INACTIVE, OnBnClickedCkInactive)*/ + ON_STN_CLICKED(IDC_LBL_UNITS, OnStnClickedLblUnits) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CClientsDlg message handlers + +void CClientsDlg::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu) +{ + ASSERT(pPopupMenu != NULL); + // Check the enabled state of various menu items. + + CCmdUI state; + state.m_pMenu = pPopupMenu; + ASSERT(state.m_pOther == NULL); + ASSERT(state.m_pParentMenu == NULL); + + // Determine if menu is popup in top-level menu and set m_pOther to + // it if so (m_pParentMenu == NULL indicates that it is secondary popup). + HMENU hParentMenu; + if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu) + state.m_pParentMenu = pPopupMenu; // Parent == child for tracking popup. + else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL) + { + CWnd* pParent = this; + // Child windows don't have menus--need to go to the top! + if (pParent != NULL && + (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL) + { + int nIndexMax = ::GetMenuItemCount(hParentMenu); + for (int nIndex = 0; nIndex < nIndexMax; nIndex++) + { + if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu) + { + // When popup is found, m_pParentMenu is containing menu. + state.m_pParentMenu = CMenu::FromHandle(hParentMenu); + break; + } + } + } + } + + state.m_nIndexMax = pPopupMenu->GetMenuItemCount(); + for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; + state.m_nIndex++) + { + state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex); + if (state.m_nID == 0) + continue; // Menu separator or invalid cmd - ignore it. + + ASSERT(state.m_pOther == NULL); + ASSERT(state.m_pMenu != NULL); + if (state.m_nID == (UINT)-1) + { + // Possibly a popup menu, route to first item of that popup. + state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex); + if (state.m_pSubMenu == NULL || + (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 || + state.m_nID == (UINT)-1) + { + continue; // First item of popup can't be routed to. + } + state.DoUpdate(this, TRUE); // Popups are never auto disabled. + } + else + { + // Normal menu item. + // Auto enable/disable if frame window has m_bAutoMenuEnable + // set and command is _not_ a system command. + state.m_pSubMenu = NULL; + state.DoUpdate(this, FALSE); + } + + // Adjust for menu deletions and additions. + UINT nCount = pPopupMenu->GetMenuItemCount(); + if (nCount < state.m_nIndexMax) + { + state.m_nIndex -= (state.m_nIndexMax - nCount); + while (state.m_nIndex < nCount && + pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID) + { + state.m_nIndex++; + } + } + state.m_nIndexMax = nCount; + } +} + + + +BOOL CClientsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + // Create the control + m_resize.Create( this ); + int nVertFactor;//used to scale vertically + int nDelta=0;//change in vertical height + nVertFactor=0; + nDelta=5; + + //top row + m_resize.Add(IDC_CLIENTLIST,0,0,100,0); + m_resize.Add(IDC_HEADOFFICE,100,0,0,0); + + + nVertFactor+=nDelta; + m_resize.Add(IDC_COMPANY_LABEL,0,nVertFactor,0,0); + m_resize.Add(IDC_COMPANY,0,nVertFactor,100,0); + m_resize.Add(IDC_BILLHEAD,100,nVertFactor,0,0); + m_resize.Add(IDC_HEADOFFICEPICKER,100,nVertFactor,0,0); + m_resize.Add(IDC_HEADOFFICEPICKERLABEL,100,nVertFactor,0,0); + + nVertFactor+=nDelta; + m_resize.Add(IDC_FIRSTNAMELABEL,0,nVertFactor,0,0); + m_resize.Add(IDC_FIRSTNAME,0,nVertFactor,28,0); + m_resize.Add(IDC_LASTNAME, 28,nVertFactor,28,0); + m_resize.Add(IDC_LASTNAMELABEL,28,nVertFactor,0,0); + m_resize.Add(IDC_CB_UNITS,50,nVertFactor,50,0); + m_resize.Add(IDC_LBL_UNITS,50,nVertFactor,0,0); + + + m_resize.Add(IDC_TECHNOTES,50,nVertFactor,50,10); + m_resize.Add(IDC_TECHNOTESLABEL,50,nVertFactor,0,0); + + nVertFactor+=nDelta; + m_resize.Add(IDC_MAILADDRESSLABEL,0,nVertFactor,0,0); + m_resize.Add(IDC_MAILADDRESS,0,nVertFactor,28,0); + m_resize.Add(IDC_STREET, 28,nVertFactor,28,0); + m_resize.Add(IDC_STREETLABEL,28,nVertFactor,0,0); + + nVertFactor+=nDelta; + m_resize.Add(IDC_CITYLABEL,0,nVertFactor,0,0); + m_resize.Add(IDC_CITY,0,nVertFactor,28,0); + m_resize.Add(IDC_STATEPROVINCE, 28,nVertFactor,28,0); + m_resize.Add(IDC_STATEPROVINCELABEL,28,nVertFactor,0,0); + + m_resize.Add(IDC_GENERALNOTES,50,nVertFactor,50,10); + m_resize.Add(IDC_GENERALNOTESLABEL,50,nVertFactor,0,0); + + nVertFactor+=nDelta; + m_resize.Add(IDC_POSTALLABEL,0,nVertFactor,0,0); + m_resize.Add(IDC_POSTAL,0,nVertFactor,28,0); + m_resize.Add(IDC_COUNTRY, 28,nVertFactor,28,0); + m_resize.Add(IDC_COUNTRYLABEL,28,nVertFactor,0,0); + + +nVertFactor+=nDelta; + m_resize.Add(IDC_PHONELABEL,0,nVertFactor,0,0); + m_resize.Add(IDC_PHONE,0,nVertFactor,20,0); + m_resize.Add(IDC_EXTENSION, 20,nVertFactor,0,0); + m_resize.Add(IDC_EXTENSIONLABEL,20,nVertFactor,0,0); + m_resize.Add(IDC_FAX, 20,nVertFactor,37,0); + m_resize.Add(IDC_FAXLABEL,20,nVertFactor,0,0); + m_resize.Add(IDC_ZONE, 50,nVertFactor,20,0); + m_resize.Add(IDC_ZONELABEL,50,nVertFactor,0,0); + m_resize.Add(IDC_EDACCTNUM, 70,nVertFactor,20,0); + m_resize.Add(IDC_LBLACCTNUMBER,70,nVertFactor,0,0); + + nVertFactor+=nDelta; + m_resize.Add(IDC_PHONELABEL2,0,nVertFactor,0,0); + m_resize.Add(IDC_PHONE2,0,nVertFactor,28,0); + m_resize.Add(IDC_PHONE3, 28,nVertFactor,28,0); + m_resize.Add(IDC_PHONELABEL3,28,nVertFactor,0,0); + m_resize.Add(IDC_PREFERTECH,50,nVertFactor,50,0); + m_resize.Add(IDC_PREFERTECHLABEL,50,nVertFactor,0,0); + + nVertFactor+=nDelta; + m_resize.Add(IDC_EMAILLABEL,0,nVertFactor,0,0); + m_resize.Add(IDC_EMAIL,0,nVertFactor,57,0); + m_resize.Add(IDC_CONTRACT, 50,nVertFactor,20,0); + m_resize.Add(IDC_CONTRACTLABEL,50,nVertFactor,0,0); + m_resize.Add(IDC_CONTRACTEXPIRYDATE,70,nVertFactor,0,0); + m_resize.Add(IDC_CONTRACTEXPIRYLABEL,70,nVertFactor,0,0); + + nVertFactor+=nDelta; + m_resize.Add(IDC_LBLDEFRATE,0,nVertFactor,0,0); + m_resize.Add(IDC_CBDEFRATE,0,nVertFactor,57,0); + m_resize.Add(IDC_ALERT, 50,nVertFactor,50,0); + m_resize.Add(IDC_ALERTLABEL,50,nVertFactor,0,0); + + + m_resize.Add(IDC_LBLTRAVRATE,0,nVertFactor,0,0); + m_resize.Add(IDC_CBDEFTRAVEL,0,nVertFactor,57,0); + + + + + + +//Use the current width and height as the minimum size + m_resize.SetMinimumTrackingSize(); + + + Security(); + + if(m_pApp->m_strDataVersion=="146") + { + AfxMessageBox( + "Database update 146 has not completed due to duplicate contact names\r\n" + "in the non-company client records\r\n\r\n" + + "Only the duplicates that need to be fixed will be shown until the update has completed\r\n\r\n" + + "It is recommended that you put a unique number as the last character \r\n" + "of the last name of each duplicate so that they are all unique from each other.\r\n\r\n" + + "Once the update has completed you can then go back in and consolidate the duplicates\r\n" + "or delete the extra un-needed clients\r\n\r\n" + + "Once you've made this change to all duplicates, restart AyaNova so that the\r\n" + "update can complete. (make sure all other users stay out during this process)"); + + //m_btnConsolidate.ShowWindow(FALSE); + } + // changes to an hourglass and + // switches back automatically when out of scope + CWaitCursor Wait; + ShowWindow(FALSE); + + + m_strSelectedClient.Empty(); + + + + //make a EMAIL "hyperlink" + m_lblEmail.SetTextColor(RGB(0,0,255)); + m_lblEmail.SetFontUnderline(TRUE); + m_lblEmail.SetLink(TRUE); + m_lblEmail.SetLinkCursor(m_pApp->hcHand); + m_lblEmail.SetLinkURL(""); + + //make a units "hyperlink" + m_lblUnits.SetTextColor(RGB(0,0,255)); + m_lblUnits.SetFontUnderline(TRUE); + m_lblUnits.SetLink(TRUE); + m_lblUnits.SetLinkCursor(m_pApp->hcHand); + m_lblUnits.SetLinkURL(""); + + + m_lblAlert.SetFontName("MS Sans Serif"); + m_lblAlert.SetFontSize(8); + m_lblAlert.SetFontBold(FALSE); + m_lblAlert.SetTextColor(RGB(255,0,0)); + + + //make a "hyperlink" + m_lblZone.SetTextColor(RGB(0,0,255)); + m_lblZone.SetFontUnderline(TRUE); + m_lblZone.SetLink(TRUE); + m_lblZone.SetLinkCursor(m_pApp->hcHand); + //empty url means it will not launch explorer + //and can be used as a button instead + m_lblZone.SetLinkURL(""); + + + + m_lblContract.SetTextColor(RGB(0,0,255)); + m_lblContract.SetFontUnderline(TRUE); + m_lblContract.SetLink(TRUE); + m_lblContract.SetLinkCursor(m_pApp->hcHand); + m_lblContract.SetLinkURL(""); + + m_lblHist.SetTextColor(RGB(0,0,255)); + m_lblHist.SetFontUnderline(TRUE); + m_lblHist.SetLink(TRUE); + m_lblHist.SetLinkURL(""); + m_lblHist.SetLinkCursor(m_pApp->hcHand); + + RefreshDisplay(0);//0=client 1=head office. + + + + m_bAddMode=false; + ShowWindow(SW_SHOWMAXIMIZED); + + if(!m_strForceSelection.IsEmpty()) + { + m_cbClientList.Select(m_strForceSelection); + OnCloseupClientlist(); + } + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + + + //SET DATA ENTRY LIMITS + +m_edAcctNum.SetLimitText(40); +m_edAlert.SetLimitText(255); +//m_edTechNotes.SetLimitText(65535); +m_edStreet.SetLimitText(255); +m_edStateProv.SetLimitText(30); +m_edPostal.SetLimitText(20); +m_edPhone.SetLimitText(20); +m_edPhone2.SetLimitText(40); +m_edPhone3.SetLimitText(40); +m_edMail.SetLimitText(100); +m_edLast.SetLimitText(50); +//m_edGenNotes +m_edFirst.SetLimitText(50); +m_edFax.SetLimitText(20); +m_edExtension.SetLimitText(10); +m_edCountry.SetLimitText(30); +m_edCompany.SetLimitText(80); +m_edCity.SetLimitText(30); + + + + + + //ShowWindow(TRUE); +m_edGenNotes.SetFocus(); + return FALSE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +bool CClientsDlg::FillClientList() +{ + CString strData,strTemp; + CString strIndex; + CString strHead,q; + + if(m_ckShowHeadOfficeCheck.GetCheck()==TRUE) + strHead="True"; + else + strHead="False"; + long lData; + m_cbClientList.Clear(); + + //added 08/03/2001 to handle client change + if(m_pApp->m_strDataVersion=="146") + { + + q.Format("SELECT clients.last, clients.first, clients.id, clients.company as compname " + "FROM clients " + "WHERE (((clients.last) In (SELECT [last] FROM [clients] As Tmp GROUP BY [last],[first] HAVING Count(*)>1 And [first] = [clients].[first])) AND ((clients.isheadoffice)=%s) AND ((clients.company) Is Null)) " + "ORDER BY clients.last, clients.first;",strHead); + +/* + q.Format("SELECT clients.id, clients.first, clients.last, clients.company AS compname FROM clients WHERE (((clients.isheadoffice)=%s)) " + "AND (((clients.company) Is Null)) ORDER BY clients.last, clients.first;",strHead); + */ + } + else + { + q.Format("SELECT clients.id, clients.company AS compname FROM clients WHERE (((clients.isheadoffice)=%s)) " + "ORDER BY clients.company;",strHead); + + } + rs->Close(); + rs->Query(q); + + + + + + if(!rs->IsEmpty()) + { + //fill combo box with available clients + + //added 08/03/2001 to handle client change + if(m_pApp->m_strDataVersion=="146") + { + + rs->FetchField("last",&strTemp); + strData=strTemp; + rs->FetchField("first",&strTemp); + strData+=", " + strTemp; + + } + else + rs->FetchField("compname",&strData); + + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbClientList.AddRow(strData,strIndex); + + while(rs->MoveForward()) + { + //added 08/03/2001 to handle client change + if(m_pApp->m_strDataVersion=="146") + { + rs->FetchField("last",&strTemp); + strData=strTemp; + rs->FetchField("first",&strTemp); + strData+=", " + strTemp; + + } + else + rs->FetchField("compname",&strData); + + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbClientList.AddRow(strData,strIndex); + } + //pretend user has selected so that other fields get filled in + if(m_strSelectedClient.IsEmpty()) //first time in + { + m_cbClientList.SetCurSel(0); + m_strSelectedClient=m_cbClientList.GetCurrentRowID(); + if(m_pstrReturnValue!=NULL) + m_pstrReturnValue->Format("%s",m_strSelectedClient); + } + else//something valid was selected before so stick with it + m_cbClientList.Select(m_strSelectedClient); + + + FillFields(); + //FillUnitList(); + + }//is no records? + else//nope + { + BlankAllFields(false,false); + } + + + + + return true; +} + + + + +//***************************************************** +bool CClientsDlg::RefreshDisplay(int dMode/*0=standard 1=headoffice 2=add*/) +{ + + + switch(dMode) + { + case 0://standard client edit mode + //m_strSelectedClient=""; + m_cbClientList.ShowWindow(TRUE); + m_lblClientListLabel.ShowWindow(TRUE); + //m_btnPM.ShowWindow(TRUE); + + //m_btnAdd.SetWindowText("Add"); + if(!m_bReadOnly) + { + //m_btnAdd.ShowWindow(TRUE); + //m_btnDelete.ShowWindow(TRUE); + //m_btnConsolidate.ShowWindow(TRUE); + //m_btnAddHead.ShowWindow(TRUE); + } + //m_btnDone.SetWindowText("Close"); + //m_btnNotes.ShowWindow(TRUE); + //m_btnAddHead.SetWindowText("Add head office"); + m_ckShowHeadOfficeCheck.ShowWindow(TRUE); + m_cbHeadOffice.ShowWindow(TRUE); + m_lblHeadOffice.ShowWindow(TRUE); + m_ckBillHead.ShowWindow(TRUE); + + m_edTechNotes.ShowWindow(TRUE); + m_lblTechNotes.ShowWindow(TRUE); + m_lblGenNotes.ShowWindow(TRUE); + m_edGenNotes.ShowWindow(TRUE); + m_lblZone.ShowWindow(TRUE); + m_lblUnits.ShowWindow(TRUE); + m_cbUnits.ShowWindow(TRUE); + + m_cbZone.ShowWindow(TRUE); + m_lblPreferTech.ShowWindow(TRUE); + m_cbPreferTech.ShowWindow(TRUE); + //m_lblContractNotes.ShowWindow(FALSE); + m_lblCompany.SetWindowText("Client: (Person or company. Required.)"); + FillHeadOfficeList(); + FillTechList(); + FillZoneList(); + FillContractList(); + FillRatesLists(); + + FillClientList(); + FillUnitList(); + break; + + case 1://headoffices only mode + //m_strSelectedClient=""; + m_lblCompany.SetWindowText("Head office:"); + //m_btnAdd.ShowWindow(FALSE); + //m_btnPM.ShowWindow(FALSE); + m_cbClientList.ShowWindow(TRUE); + m_lblClientListLabel.ShowWindow(TRUE); + //m_btnAdd.SetWindowText("Add"); + //m_btnDone.SetWindowText("Close"); + if(!m_bReadOnly) + { + //m_btnDelete.ShowWindow(TRUE); + //m_btnAddHead.ShowWindow(TRUE); + //m_btnConsolidate.ShowWindow(TRUE); + } + + //m_btnAddHead.SetWindowText("Add head office"); + m_ckShowHeadOfficeCheck.ShowWindow(TRUE); + //m_btnNotes.ShowWindow(TRUE); + //m_btnConsolidate.ShowWindow(FALSE); + m_cbHeadOffice.ShowWindow(FALSE); + m_lblHeadOffice.ShowWindow(FALSE); + m_ckBillHead.ShowWindow(FALSE); + + m_edTechNotes.ShowWindow(FALSE); + m_lblTechNotes.ShowWindow(FALSE); + m_lblGenNotes.ShowWindow(FALSE); + m_edGenNotes.ShowWindow(FALSE); + m_lblZone.ShowWindow(FALSE); + m_cbZone.ShowWindow(FALSE); + m_lblUnits.ShowWindow(FALSE); + m_cbUnits.ShowWindow(FALSE); + m_lblPreferTech.ShowWindow(FALSE); + m_cbPreferTech.ShowWindow(FALSE); + //m_lblContractNotes.ShowWindow(TRUE); + + FillClientList(); + + break; + + case 2://add client mode + m_lblCompany.SetWindowText("Client: (Person or company. Required.)"); + m_cbClientList.ShowWindow(FALSE); + m_lblClientListLabel.ShowWindow(FALSE); + //m_btnPM.ShowWindow(FALSE); + //m_btnAdd.SetWindowText("SAVE"); + //m_btnDone.SetWindowText("Cancel"); + //m_btnDelete.ShowWindow(FALSE); + //m_btnNotes.ShowWindow(FALSE); + //m_btnConsolidate.ShowWindow(FALSE); + //m_btnAddHead.ShowWindow(FALSE); + m_ckShowHeadOfficeCheck.ShowWindow(FALSE); + BlankAllFields(true,true); + break; + + case 3://add head office mode + m_lblCompany.SetWindowText("Head office:"); + m_cbClientList.ShowWindow(FALSE); + //m_btnPM.ShowWindow(FALSE); + m_lblClientListLabel.ShowWindow(FALSE); + //m_btnAddHead.SetWindowText("SAVE"); + //m_btnDone.SetWindowText("Cancel"); + //m_btnDelete.ShowWindow(FALSE); + //m_btnNotes.ShowWindow(FALSE); + //m_btnConsolidate.ShowWindow(FALSE); + //m_btnAdd.ShowWindow(FALSE); + m_ckShowHeadOfficeCheck.ShowWindow(FALSE); + BlankAllFields(true,true); + + + //m_btnAddHead.ShowWindow(TRUE); + + + m_cbHeadOffice.ShowWindow(FALSE); + m_lblHeadOffice.ShowWindow(FALSE); + m_ckBillHead.ShowWindow(FALSE); + + m_edTechNotes.ShowWindow(FALSE); + m_lblTechNotes.ShowWindow(FALSE); + m_lblGenNotes.ShowWindow(FALSE); + m_edGenNotes.ShowWindow(FALSE); + m_lblZone.ShowWindow(FALSE); + m_cbZone.ShowWindow(FALSE); + m_lblPreferTech.ShowWindow(FALSE); + m_cbPreferTech.ShowWindow(FALSE); + //m_lblContractNotes.ShowWindow(TRUE); + + + + + break; + } + + + if(m_bReadOnly) + { + //m_btnAdd.ShowWindow(FALSE); + //m_btnAddHead.ShowWindow(FALSE); + //m_btnConsolidate.ShowWindow(FALSE); + //m_btnDelete.ShowWindow(FALSE); + //m_btnNotes.ShowWindow(FALSE); + m_ckBillHead.EnableWindow(FALSE); + + m_cbRate.EnableWindow(FALSE); + m_cbDefTravelRate.EnableWindow(FALSE); + //m_ckShowHeadOfficeCheck.EnableWindow(FALSE); + m_dtContractExpiryDate.EnableWindow(FALSE); + m_edAlert.SetReadOnly(TRUE); + m_edCity.SetReadOnly(TRUE); + m_edCompany.SetReadOnly(TRUE); + m_edCountry.SetReadOnly(TRUE); + m_edEmail.SetReadOnly(TRUE); + m_edExtension.SetReadOnly(TRUE); + m_edFax.SetReadOnly(TRUE); + m_edFirst.SetReadOnly(TRUE); + m_edGenNotes.SetReadOnly(TRUE); + m_edLast.SetReadOnly(TRUE); + m_edMail.SetReadOnly(TRUE); + m_edPhone.SetReadOnly(TRUE); + m_edPostal.SetReadOnly(TRUE); + m_edStateProv.SetReadOnly(TRUE); + m_edStreet.SetReadOnly(TRUE); + m_edTechNotes.SetReadOnly(TRUE); + m_edAcctNum.EnableWindow(FALSE); + + + + } + + return true; +} + +void CClientsDlg::OnCloseupClientlist() +{ + CString strTemp; + strTemp=m_cbClientList.GetCurrentRowID(); + //jump back if same client + if(strTemp==m_strSelectedClient) return; + + //save current selection so that updates and changes + //will still show what was last selected + m_strSelectedClient=strTemp; + if(m_pstrReturnValue!=NULL) + m_pstrReturnValue->Format("%s",m_strSelectedClient); + + FillFields(); +//v1.9.4.4 moved to fill fields function + //FillUnitList(); +} + +void CClientsDlg::OnHeadoffice() +{ + //user clicked the head office only checkbox + if(m_ckShowHeadOfficeCheck.GetCheck()==TRUE) + RefreshDisplay(1);//head office mode + else + RefreshDisplay(0);//normal mode +} + + + + +bool CClientsDlg::FillFields() +{ + + + CString q; + CString strData,strRecStatus; + bool bData; + BOOL intbData; + long lData; + COleDateTime dtData; + + //v1.9.4.5 + bool bRefreshTechList=false; + + q=m_cbClientList.GetCurrentRowID(); + if(q.IsEmpty()) //then there is no record to display, show blanks instead + { + BlankAllFields(false,false); + return false; + } + BlankAllFields(false,true); + rs->Close(); + q.Format("SELECT clients.* FROM clients WHERE (((clients.id)=%s));",m_cbClientList.GetCurrentRowID()); + rs->Query(q); + if(!rs->IsEmpty()) + { + rs->FetchField("first",&strData); + m_edFirst.SetWindowText(strData); + + rs->FetchField("czone",&lData); + strData.Format("%u",lData); + m_cbZone.Select(strData); + + rs->FetchField("defrate",&lData); + strData.Format("%u",lData); + m_cbRate.Select(strData); + + rs->FetchField("deftravelrate",&lData); + strData.Format("%u",lData); + m_cbDefTravelRate.Select(strData); + + + rs->FetchField("headoffice",&lData); + strData.Format("%u",lData); + m_cbHeadOffice.Select(strData); + + + rs->FetchField("billheadoffice",&bData); + intbData=TRUE; + if(bData==false) intbData=FALSE; + m_ckBillHead.SetCheck(intbData); + + + + rs->FetchField("alert",&strData); + m_edAlert.SetWindowText(strData); + + rs->FetchField("technotes",&strData); + m_edTechNotes.SetWindowText(strData); + + rs->FetchField("streetaddress",&strData); + m_edStreet.SetWindowText(strData); + + rs->FetchField("stateprov",&strData); + m_edStateProv.SetWindowText(strData); + + + rs->FetchField("prefertech",&lData); + //v1.9.4.5, now sets in fill tech list + if(lData!=lPreferredTech) + { + lPreferredTech=lData; + bRefreshTechList=true; + } + //strData.Format("%u",lData); + //m_cbPreferTech.Select(strData); + + rs->FetchField("postal",&strData); + m_edPostal.SetWindowText(strData); + + rs->FetchField("bizphone",&strData); + m_edPhone.SetWindowText(strData); + + rs->FetchField("phone2",&strData); + m_edPhone2.SetWindowText(strData); + + rs->FetchField("phone3",&strData); + m_edPhone3.SetWindowText(strData); + + + rs->FetchField("mailaddress",&strData); + m_edMail.SetWindowText(strData); + + rs->FetchField("last",&strData); + m_edLast.SetWindowText(strData); + + //m_cbHeadOffice; + + rs->FetchField("generalnotes",&strData); + m_edGenNotes.SetWindowText(strData); + + + rs->FetchField("fax",&strData); + m_edFax.SetWindowText(strData); + + rs->FetchField("extension",&strData); + m_edExtension.SetWindowText(strData); + + rs->FetchField("email",&strData); + m_edEmail.SetWindowText(strData); + + rs->FetchField("acctnumber",&strData); + m_edAcctNum.SetWindowText(strData); + + rs->FetchField("country",&strData); + m_edCountry.SetWindowText(strData); + + + rs->FetchField("contract",&lData); + strData.Format("%u",lData); + m_cbContract.Select(strData); + if(lData==0) //means no contract + { + m_dtContractExpiryDate.ShowWindow(FALSE); + m_lblContractExpiry.ShowWindow(FALSE); + } + else + { + m_dtContractExpiryDate.ShowWindow(TRUE); + m_lblContractExpiry.ShowWindow(TRUE); + } + + if(rs->FetchField("contractexpires",&dtData)==0) + dtData=COleDateTime::GetCurrentTime();//set to today if no value + m_dtContractExpiryDate.SetTime(dtData); + + + + rs->FetchField("company",&strData); + m_edCompany.SetWindowText(strData); + + rs->FetchField("city",&strData); + m_edCity.SetWindowText(strData); + + + + + + //Set recordset back to original + q.Format("SELECT clients.* FROM clients WHERE (((clients.id)=%s));",m_cbClientList.GetCurrentRowID()); + rs->Query(q); + + } + + //v1.9.4.4 added and removed from wherever it was called separately + //since it should always go hand in hand with fillfields + FillUnitList(); + + //v1.9.4.5 + if(bRefreshTechList) + FillTechList(); + + return true; +} + +bool CClientsDlg::FillZoneList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbZone.Clear(); + m_cbZone.AddRow("","0"); + rs->Query("SELECT zones.* FROM zones ORDER BY zones.name;"); + if(!rs->IsEmpty()) + { + //fill combo box with available zones + //rs->MoveFirst(); + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbZone.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbZone.AddRow(strData,strIndex); + } + + } + return true; +} + +bool CClientsDlg::FillTechList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbPreferTech.Clear(); + CString q; + + +//---------- + +//v1.9.4.5 + //If there is a selected client, + //Get preferred tech and see if inactive, if so + //add to the list manually + if(lPreferredTech!=0) + { + + q.Format("SELECT users.id, [last] & \", \" & [first] AS fullname " + "FROM users " + "WHERE (((users.id)=%u) AND ((users.active)=False));",lPreferredTech); + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty()) //it's an inactive tech put them in the list "manually" + { + rs2->FetchField("fullname",&strData); + rs2->FetchField("id",&lData); + strIndex.Format("%u",lData); + q=" " + strData; + m_cbPreferTech.AddRow(q,strIndex); + + } + + + } + + + + + + + +//1.9.4.4 was: rs2->QueryReadOnly("SELECT users.id, [last] & \", \" & [first] AS fullname FROM users WHERE (((users.tech)=True)) ORDER BY users.last;"); + //1.9.4.5 is now: +rs2->QueryReadOnly("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;"); + +//v1.9.4.5 changed query above so inactive techs are not displayed in the +//preferred tech list + + m_cbPreferTech.AddRow("","0"); + if(!rs2->IsEmpty()) + { + + + + do + { + rs2->FetchField("fullname",&strData); + rs2->FetchField("id",&lData); + if(lData!=1) + { + strIndex.Format("%u",lData); + m_cbPreferTech.AddRow(strData,strIndex); + } + }while(rs2->MoveForward()); + + } + + m_cbPreferTech.Select(lPreferredTech); + return true; +} + +bool CClientsDlg::FillContractList() +{ + + + CString strData; + CString strIndex; + long lData; + m_cbContract.Clear(); + m_cbContract.AddRow("","0"); + rs->Query("SELECT contracts.* FROM contracts ORDER BY contracts.name;"); + if(!rs->IsEmpty()) + { + //fill combo box with available contracts + //rs->MoveFirst(); + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbContract.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbContract.AddRow(strData,strIndex); + } + + } + return true; +} + + + + + + + + + + + + + + + + + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CClientsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode) return true;//dont attempt to update + + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + if(!EditPrompt()) return true; + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + rs->pTheConnection->BeginTrans(); + rs->UpdateField(fldname,&str); + + if(!rs->SaveRecord()) + { + rs->pTheConnection->RollbackTrans(); + edControl->Undo(); + edControl->SetModify(FALSE); + return false; + } + rs->pTheConnection->CommitTrans(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE GZCOMBO CONTROL FIELD +//************************************************************ +bool CClientsDlg::SaveField(CgzCombo *cbControl,CString fldname) +{ + + if(m_bAddMode) return true;//dont attempt to update + if(!EditPrompt()) return false; + CString str; + long lData; + str=cbControl->GetCurrentRowID(); + if(str.IsEmpty()) return false;//shouldn't happen but... + lData=atol(str); + rs->pTheConnection->BeginTrans(); + rs->UpdateField(fldname,&lData); + rs->SaveRecord(); + rs->pTheConnection->CommitTrans(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CClientsDlg::SaveField(CButton *ckControl,CString fldname) +{ + if(m_bAddMode) return true;//dont attempt to update + if(!EditPrompt()) return false; + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->pTheConnection->BeginTrans(); + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + rs->pTheConnection->CommitTrans(); + UpdateModified(); + return true; +} +//************************************************************ +//SAVE DateTimePicker CONTROL FIELD +//************************************************************ +bool CClientsDlg::SaveField(CDateTimeCtrl *dtControl,CString fldname) +{ + if(m_bAddMode) return true;//dont attempt to update + if(!EditPrompt()) return false; + COleDateTime dtData; + dtControl->GetTime(dtData); + rs->pTheConnection->BeginTrans(); + rs->UpdateField(fldname,&dtData); + rs->SaveRecord(); + rs->pTheConnection->CommitTrans(); + UpdateModified(); + return true; +} + + +//************************************************ +//UPDATE MODIFIED DATA +//************************************************* +bool CClientsDlg::UpdateModified() +{ + bool bIndexed=false; + //updates modified by and modified on fields + rs->UpdateField("modifier",&m_pApp->m_lusrID); + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + + //flag for indexing + rs->pTheConnection->BeginTrans(); + rs->UpdateField("indexed",&bIndexed); + rs->SaveRecord(); + rs->pTheConnection->CommitTrans(); + + + return true; +} + + + + + + + + + + + +//************************************************* +//DELETE RECORD +//************************************************* +void CClientsDlg::OnDelete() +{ + +} + + +//******************************************************** +void CClientsDlg::OnAdd() +{ + // Add/save client record + if(m_bAddMode)//then user has clicked SAVE + { + //validate and save + if(!AddRecord(false)) + return; + if(m_ckShowHeadOfficeCheck.GetCheck()==TRUE) + RefreshDisplay(1);//head office mode + else + RefreshDisplay(0);//normal mode + m_bAddMode=false; + + } + else //user has just clicked add + { + //switch to add client mode + m_bAddMode=true; + RefreshDisplay(2);//add client mode + + SetDefaults(); + + } + + + +} + + +//*********************************************************** +void CClientsDlg::OnAddhead() +{ + // Add head office record + // Add/save client record + if(m_bAddMode)//then we user has clicked SAVE + { + //validate and save + AddRecord(true); + if(m_ckShowHeadOfficeCheck.GetCheck()==TRUE) + RefreshDisplay(1);//head office mode + else + RefreshDisplay(0);//normal mode + m_bAddMode=false; + + } + else //user has just clicked add + { + //switch to add client mode + m_bAddMode=true; + RefreshDisplay(3);//add head mode + SetDefaults(); + + } +} + + + +//********************************************************** +void CClientsDlg::OnOK() +{ +/* +if(m_bAddMode)//then user has pressed cancel button +{ +//revert to previous view and save changes +if(m_ckShowHeadOfficeCheck.GetCheck()==TRUE) +RefreshDisplay(1);//head office mode +else +RefreshDisplay(0);//normal mode +m_bAddMode=false; +} +else +{ + + if(m_pstrReturnValue!=NULL) + m_pstrReturnValue->Format("%s",m_strSelectedClient); + CDialog::OnOK(); + } + */ +} + + + + +//**************************************************** +void CClientsDlg::BlankAllFields(bool bSetDefaults,bool bEnable) +{ + BOOL e=FALSE; + if(bEnable) e=TRUE; + + m_edPhone2.SetWindowText(""); + m_edPhone2.EnableWindow(e); + + m_edPhone3.SetWindowText(""); + m_edPhone3.EnableWindow(e); + m_cbUnits.Clear(); + + m_edAcctNum.SetWindowText(""); + m_edAcctNum.EnableWindow(e); + + m_cbZone.Select("0");//any zone + m_cbZone.EnableWindow(e); + + m_cbRate.Select("0"); + m_cbDefTravelRate.Select("0"); + m_cbRate.EnableWindow(e); + m_cbDefTravelRate.EnableWindow(e); + + m_ckBillHead.SetCheck(FALSE); + m_ckBillHead.EnableWindow(e); + + + + + m_edAlert.SetWindowText(""); + m_edAlert.EnableWindow(e); + + m_edTechNotes.SetWindowText(""); + m_edTechNotes.EnableWindow(e); + + m_edStreet.SetWindowText(""); + m_edStreet.EnableWindow(e); + + m_cbPreferTech.Select("0"); + m_cbPreferTech.EnableWindow(e); + + m_edPhone.SetWindowText(""); + m_edPhone.EnableWindow(e); + m_edMail.SetWindowText(""); + m_edMail.EnableWindow(e); + m_edLast.SetWindowText(""); + m_edLast.EnableWindow(e); + m_cbHeadOffice.Select("0"); + m_cbHeadOffice.EnableWindow(e); + m_edGenNotes.SetWindowText(""); + m_edGenNotes.EnableWindow(e); + m_edFirst.SetWindowText(""); + m_edFirst.EnableWindow(e); + m_edFax.SetWindowText(""); + m_edFax.EnableWindow(e); + m_edExtension.SetWindowText(""); + m_edExtension.EnableWindow(e); + + m_edEmail.SetWindowText(""); + m_edEmail.EnableWindow(e); + + m_cbContract.Select("0"); + m_cbContract.EnableWindow(e); + m_edCompany.SetWindowText(""); + m_edCompany.EnableWindow(e); + + m_dtContractExpiryDate.SetTime( COleDateTime::GetCurrentTime()); + m_dtContractExpiryDate.EnableWindow(e); + + if(bSetDefaults) + { + //set the defaultable fields to their defaults + rs->Query("SELECT defaults.* FROM defaults;"); + CString data; + rs->FetchField("city",&data); + m_edCity.SetWindowText(data); + rs->FetchField("country",&data); + m_edCountry.SetWindowText(data); + rs->FetchField("postal",&data); + m_edPostal.SetWindowText(data); + rs->FetchField("stateprov",&data); + m_edStateProv.SetWindowText(data); + } + else + { + m_edCity.SetWindowText(""); + m_edCountry.SetWindowText(""); + m_edPostal.SetWindowText(""); + m_edStateProv.SetWindowText(""); + } + + m_edCity.EnableWindow(e); + m_edCountry.EnableWindow(e); + m_edPostal.EnableWindow(e); + m_edStateProv.EnableWindow(e); + + + + +} + + +//********************************************************* +bool CClientsDlg::AddRecord(bool bIsHeadOffice) +{ + + CString q; + CString strData; + bool bData; + BOOL intbData; + long lData,lNewID; + COleDateTime dtData; + + // m_edLast.GetWindowText(strData); + m_edCompany.GetWindowText(q); + + //make sure there is at least a company or last name + if(q.IsEmpty()) + { + AfxMessageBox("You must enter a client name to proceed"); + return false; + } + + dtData=COleDateTime::GetCurrentTime(); + + q.Format("INSERT INTO clients ( creator, created, modifier, modified ) " + "SELECT %u, #%s#, %u, #%s#;", + m_pApp->m_lusrID,dtData.Format(_T("%m/%d/%Y %H:%M:%S")), + m_pApp->m_lusrID,dtData.Format(_T("%m/%d/%Y %H:%M:%S"))); + + rs->Ex(q,&lNewID); + rs->Close(); + + q.Format("SELECT clients.* FROM clients WHERE (((clients.id)=%u));",lNewID); + rs->Query(q); + + ASSERT(!rs->IsEmpty()); + + m_strSelectedClient.Format("%u",lNewID); + + + + + //go through the fields one by one + + rs->pTheConnection->BeginTrans(); + //first set non-visible fields + bData=false; + if(bIsHeadOffice) + bData=true; + rs->UpdateField("isheadoffice",&bData); + + + + + //now set visible items + m_edFirst.GetWindowText(strData); + rs->UpdateField("first",&strData); + + strData=m_cbZone.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("czone",&lData); + + bData=true; + intbData=m_ckBillHead.GetCheck(); + if(intbData==FALSE) + bData=false; + rs->UpdateField("billheadoffice",&bData); + + + m_edAlert.GetWindowText(strData); + rs->UpdateField("alert",&strData); + + m_edTechNotes.GetWindowText(strData); + rs->UpdateField("technotes",&strData); + + m_edStreet.GetWindowText(strData); + rs->UpdateField("streetaddress",&strData); + + m_edStateProv.GetWindowText(strData); + rs->UpdateField("stateprov",&strData); + + strData=m_cbPreferTech.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("prefertech",&lData); + + m_edPostal.GetWindowText(strData); + rs->UpdateField("postal",&strData); + + m_edPhone.GetWindowText(strData); + rs->UpdateField("bizphone",&strData); + + m_edMail.GetWindowText(strData); + rs->UpdateField("mailaddress",&strData); + + m_edLast.GetWindowText(strData); + rs->UpdateField("last",&strData); + + strData=m_cbHeadOffice.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("prefertech",&lData); + + m_edGenNotes.GetWindowText(strData); + rs->UpdateField("generalnotes",&strData); + + m_edFax.GetWindowText(strData); + rs->UpdateField("fax",&strData); + + m_edExtension.GetWindowText(strData); + rs->UpdateField("extension",&strData); + + m_edEmail.GetWindowText(strData); + rs->UpdateField("email",&strData); + + m_edCountry.GetWindowText(strData); + rs->UpdateField("country",&strData); + + strData=m_cbContract.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("contract",&lData); + + m_dtContractExpiryDate.GetTime(dtData); + rs->UpdateField("contractexpires",&dtData); + + m_edCompany.GetWindowText(strData); + rs->UpdateField("company",&strData); + + m_edCity.GetWindowText(strData); + rs->UpdateField("city",&strData); + + //account number...whoops! about 20 releases overdue + m_edAcctNum.GetWindowText(strData); + rs->UpdateField("acctnumber",&strData); + + + + if(!rs->SaveRecord()) + { + rs->RecordSetPointer()->CancelUpdate(); + rs->pTheConnection->RollbackTrans(); + m_strSelectedClient="0"; + } + rs->pTheConnection->CommitTrans(); + + //q.Format("SELECT clients.* FROM clients;"); + //rs->Query(q); + rs->Close(); + return true; +} + +//******************************************* +void CClientsDlg::OnKillfocusFirstname() +{ + SaveField(&m_edFirst,"first",true); +} + +//*****************************************8 +void CClientsDlg::OnKillfocusCompany() +{ + //bool allowblank=false; + /* + CString str; + m_edLast.GetWindowText(str); + if(str.IsEmpty()) allowblank=false; + */ + if(m_edCompany.GetModify()==false) return; + //Check for duplicate before saving +CString q; +CString str; +m_edCompany.GetWindowText(str); +if(str.IsEmpty()) return; + +//check if it's just the same as before +m_cbClientList.GetWindowText(q); +if(q==str) return; + +q.Format("SELECT clients.company " + "FROM clients WHERE (((clients.company)=\"%s\"));",str); +rs2->QueryReadOnly(q); +if(!rs2->IsEmpty()) +{ + q.Format("Client %s is already in the database\r\n" + "Every client name must be unique in AyaNova.",str); + AfxMessageBox(q); + m_edCompany.Undo(); + m_edCompany.SetModify(FALSE); + m_edCompany.SetFocus(); + return; + +} + + SaveField(&m_edCompany,"company",false); + m_edCompany.SetModify(FALSE); + if(!m_bAddMode) FillClientList(); +} + +void CClientsDlg::OnKillfocusLastname() +{ + bool allowblank=true; + CString str; + m_edCompany.GetWindowText(str); + if(str.IsEmpty()) allowblank=false; + SaveField(&m_edLast,"last",allowblank); + +} + +void CClientsDlg::OnKillfocusMailaddress() +{ + SaveField(&m_edMail,"mailaddress",true); +} + +void CClientsDlg::OnKillfocusStreet() +{ + SaveField(&m_edStreet,"streetaddress",true); + +} + +void CClientsDlg::OnKillfocusCity() +{ + SaveField(&m_edCity,"city",true); + +} + +void CClientsDlg::OnKillfocusStateprovince() +{ + SaveField(&m_edStateProv,"stateprov",true); + +} + +void CClientsDlg::OnKillfocusPostal() +{ + SaveField(&m_edPostal,"postal",true); +} + +void CClientsDlg::OnKillfocusCountry() +{ + SaveField(&m_edCountry,"country",true); + +} + +void CClientsDlg::OnKillfocusPhone() +{ + SaveField(&m_edPhone,"bizphone",true); + +} + +void CClientsDlg::OnKillfocusExtension() +{ + SaveField(&m_edExtension,"extension",true); + +} + +void CClientsDlg::OnKillfocusEmail() +{ + SaveField(&m_edEmail,"email",true); + +} + +void CClientsDlg::OnKillfocusFax() +{ + SaveField(&m_edFax,"fax",true); + +} + +void CClientsDlg::OnCloseupHeadofficepicker() +{ + SaveField(&m_cbHeadOffice,"headoffice"); +} + +void CClientsDlg::OnBillhead() +{ + SaveField(&m_ckBillHead,"billheadoffice"); + +} + + + +void CClientsDlg::OnKillfocusTechnotes() +{ + SaveField(&m_edTechNotes,"technotes",true); + +} + +void CClientsDlg::OnKillfocusGeneralnotes() +{ + SaveField(&m_edGenNotes,"generalnotes",true); + +} +//********************************************** +void CClientsDlg::OnCloseupContract() +{ + + if(m_cbContract.GetCurrentRowID()=="0") //means no contract + { + m_dtContractExpiryDate.ShowWindow(FALSE); + m_lblContractExpiry.ShowWindow(FALSE); + } + else + { + m_dtContractExpiryDate.ShowWindow(TRUE); + m_lblContractExpiry.ShowWindow(TRUE); + } + SaveField(&m_cbContract,"contract"); +} + +void CClientsDlg::OnCloseupZone() +{ + SaveField(&m_cbZone,"czone"); + +} + +void CClientsDlg::OnCloseupPrefertech() +{ + SaveField(&m_cbPreferTech,"prefertech"); + +} + +void CClientsDlg::OnDatetimechangeContractexpirydate(NMHDR* pNMHDR, LRESULT* pResult) +{ + SaveField(&m_dtContractExpiryDate,"contractexpires"); + + *pResult = 0; +} + +void CClientsDlg::OnKillfocusAlert() +{ + SaveField(&m_edAlert,"alert",true); + +} + +bool CClientsDlg::FillHeadOfficeList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbHeadOffice.Clear(); + m_cbHeadOffice.AddRow("","0"); + if(!rs->Query("SELECT clients.* FROM clients WHERE (((clients.isheadoffice)=True)) " + "ORDER BY clients.company;")) + return false; + if(!rs->IsEmpty()) + { + //fill combo box with available headoffices + //rs->MoveFirst(); + rs->FetchField("company",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbHeadOffice.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("company",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbHeadOffice.AddRow(strData,strIndex); + } + + } + return true; +} + +void CClientsDlg::OnZonelabel() +{ + + CString s; + s=m_cbZone.GetCurrentRowID(); + CZonesDlg d; + if(d.DoModal()==IDOK) + { + FillZoneList(); + m_cbZone.Select(s); + if(!m_bAddMode) + FillFields(); + } +} + + + +void CClientsDlg::OnContractlabel() +{ + CString s; + s=m_cbContract.GetCurrentRowID(); + CContractsDlg dlg; + if(dlg.DoModal()==IDOK) + { + FillContractList(); + m_cbContract.Select(s); + FillFields(); + } +} + + +void CClientsDlg::SetReturnString(CString *ret) +{ + m_pstrReturnValue=ret; + +} + +void CClientsDlg::OnHistory() +{ + + + +} + + +//Preventative maintenance scheduling +void CClientsDlg::OnBtnpm() +{ + +} + + + +void CClientsDlg::SetDefaults() +{ + CString strData; + + + + rs2->Query("SELECT * FROM defaults;"); + + rs2->FetchField("city",&m_strDefaultCity); + if(m_strDefaultCity.IsEmpty()) + m_strDefaultCity=" "; + //m_edCity.SetWindowText(strData); + + rs2->FetchField("stateprov",&m_strDefaultStateProv); + if(m_strDefaultStateProv.IsEmpty()) + m_strDefaultStateProv=" "; + //m_edStateProv.SetWindowText(strData); + + rs2->FetchField("postal",&m_strDefaultPostal); + if(m_strDefaultPostal.IsEmpty()) + m_strDefaultPostal=" "; + //m_edPostal.SetWindowText(strData); + + rs2->FetchField("country",&m_strDefaultCountry); + if(m_strDefaultCountry.IsEmpty()) + m_strDefaultCountry=" "; + //m_edCountry.SetWindowText(strData); +} + +void CClientsDlg::Security() +{ + int x=m_pApp->Allowed(RCLIENTS,true); + if(x==0) + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2) + m_bReadOnly=true; + else + m_bReadOnly=false; + + //disable PM button? + m_bPMAllowed=true; + x=m_pApp->Allowed(RPM,true); + if(x==0)//no access allowed + { + m_bPMAllowed=false; + //m_btnPM.EnableWindow(FALSE); + } +} + +void CClientsDlg::OnCloseupCbdefrate() +{ + SaveField(&m_cbRate,"defrate"); + +} + +void CClientsDlg::OnCloseupCbdeftravel() +{ + SaveField(&m_cbDefTravelRate,"deftravelrate"); +} + +void CClientsDlg::FillRatesLists() +{ + + //fill travel and regular rates list boxes + CString strData; + CString strIndex; + long lData; + bool bData; + m_cbDefTravelRate.Clear(); + m_cbRate.Clear(); + m_cbDefTravelRate.AddRow(" ","0"); + m_cbRate.AddRow(" ","0"); + rs->Query("SELECT rates.* FROM rates ORDER BY rates.name;"); + if(!rs->IsEmpty()) + { + //fill combo box with available categories + rs->MoveFirst(); + rs->FetchField("travelrate",&bData); + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + if(bData==true)//it's a travel rate + m_cbDefTravelRate.AddRow(strData,strIndex); + else + m_cbRate.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("travelrate",&bData); + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + + if(bData==true)//it's a travel rate + m_cbDefTravelRate.AddRow(strData,strIndex); + else + m_cbRate.AddRow(strData,strIndex); + } + + //select default rate + m_cbRate.SetCurSel(0); + m_cbDefTravelRate.SetCurSel(0); + + } +} + +bool CClientsDlg::EditPrompt() +{ + if(m_bEditPrompt) + { + if(AfxMessageBox("Warning: you are about to change this existing client record\r\n\r\n" + "If you want to add a new client use the ADD NEW CLIENT button instead\r\n\r\n" + "Change this client record and continue to allow other changes?",MB_YESNO)==IDYES) + { + m_bEditPrompt=false; + return true; + } + else + return false; + } + else + return true; + + +} + +void CClientsDlg::OnBtnnotes() +{ + + + +} + + +//09/20/00 long awaited consolidation routines +void CClientsDlg::OnConsolidate() +{ + + +} + +void CClientsDlg::OnBtndone() +{ + //if(m_bAddMode)//then user has pressed cancel button + //{ + // //revert to previous view and save changes + // if(m_ckShowHeadOfficeCheck.GetCheck()==TRUE) + // RefreshDisplay(1);//head office mode + // else + // RefreshDisplay(0);//normal mode + // m_bAddMode=false; + //} + //else + //{ + // + // if(m_pstrReturnValue!=NULL) + // m_pstrReturnValue->Format("%s",m_strSelectedClient); + // CDialog::OnOK(); + //} +} + +void CClientsDlg::OnKillfocusEdacctnum() +{ + SaveField(&m_edAcctNum,"acctnumber",true); +} + + + +//***************************************************** +//Menu commands added Oct 2 2002 to clean up things. +//***************************************************** +void CClientsDlg::OnNewClientrecord() +{ + CString q; + CString strTemp; + CString strTemp2; + COleDateTime dtData; + long lData; + dtData=COleDateTime::GetCurrentTime(); + strTemp.Format("New record %s",dtData.Format("%H%M%S")); + + //Get the address default strings set + SetDefaults(); + + q.Format("INSERT INTO clients ( company ) SELECT \"%s\";",strTemp); + if(!rs->Ex(q,&lData)) + { + AfxMessageBox("The new record could not be created due to\r\n" + "the error previously indicated.\r\n\r\n" + "If this problem persists and you require technical support\r\n" + "take a screenshot of the error message displayed before\r\n" + "and email it to support@ayanova.com with any other information\r\n" + "that might help."); + return; + } + + //change the newly added client to include the ID number + //why? Looks cleaner in case it gets somehow left behind + //and is guranteed unique where the temporary name is not + strTemp2.Format("New record %u",lData); + q.Format("UPDATE clients SET clients.company = \"%s\", " + "clients.city = \"%s\", clients.stateprov = \"%s\", clients.postal = \"%s\", clients.country = \"%s\" " + "WHERE (((clients.company)=\"%s\"));",strTemp2, + m_strDefaultCity,m_strDefaultStateProv,m_strDefaultPostal,m_strDefaultCountry,strTemp); + + if(!rs->Ex(q)) + { + AfxMessageBox("The new record could not be created due to\r\n" + "the error previously indicated.\r\n\r\n" + "If this problem persists and you require technical support\r\n" + "take a screenshot of the error message displayed before\r\n" + "and email it to support@ayanova.com with any other information\r\n" + "that might help."); + return; + } + + //Set this record current + m_strSelectedClient.Format("%u",lData); + + //ensure it's not set to head office mode + if(m_ckShowHeadOfficeCheck.GetCheck()) + { + m_ckShowHeadOfficeCheck.SetCheck(FALSE); + RefreshDisplay(0); + } + else + { + //display it + FillClientList(); + } + + + + + + //Highlight the client name for editing + m_edCompany.SetFocus(); + m_edCompany.SetSel(0,-1); + m_bEditPrompt=false; + + +} + + +void CClientsDlg::OnNewHeadofficerecord() +{ + CString q; + CString strTemp; + CString strTemp2; + COleDateTime dtData; + long lData; + dtData=COleDateTime::GetCurrentTime(); + strTemp.Format("New record %s",dtData.Format("%H%M%S")); + //Get the address default strings set + SetDefaults(); + q.Format("INSERT INTO clients ( company, isheadoffice ) SELECT \"%s\",True;",strTemp); + if(!rs->Ex(q,&lData)) + { + AfxMessageBox("The new record could not be created due to\r\n" + "the error previously indicated.\r\n\r\n" + "If this problem persists and you require technical support\r\n" + "take a screenshot of the error message displayed before\r\n" + "and email it to support@ayanova.com with any other information\r\n" + "that might help."); + return; + } + + //change the newly added client to include the ID number + //why? Looks cleaner in case it gets somehow left behind + //and is guranteed unique where the temporary name is not + strTemp2.Format("New record %u",lData); + q.Format("UPDATE clients SET clients.company = \"%s\", " + "clients.city = \"%s\", clients.stateprov = \"%s\", clients.postal = \"%s\", clients.country = \"%s\" " + "WHERE (((clients.company)=\"%s\"));",strTemp2, + m_strDefaultCity,m_strDefaultStateProv,m_strDefaultPostal,m_strDefaultCountry,strTemp); + + /*strTemp2.Format("New record %u",lData); + q.Format("UPDATE clients SET clients.company = \"%s\" " + "WHERE (((clients.company)=\"%s\"));",strTemp2,strTemp);*/ + + if(!rs->Ex(q)) + { + AfxMessageBox("The new record could not be created due to\r\n" + "the error previously indicated.\r\n\r\n" + "If this problem persists and you require technical support\r\n" + "take a screenshot of the error message displayed before\r\n" + "and email it to support@ayanova.com with any other information\r\n" + "that might help."); + return; + } + + //Set this record current + m_strSelectedClient.Format("%u",lData); + + //ensure it's not set to client mode + if(!m_ckShowHeadOfficeCheck.GetCheck()) + { + m_ckShowHeadOfficeCheck.SetCheck(TRUE); + RefreshDisplay(1); + } + else + { + //display it + FillClientList(); + } + + //Highlight the client name for editing + m_edCompany.SetFocus(); + m_edCompany.SetSel(0,-1); + m_bEditPrompt=false; + +} + + + +void CClientsDlg::OnUpdateNewClientrecord(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(m_bReadOnly?FALSE:TRUE); + +} + + + + +void CClientsDlg::OnUpdateNewHeadofficerecord(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(m_bReadOnly?FALSE:TRUE); +} + + +void CClientsDlg::OnEditDeletethisrecord() +{ + // Delete current record + CString q,strData; + bool bFail=false; + long lrecs; + CString strWarning; + CString strTemp; + CString strClient=m_cbClientList.GetCurrentRowID(); + + + q.Format("SELECT wo.id FROM wo WHERE (((wo.client)=%s));",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("Work orders: %u\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + q.Format("SELECT rentals.clientlink FROM rentals WHERE (((rentals.clientlink)=%s));",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("Rental / loaner records: %u\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + q.Format("SELECT units.client FROM units WHERE (((units.client)=%s));",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("Unit (equipment) records: %u\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + q.Format("SELECT pmhead.link FROM pmhead WHERE (((pmhead.isclient)=True) " +"AND ((pmhead.link)=%s));",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("Preventive maintenance schedule records: %u\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + q.Format("SELECT contacts.clientlink FROM contacts WHERE (((contacts.clientlink)=%s)); ",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("Client notebook records: %u\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + q.Format("SELECT clients.company FROM clients WHERE (((clients.headoffice)=%s)); ",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("By %u clients as their head office\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + + q.Format("SELECT client_requests.clientlink FROM client_requests " +"WHERE (((client_requests.clientlink)=%s));",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("ARAS service requests: %u\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + q.Format("SELECT clients_aras.clientlink FROM clients_aras WHERE " +"(((clients_aras.clientlink)=%s));",strClient); + if(!rs->QueryReadOnly(q)) return; + if(!rs->IsEmpty()) + { + bFail=true; + strTemp.Format("ARAS login account records: %u\r\n",rs->FetchRecordCount()); + strWarning+=strTemp; + } + + + if(!bFail)//Safe to delete + { + q.Format("DELETE clients.*, clients.id FROM clients WHERE (((clients.id)=%s));",m_cbClientList.GetCurrentRowID()); + rs->Ex(q); + //a deleted client can't be selected + m_strSelectedClient=""; + + } + else + { + + //fill combo box with available zones + //rs->MoveFirst(); + lrecs=1; + while(rs->MoveForward()) + lrecs++; + q.Format( + "This client can not be deleted right now:\r\n\r\n" + + "You can only delete a client record if it is not in use\r\n" + "anywhere else in AyaNova to protect the integrity of the\r\n" + "AyaNova database.\r\n\r\n" + + "This client record is currently in use in the following places:\r\n" + "%s" + "\r\n" + + "You have three options:\r\n" + "1) Leave this client as is (recommended)\r\n" + "2) Move all this clients data to another client\r\n" + " (use the Edit->Consolidate menu option)\r\n" + "3) Delete or change the areas listed above\r\n" + " to use a different client, then delete this client\r\n",strWarning); + m_pApp->ShowStuff(q); + } + FillClientList(); +} + +void CClientsDlg::OnUpdateEditDeletethisrecord(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(m_bReadOnly?FALSE:TRUE); +} + + +void CClientsDlg::OnEditConsolidatetwoclientstogether() +{ + CConsolidateDlg d; + d.DoModal(); + FillFields(); +} + +void CClientsDlg::OnUpdateEditConsolidatetwoclientstogether(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(m_bReadOnly?FALSE:TRUE); +} + + + +void CClientsDlg::OnClientsAras() +{ +CClientsRA d; +d.m_strCurrentClient=m_strSelectedClient; +d.DoModal(); + +} + +void CClientsDlg::OnUpdateClientsAras(CCmdUI *pCmdUI) +{ + // TODO: Add your command update UI handler code here +} + +void CClientsDlg::OnToolsOpenclientnotebook() +{ + rs->Close(); + CContactsViewDlg d; + + d.Setup(m_strSelectedClient); + + d.DoModal(); + + FillFields(); +} + +void CClientsDlg::OnUpdateToolsOpenclientnotebook(CCmdUI *pCmdUI) +{ + // TODO: Add your command update UI handler code here +} + +void CClientsDlg::OnToolsSchedulepreventivemaintenanceforthisclient() +{ + CString str,prompt; + m_edCompany.GetWindowText(str); + if(str.IsEmpty()) + { + m_edFirst.GetWindowText(str); + prompt="Schedule preventive maintenance for client: " + str + " "; + m_edLast.GetWindowText(str); + prompt=prompt+ str; + + + + } + else + prompt="Schedule preventive maintenance for client: " + str; + + //Open the PM dialog for this client + CPM d; + + //set criteria serial number + d.PreInitialize(true,false,m_strSelectedClient, prompt); + + d.DoModal(); + //added to refresh main recordset + FillFields(); +} + +void CClientsDlg::OnUpdateToolsSchedulepreventivemaintenanceforthisclient(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(m_bPMAllowed?TRUE:FALSE); + + +} + +void CClientsDlg::OnToolsDisplayrecordhistory() +{ + CString test; + rs->FetchField("company",&test); + + COleDateTime dtCreated,dtModified; + CString modifier,creator; + long m,c; + //GET RECORD STATUS FIELDS + rs->FetchField("created",&dtCreated); + rs->FetchField("modified",&dtModified); + + rs->FetchField("creator",&c); + + rs->FetchField("modifier",&m); + creator.Format("%u",c); + modifier.Format("%u",m); + + + CStatusDlg d; + d.SetValues(&creator,&modifier,&dtCreated,&dtModified); + d.DoModal(); +} + +void CClientsDlg::OnUpdateToolsDisplayrecordhistory(CCmdUI *pCmdUI) +{ + // TODO: Add your command update UI handler code here +} + +void CClientsDlg::OnClosethisscreen() +{ + if(m_pstrReturnValue!=NULL) + m_pstrReturnValue->Format("%s",m_strSelectedClient); + CDialog::OnOK(); +} + +void CClientsDlg::OnUpdateClosethisscreen(CCmdUI *pCmdUI) +{ + // TODO: Add your command update UI handler code here +} + +void CClientsDlg::OnClientMenuHelp() +{ + WinHelp(0x20083); +} + +void CClientsDlg::OnEnKillfocusPhone2() +{ + SaveField(&m_edPhone2,"phone2",true); +} + +void CClientsDlg::OnEnKillfocusPhone3() +{ + SaveField(&m_edPhone3,"phone3",true); +} + + +void CClientsDlg::OnEmaillabel() +{ + + +CString strURL; + m_edEmail.GetWindowText(strURL); + if(!strURL.IsEmpty())//do this only if there was an url + { + strURL="mailto:" + strURL; + ShellExecute(NULL,"open",strURL,NULL,NULL,SW_SHOWNORMAL); + + } + +} +void CClientsDlg::OnToolsSetaddressdefaults() +{ +CDefaultsDlg d; + d.DoModal(); +} + + + +void CClientsDlg::FillUnitList(void) +{ + CString q,strData,strIndex; + long lData; + //FILL UNIT LIST: + m_cbUnits.Clear(); + if(m_strSelectedClient.IsEmpty()) return; + + + + q.Format("SELECT units.id, [sn] & \" - \" & IIf(IsNull([company_person]),\" " +"\",[company_person]) & \" \" & IIf(IsNull([unitmodels].[description]),\" " +"\",[unitmodels].[description]) " +"& \" \" & IIf(IsNull([unitmodels].[model]),\" " +"\",[unitmodels].[model]) AS name FROM (units LEFT " +"JOIN unitmodels ON units.model = unitmodels.id) " +"LEFT JOIN nonclients ON unitmodels.manufacturer = " +"nonclients.id WHERE (((units.client)=%s)) ORDER BY " +"units.sn;",m_strSelectedClient); +#ifdef _DEBUG + //m_pApp->ShowStuff(q); +#endif + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty()) + { + do + { + rs2->FetchField("name",&strData); + strData.TrimRight(); + strData.TrimRight('-'); + rs2->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbUnits.AddRow(strData,strIndex); + }while(rs2->MoveForward()); + } + else + m_cbUnits.AddRow(" < No units >","0"); + + m_cbUnits.Select(0); +} + + + +void CClientsDlg::OnStnClickedLblUnits() +{ + CString strUnit=m_cbUnits.GetCurrentRowID(); + CUnitsDlg d; + if(strUnit!="0" && !strUnit.IsEmpty()) + d.m_strSelectedUnit=strUnit; + d.DoModal(); + + //added v1.9.4.5 + //not refreshing unit list when new one added or old one removed + FillFields(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.h new file mode 100644 index 0000000..13756b9 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsDlg.h @@ -0,0 +1,225 @@ +#if !defined(AFX_CLIENTSDLG_H__8983F421_114C_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_CLIENTSDLG_H__8983F421_114C_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ClientsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CClientsDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +#include "statusdlg.h" +#include "ResizeCtrl.h" +#include "afxwin.h" +#include "defaultsdlg.h" +class CClientsDlg : public CDialog +{ +// Construction +public: + CResizeCtrl m_resize; + bool EditPrompt(); + bool m_bEditPrompt; + void FillRatesLists(); + void Security(); + bool m_bReadOnly; + CString m_strForceSelection; + void SetDefaults(); + ~CClientsDlg(); + + bool FillHeadOfficeList(); + + void BlankAllFields(bool bSetDefaults,bool bEnable); + CString m_strSelectedClient; + void SetReturnString(CString *ret); + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool SaveField(CgzCombo* cbControl,CString fldname); + bool SaveField(CButton* ckControl,CString fldname); + bool SaveField(CDateTimeCtrl* dtControl,CString fldname); + bool UpdateModified(); + //------------------------------- + + bool FillContractList(); + bool FillTechList(); + bool FillZoneList(); + bool FillFields(); + bool AddRecord(bool IsHeadOffice); + bool RefreshDisplay(int dMode/*0=standard 1=headoffice 2=add*/); + bool FillClientList(); + bool m_bAddMode; + CClientsDlg(CWnd* pParent = NULL); // standard constructor +CSpApp* m_pApp; +GZRset* rs; +GZRset* rs2; +CString * m_pstrReturnValue; +// Dialog Data + //{{AFX_DATA(CClientsDlg) + enum { IDD = IDD_CLIENTS }; + CButton m_btnNotes; + CButton m_btnDone; + CEdit m_edAcctNum; + CgzCombo m_cbDefTravelRate; + CgzCombo m_cbRate; + CButton m_btnPM; + CLabel m_lblHist; + CLabel m_lblZone; + CgzCombo m_cbZone; + CButton m_ckBillHead; + CLabel m_lblAlert; + CEdit m_edAlert; + CStatic m_lblTechNotes; + CEdit m_edTechNotes; + CStatic m_lblStreet; + CEdit m_edStreet; + CStatic m_lblStateProv; + CEdit m_edStateProv; + CLabel m_lblPreferTech; + CgzCombo m_cbPreferTech; + CStatic m_lblPostal; + CEdit m_edPostal; + CStatic m_lblPhone; + CEdit m_edPhone; + CStatic m_lblMail; + CEdit m_edMail; + CStatic m_lblLast; + CEdit m_edLast; + CStatic m_lblHeadOffice; + CgzCombo m_cbHeadOffice; + CStatic m_lblGenNotes; + CEdit m_edGenNotes; + CStatic m_lblFirst; + CEdit m_edFirst; + CStatic m_lblFax; + CEdit m_edFax; + CStatic m_lblExtension; + CEdit m_edExtension; + CLabel m_lblEmail; + CEdit m_edEmail; + CButton m_btnDelete; + CStatic m_lblCountry; + CEdit m_edCountry; + CLabel m_lblContract; + CStatic m_lblContractExpiry; + CDateTimeCtrl m_dtContractExpiryDate; + CgzCombo m_cbContract; + CButton m_btnConsolidate; + CStatic m_lblCompany; + CEdit m_edCompany; + CStatic m_lblCity; + CEdit m_edCity; + CButton m_btnAddHead; + CButton m_btnAdd; + CButton m_ckShowHeadOfficeCheck; + CStatic m_lblClientListLabel; + CgzCombo m_cbClientList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CClientsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CClientsDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnCloseupClientlist(); + afx_msg void OnHeadoffice(); + afx_msg void OnCloseupContract(); + afx_msg void OnDelete(); + afx_msg void OnAdd(); + afx_msg void OnAddhead(); + virtual void OnOK(); + afx_msg void OnKillfocusFirstname(); + afx_msg void OnKillfocusCompany(); + afx_msg void OnKillfocusLastname(); + afx_msg void OnKillfocusMailaddress(); + afx_msg void OnKillfocusStreet(); + afx_msg void OnKillfocusCity(); + afx_msg void OnKillfocusStateprovince(); + afx_msg void OnKillfocusPostal(); + afx_msg void OnKillfocusCountry(); + afx_msg void OnKillfocusPhone(); + afx_msg void OnKillfocusExtension(); + afx_msg void OnKillfocusEmail(); + afx_msg void OnKillfocusFax(); + afx_msg void OnCloseupHeadofficepicker(); + afx_msg void OnBillhead(); + afx_msg void OnKillfocusTechnotes(); + afx_msg void OnKillfocusGeneralnotes(); + afx_msg void OnCloseupZone(); + afx_msg void OnCloseupPrefertech(); + afx_msg void OnDatetimechangeContractexpirydate(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKillfocusAlert(); + afx_msg void OnZonelabel(); + afx_msg void OnContractlabel(); + afx_msg void OnHistory(); + afx_msg void OnBtnpm(); + afx_msg void OnCloseupCbdefrate(); + afx_msg void OnCloseupCbdeftravel(); + afx_msg void OnBtnnotes(); + afx_msg void OnConsolidate(); + afx_msg void OnBtndone(); + afx_msg void OnKillfocusEdacctnum(); + afx_msg void OnClientsAras(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnNewClientrecord(); + afx_msg void OnUpdateNewClientrecord(CCmdUI *pCmdUI); + afx_msg void OnNewHeadofficerecord(); + afx_msg void OnUpdateNewHeadofficerecord(CCmdUI *pCmdUI); + afx_msg void OnEditDeletethisrecord(); + afx_msg void OnUpdateEditDeletethisrecord(CCmdUI *pCmdUI); + afx_msg void OnEditConsolidatetwoclientstogether(); + afx_msg void OnUpdateEditConsolidatetwoclientstogether(CCmdUI *pCmdUI); + afx_msg void OnUpdateClientsAras(CCmdUI *pCmdUI); + afx_msg void OnToolsOpenclientnotebook(); + afx_msg void OnUpdateToolsOpenclientnotebook(CCmdUI *pCmdUI); + afx_msg void OnToolsSchedulepreventivemaintenanceforthisclient(); + afx_msg void OnUpdateToolsSchedulepreventivemaintenanceforthisclient(CCmdUI *pCmdUI); + afx_msg void OnToolsDisplayrecordhistory(); + afx_msg void OnUpdateToolsDisplayrecordhistory(CCmdUI *pCmdUI); + afx_msg void OnClosethisscreen(); + afx_msg void OnUpdateClosethisscreen(CCmdUI *pCmdUI); + afx_msg void OnClientMenuHelp(); + void OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu); + + // User is allowed into PM? + bool m_bPMAllowed; + + CEdit m_edPhone2; + CEdit m_edPhone3; + afx_msg void OnEnKillfocusPhone2(); + afx_msg void OnEnKillfocusPhone3(); + afx_msg void OnEmaillabel(); + + afx_msg void OnToolsSetaddressdefaults(); + + CgzCombo m_cbUnits; + CLabel m_lblUnits; + + void FillUnitList(void); + afx_msg void OnStnClickedLblUnits(); +private: + CString m_strDefaultCity; + CString m_strDefaultStateProv; + CString m_strDefaultPostal; + CString m_strDefaultCountry; + long lPreferredTech; + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CLIENTSDLG_H__8983F421_114C_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.cpp new file mode 100644 index 0000000..4c694d1 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.cpp @@ -0,0 +1,546 @@ +// ClientsRA.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ClientsRA.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CClientsRA dialog + + +CClientsRA::CClientsRA(CWnd* pParent /*=NULL*/) + : CDialog(CClientsRA::IDD, pParent) + , m_bDontCallSaveRecord(false) +{ + //{{AFX_DATA_INIT(CClientsRA) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + //Initialize recordset pointer + rs=m_pApp->rsPool->GetRS("CClientsRA"); + m_bAddMode=false; +} + + +void CClientsRA::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CClientsRA) + DDX_Control(pDX, IDC_LBL_HISTORY, m_lblHistory); + DDX_Control(pDX, IDC_EDPW, m_edPassword); + DDX_Control(pDX, IDC_EDPRIVATENOTES, m_edPrivateNotes); + DDX_Control(pDX, IDC_EDLOGINID, m_edLoginID); + DDX_Control(pDX, IDC_CKWOREPORTS, m_ckWOReports); + DDX_Control(pDX, IDC_CKVIEWWORKORDERS, m_ckViewWorkorders); + DDX_Control(pDX, IDC_CKVIEWSTATUS, m_ckViewStatus); + DDX_Control(pDX, IDC_CKVIEWREQUESTS, m_ckViewRequests); + DDX_Control(pDX, IDC_CKREQUEST_SERVICE, m_ckRequestService); + DDX_Control(pDX, IDC_CBCLIENT, m_cbClient); + DDX_Control(pDX, IDC_CBACCOUNT, m_cbAccount); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CClientsRA, CDialog) + //{{AFX_MSG_MAP(CClientsRA) + ON_CBN_CLOSEUP(IDC_CBCLIENT, OnCloseupCbclient) + ON_CBN_CLOSEUP(IDC_CBACCOUNT, OnCloseupCbaccount) + ON_COMMAND(ID_CLIENT_RA_ADD, OnClientRaAdd) + ON_COMMAND(ID_CLIENT_RA_CLOSE, OnClientRaClose) + ON_COMMAND(ID_CLIENT_RA_DELETE, OnClientRaDelete) + ON_EN_KILLFOCUS(IDC_EDLOGINID, OnKillfocusEdloginid) + ON_EN_KILLFOCUS(IDC_EDPRIVATENOTES, OnKillfocusEdprivatenotes) + ON_EN_KILLFOCUS(IDC_EDPW, OnKillfocusEdpw) + ON_BN_CLICKED(IDC_CKWOREPORTS, OnCkworeports) + ON_BN_CLICKED(IDC_CKVIEWWORKORDERS, OnCkviewworkorders) + ON_BN_CLICKED(IDC_CKVIEWSTATUS, OnCkviewstatus) + ON_BN_CLICKED(IDC_CKVIEWREQUESTS, OnCkviewrequests) + ON_BN_CLICKED(IDC_CKREQUEST_SERVICE, OnCkrequestService) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CClientsRA message handlers + +void CClientsRA::OnOK() +{} + +CClientsRA::~CClientsRA() +{ +//delete rs; + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +BOOL CClientsRA::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + FillClientList(); + FillAccountList(); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CClientsRA::FillClientList() +{ +CString q,strData,strIndex; +long lData; + +//fill client list +m_strCurrentAccount.Empty(); + m_cbClient.Clear(); + ClearAllEntries(); + + q.Format("SELECT clients.id, clients.company FROM clients " + "ORDER BY clients.company;"); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + return; + + do{ + rs->FetchField("company",&strData); + + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbClient.AddRow(strData,strIndex); + + + }while(rs->MoveForward()); + + //handle empty selection or reselect current one + if(m_strCurrentClient.IsEmpty()) //first time in + { + m_cbClient.SetCurSel(0); + m_strCurrentClient=m_cbClient.GetCurrentRowID(); + + } + else//something valid was selected before so stick with it + m_cbClient.Select(m_strCurrentClient); + + + + + +} + +void CClientsRA::FillAccountList() +{ + CString q,strData,strIndex; +long lData; +//FILL ACCOUNT LIST + m_cbAccount.Clear(); + + q.Format("SELECT clients_aras.id, clients_aras.loginid " + "FROM clients_aras " + "WHERE (((clients_aras.clientlink)=%s));",m_strCurrentClient); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + { + AllowEntry(false); + return; + } + + do{ + rs->FetchField("loginid",&strData); + + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbAccount.AddRow(strData,strIndex); + + + }while(rs->MoveForward()); + + //done this way in case there is some reason later + //to persist the selected account + //m_strCurrentAccount.Empty(); + //handle empty selection or reselect current one + if(m_strCurrentAccount.IsEmpty()) //first time in + { + m_cbAccount.SetCurSel(0); + m_strCurrentAccount=m_cbAccount.GetCurrentRowID(); + + } + else//something valid was selected before so stick with it + m_cbAccount.Select(m_strCurrentAccount); + + FillFields(); +} + +void CClientsRA::AllowEntry(bool bAllow) +{ + BOOL e=bAllow?TRUE:FALSE; + m_ckRequestService.EnableWindow(e); + m_ckViewRequests.EnableWindow(e); + m_ckViewStatus.EnableWindow(e); + m_ckViewWorkorders.EnableWindow(e); + m_ckWOReports.EnableWindow(e); + m_edLoginID.EnableWindow(e); + m_edPassword.EnableWindow(e); + m_edPrivateNotes.EnableWindow(e); + m_lblHistory.EnableWindow(e); + + +} + +void CClientsRA::ClearAllEntries() +{ + m_ckRequestService.SetCheck(FALSE); + m_ckViewRequests.SetCheck(FALSE); + m_ckViewStatus.SetCheck(FALSE); + m_ckViewWorkorders.SetCheck(FALSE); + m_ckWOReports.SetCheck(FALSE); + m_edLoginID.SetWindowText(""); + m_edPassword.SetWindowText(""); + m_edPrivateNotes.SetWindowText(""); + m_lblHistory.SetWindowText(""); +} + +void CClientsRA::FillFields() +{ + CString q; + bool bData; + CString strData; + COleDateTime dtData; + CString strHistory; + ClearAllEntries(); +if(m_strCurrentAccount.IsEmpty()) m_strCurrentAccount="0";//so that the following normal process happens + + q.Format("SELECT clients_aras.*, [users].[last] & \", \" & [users].[first] AS CREATED_BY, " + "[users_1].[last] & \", \" & [users_1].[first] AS LAST_EDITED_BY " +"FROM (clients_aras LEFT JOIN users ON clients_aras.creator = users.id) LEFT JOIN users AS users_1 ON clients_aras.modifier = users_1.id " +"WHERE (((clients_aras.id)=%s));",m_strCurrentAccount); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + { + AllowEntry(false); + return; + } + else + AllowEntry(true); + + rs->FetchField("loginid",&strData); + m_edLoginID.SetWindowText(strData); + + rs->FetchField("loginpw",&strData); + m_edPassword.SetWindowText(strData); + + rs->FetchField("private_notes",&strData); + m_edPrivateNotes.SetWindowText(strData); + + rs->FetchField("view_wo_status", &bData); + m_ckViewStatus.SetCheck(bData?TRUE:FALSE); + + rs->FetchField("request_service", &bData); + m_ckRequestService.SetCheck(bData?TRUE:FALSE); + + rs->FetchField("view_request_list", &bData); + m_ckViewRequests.SetCheck(bData?TRUE:FALSE); + + rs->FetchField("wo_view", &bData); + m_ckViewWorkorders.SetCheck(bData?TRUE:FALSE); + + rs->FetchField("wo_report", &bData); + m_ckWOReports.SetCheck(bData?TRUE:FALSE); + + + //HISTORY + rs->FetchField("CREATED_BY",&strData); + strHistory="Account created by: " + strData; + rs->FetchField("created",&dtData); + strHistory+=" On: " + dtData.Format() + "\r\n"; + + rs->FetchField("LAST_EDITED_BY",&strData); + strHistory+="Last modified by: " + strData; + rs->FetchField("modified",&dtData); + strHistory+=" On: " + dtData.Format() + "\r\n"; + + + rs->FetchField("last_login_date",&dtData); + strHistory+="Last remote login on: " + dtData.Format(); + m_lblHistory.SetWindowText(strHistory); + + +} + + +void CClientsRA::OnCloseupCbclient() +{ + if(m_strCurrentClient==m_cbClient.GetCurrentRowID()) + return;//do nothing if same client. Fixes bounce problem + ClearAllEntries(); + m_strCurrentAccount.Empty(); + m_strCurrentClient=m_cbClient.GetCurrentRowID(); + FillAccountList(); +} + + +void CClientsRA::OnCloseupCbaccount() +{ + if(m_strCurrentAccount==m_cbAccount.GetCurrentRowID()) + return;//fix for bounce problem + m_strCurrentAccount=m_cbAccount.GetCurrentRowID(); + FillFields(); + +} + +void CClientsRA::OnClientRaAdd() +{ + if(m_bAddMode) + { + //save record + if(SaveRecord(false)) + { + m_cbAccount.EnableWindow(TRUE); + m_cbClient.EnableWindow(TRUE); + m_bAddMode=false; + m_strCurrentAccount.Empty(); + FillAccountList(); + } + } + else + { + ClearAllEntries(); + AllowEntry(true); + m_bAddMode=true; + m_cbAccount.EnableWindow(FALSE); + m_cbClient.EnableWindow(FALSE); + } + + HandleMenuMode(); + + + +} + +void CClientsRA::OnClientRaClose() +{ + if(m_bAddMode) + { + AfxMessageBox("You can't close while adding a record."); + return; + } + + CDialog::OnOK(); + +} + +void CClientsRA::OnClientRaDelete() +{ + if(m_bAddMode)//is cancel, not delete + { + m_bAddMode=false; + m_cbAccount.EnableWindow(TRUE); + m_cbClient.EnableWindow(TRUE); + HandleMenuMode(); + FillAccountList(); + return; + } + + //Delete a record +CString q; + +q.Format("DELETE clients_aras.*, clients_aras.id FROM clients_aras " + "WHERE (((clients_aras.id)=%s));",m_strCurrentAccount); +if(AfxMessageBox("Delete this account?\r\nAre you sure?",MB_YESNO)==IDYES) +{ + m_strCurrentAccount.Empty(); + ClearAllEntries(); +rs->Ex(q); +FillAccountList(); +} + + + + + +} + +void CClientsRA::HandleMenuMode() +{ + CString strDeleteText; + CString strAddText; + + if(m_bAddMode) + { + strDeleteText="Ca&ncel add"; + strAddText="&Save"; + } + else + { + strDeleteText="&Delete"; + strAddText="&Add"; + } + +CMenu* pMenu=this->GetMenu(); +pMenu->ModifyMenu(ID_CLIENT_RA_ADD,MF_BYCOMMAND,ID_CLIENT_RA_ADD,strAddText); +pMenu->ModifyMenu(ID_CLIENT_RA_DELETE,MF_BYCOMMAND,ID_CLIENT_RA_DELETE,strDeleteText); +this->DrawMenuBar(); +} + +bool CClientsRA::SaveRecord(bool bUpdate) +{ + //don't do this if an update request and in add mode + if(m_bAddMode && bUpdate==true) return false; + + GZK k; + + CString q,login,pw,notes,str,loginhashed; + CString RequestService, ViewRequests, ViewStatus, ViewWorkorders, WOReports; + COleDateTime dtNow, dtNever; + dtNow=COleDateTime::GetCurrentTime(); + dtNever.SetDateTime(1968,03,12,0,0,0); + + m_edLoginID.GetWindowText(login); + if(login.IsEmpty()) + { + AfxMessageBox("Login can not be blank"); + return false; + + } + loginhashed=login; + k.GZHash(&loginhashed); + + m_edPassword.GetWindowText(pw); + m_edPrivateNotes.GetWindowText(notes); + notes.Replace("\"","'"); + + RequestService=m_ckRequestService.GetCheck() ? "True":"False"; + ViewRequests=m_ckViewRequests.GetCheck() ? "True":"False"; + ViewStatus=m_ckViewStatus.GetCheck() ? "True":"False"; + ViewWorkorders=m_ckViewWorkorders.GetCheck() ? "True":"False"; + WOReports=m_ckWOReports.GetCheck() ? "True":"False"; + + q.Format("SELECT users.login FROM users WHERE (((users.login)=\"%s\")); ",loginhashed); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + AfxMessageBox( + "Security warning: The login assigned to this client can not be used.\r\n" + "The reason is that the same login is in use already by an AyaNova user.\r\n\r\n" + + "Login names must be unique amongst all AyaNova users and ARAS client accounts.\r\n\r\n" + + "Change the login name to something unique before saving.",MB_ICONSTOP); + m_edLoginID.SetFocus(); + return false; + + } + + + if(bUpdate==false)//insert new record + { + //Check if login name already exists and disallow if so + q.Format("SELECT clients.company FROM clients_aras LEFT JOIN " +"clients ON clients_aras.clientlink = clients.id WHERE " +"(((clients_aras.loginid)=\"%s\"));",login); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + rs->FetchField("company",&str); + q.Format( + "Problem: No two ARAS client login id's can be the same.\r\n" + "The account login id \"%s\" is already in use by \r\n" + "an existing account for %s\r\n" + "This record can not be saved until the login id is changed.\r\n",login,str); + + AfxMessageBox(q,MB_ICONSTOP); + m_edLoginID.SetFocus(); + return false; + + } + + + + q.Format("INSERT INTO clients_aras ( clientlink, loginid, loginpw, view_wo_status, " + "search_history, wo_view, wo_report, request_service, view_request_list, private_notes, " + "last_login_date, creator, modifier, created, modified ) " + "SELECT %s , \"%s\", \"%s\", %s, %s , %s, %s, %s, %s, \"%s\", #%s#, %u, %u, #%s#, #%s#;" + ,m_strCurrentClient,login, pw,ViewStatus, "False",ViewWorkorders,WOReports,RequestService,ViewRequests,notes, + dtNever.Format(_T("%m/%d/%Y %H:%M:%S")),m_pApp->m_lusrID,m_pApp->m_lusrID, + dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),dtNow.Format(_T("%m/%d/%Y %H:%M:%S"))); + } + + + else//update existing record + { + //check if login name already exists for other clients than this one + //if so then disallow save + + //Query for any user other than current account with same password + q.Format("SELECT clients.company FROM clients_aras LEFT JOIN " +"clients ON clients_aras.clientlink = clients.id WHERE " +"(((clients_aras.loginid)=\"%s\") AND ((clients_aras.id)<>%s));",login,m_strCurrentAccount); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + rs->FetchField("company",&str); + q.Format( + "Problem: No two ARAS client login id's can be the same.\r\n" + "The account login id \"%s\" is already in use by \r\n" + "an existing account for %s\r\n" + "This record can not be saved until the login id is changed.\r\n",login,str); + + AfxMessageBox(q,MB_ICONSTOP); + //m_edLoginID.SetFocus(); + + return false; + + } + + + q.Format("UPDATE clients_aras SET loginid=\"%s\", loginpw=\"%s\", view_wo_status=%s, search_history=False, " + "wo_view=%s, wo_report=%s, request_service=%s, view_request_list=%s, " + "private_notes=\"%s\", modifier=%u, modified=#%s# " + "WHERE (((clients_aras.id)=%s));", + login,pw,ViewStatus,ViewWorkorders,WOReports,RequestService,ViewRequests,notes,m_pApp->m_lusrID, + dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),m_strCurrentAccount); + + } + + return(rs->Ex(q)); + + + +} + +void CClientsRA::OnKillfocusEdloginid() +{ + if(m_bDontCallSaveRecord) return; + m_bDontCallSaveRecord=true; + if(SaveRecord(true)) + { + if(!m_bAddMode) + FillAccountList(); + } + m_bDontCallSaveRecord=false; + +} + +void CClientsRA::OnKillfocusEdprivatenotes() +{SaveRecord(true);} + +void CClientsRA::OnKillfocusEdpw() +{SaveRecord(true);} + +void CClientsRA::OnCkworeports() +{SaveRecord(true);} + +void CClientsRA::OnCkviewworkorders() +{SaveRecord(true);} + +void CClientsRA::OnCkviewstatus() +{SaveRecord(true);} + +void CClientsRA::OnCkviewrequests() +{SaveRecord(true);} + +void CClientsRA::OnCkrequestService() +{SaveRecord(true);} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.h new file mode 100644 index 0000000..9182c5f --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ClientsRA.h @@ -0,0 +1,91 @@ +#if !defined(AFX_CLIENTSRA_H__992FAD64_D5A5_4CCF_A1AE_AD3F5224139B__INCLUDED_) +#define AFX_CLIENTSRA_H__992FAD64_D5A5_4CCF_A1AE_AD3F5224139B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ClientsRA.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CClientsRA dialog +#include "gzrset.h" +//#include "label.h" +//#include "gzlistbox.h" +#include "gzcombo.h" +#include "gzk.h" + +class CClientsRA : public CDialog +{ +// Construction +public: + ~CClientsRA(); + CString m_strCurrentClient; + CClientsRA(CWnd* pParent = NULL); // standard constructor +CSpApp* m_pApp; + GZRset* rs; + bool m_bAddMode; +// Dialog Data + //{{AFX_DATA(CClientsRA) + enum { IDD = IDD_CLIENTS_RA }; + CStatic m_lblHistory; + CEdit m_edPassword; + CEdit m_edPrivateNotes; + CEdit m_edLoginID; + CButton m_ckWOReports; + CButton m_ckViewWorkorders; + CButton m_ckViewStatus; + CButton m_ckViewRequests; + CButton m_ckRequestService; + CgzCombo m_cbClient; + CgzCombo m_cbAccount; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CClientsRA) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CClientsRA) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnCloseupCbclient(); + afx_msg void OnCloseupCbaccount(); + afx_msg void OnClientRaAdd(); + afx_msg void OnClientRaClose(); + afx_msg void OnClientRaDelete(); + afx_msg void OnKillfocusEdloginid(); + afx_msg void OnKillfocusEdprivatenotes(); + afx_msg void OnKillfocusEdpw(); + afx_msg void OnCkworeports(); + afx_msg void OnCkviewworkorders(); + afx_msg void OnCkviewstatus(); + afx_msg void OnCkviewrequests(); + afx_msg void OnCkrequestService(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + bool SaveRecord(bool bUpdate); + void HandleMenuMode(); + void FillFields(); + void ClearAllEntries(); + void AllowEntry(bool bAllow); + CString m_strCurrentAccount; + void FillAccountList(); + void FillClientList(); +public: + // Used by saverecord and OnKillFocusEdLoginID to prevent looping error dialog + bool m_bDontCallSaveRecord; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CLIENTSRA_H__992FAD64_D5A5_4CCF_A1AE_AD3F5224139B__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Common.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Common.h new file mode 100644 index 0000000..84b7ff0 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Common.h @@ -0,0 +1,23 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#ifndef _QWORD_DEFINED +#define _QWORD_DEFINED +typedef __int64 QWORD, *LPQWORD; +#endif + +#define MAKEQWORD(a, b) \ + ((QWORD)( ((QWORD) ((DWORD) (a))) << 32 | ((DWORD) (b)))) + +#define LODWORD(l) \ + ((DWORD)(l)) +#define HIDWORD(l) \ + ((DWORD)(((QWORD)(l) >> 32) & 0xFFFFFFFF)) + +// Read 4K of data at a time (used in the C++ streams, Win32 I/O, and assembly functions) +#define MAX_BUFFER_SIZE 4096 + +// Map a "view" size of 10MB (used in the filemap function) +#define MAX_VIEW_SIZE 10485760 + +#endif diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.cpp new file mode 100644 index 0000000..e2d8cc8 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.cpp @@ -0,0 +1,196 @@ +// ConsolidateDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ConsolidateDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CConsolidateDlg dialog + + +CConsolidateDlg::CConsolidateDlg(CWnd* pParent /*=NULL*/) + : CDialog(CConsolidateDlg::IDD, pParent) +{ + + //{{AFX_DATA_INIT(CConsolidateDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_pApp = (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Consolidate clients dialog"); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + +rs=m_pApp->rsPool->GetRS("CConsolidateDlg"); + + +} + + +CConsolidateDlg::~CConsolidateDlg() +{ +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CConsolidateDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CConsolidateDlg) + DDX_Control(pDX, IDC_CBTO, m_cbTo); + DDX_Control(pDX, IDC_CBFROM, m_cbFrom); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNCONSOLIDATE, m_btnConsolidate); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CConsolidateDlg, CDialog) + //{{AFX_MSG_MAP(CConsolidateDlg) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_BN_CLICKED(IDC_BTNCONSOLIDATE, OnBtnconsolidate) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CConsolidateDlg message handlers + +void CConsolidateDlg::OnOK() +{ + //Do nothing enter key workaround + + +} + +void CConsolidateDlg::OnBtndone() +{ + CDialog::OnOK(); + +} + + +//Doooooo-iiiiiiitttttttt...... +void CConsolidateDlg::OnBtnconsolidate() +{ + + CString q,from,to; + + from=m_cbFrom.GetCurrentRowID(); + to=m_cbTo.GetCurrentRowID(); + + + + //validate the two entries + //something in each one: + if(from.IsEmpty() || to.IsEmpty() || from=="0" || to=="0") + { + AfxMessageBox("You must select a client from each list to proceed."); + return; + } + //Not the same: + if(from==to) + { + AfxMessageBox("Invalid selection (they can't be the same)"); + return; + } + +//warning: + AfxMessageBox("Warning: all other users must close this program now to avoid database corruption.\r\n" + "This operation will make changes to nearly every table in the entire database\r\n" + "Note: this change will not currently update the Preventive maintenance area of the program\r\n" + "If you use Preventive Maintenance and the client being consolidated is used there\r\n" + "you will need to manually change them\r\n" + "\r\nMake sure you are the only user running this program before clicking on OK"); + + if(AfxMessageBox("You're absolutely 100% certain no one else is running this program?\r\nClick NO to cancel without consolidating",MB_YESNO)!=IDYES) + return; + + //are you sure? + if(AfxMessageBox("Warning: this operation can not be reversed.\r\n" + "You're sure you want to do this?",MB_YESNO|MB_DEFBUTTON2)!=IDYES) + return; + + + //run the change queries (alphabetical order by table) + + //CONTACTS + q.Format("UPDATE contacts SET contacts.clientlink = %s " + "WHERE (((contacts.clientlink)=%s));",to,from); + rs->Ex(q); + + /*//PMSCHEDULES + q.Format("UPDATE pmschedules SET pmschedules.client = %s " + "WHERE (((pmschedules.client)=%s));",to,from); + rs->Ex(q); + */ + + //RENTALS + q.Format("UPDATE rentals SET rentals.clientlink = %s " + "WHERE (((rentals.clientlink)=%s));",to,from); + rs->Ex(q); + + //STATUSVIEWS + q.Format("UPDATE statusviews SET statusviews.client = %s " + "WHERE (((statusviews.client)=%s));",to,from); + rs->Ex(q); + + //UNITS + q.Format("UPDATE units SET units.client = %s " + "WHERE (((units.client)=%s));",to,from); + rs->Ex(q); + + //Workorders + q.Format("UPDATE wo SET wo.client = %s " + "WHERE (((wo.client)=%s));",to,from); + rs->Ex(q); + + AfxMessageBox("All done!\r\nYou might not see the changes take effect on the main\r\n" + "workorder screen until you refresh the display"); + +} + + + + +BOOL CConsolidateDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CString strData, strIndex,q; + long lData; + q="SELECT clients.id, clients.company AS compname FROM clients " + "ORDER BY clients.company;"; + rs->Query(q); + if(rs->IsEmpty()) + { + AfxMessageBox("Can't find any clients, that's wierd."); + return false; + } + + m_cbFrom.AddRow(" Select...","0"); + m_cbTo.AddRow(" Select...","0"); + + do + { + rs->FetchField("compname",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbFrom.AddRow(strData,strIndex); + m_cbTo.AddRow(strData,strIndex); + + }while(rs->MoveForward()); + + m_cbFrom.Select(0); + m_cbTo.Select(0); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.h new file mode 100644 index 0000000..659508d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ConsolidateDlg.h @@ -0,0 +1,56 @@ +#if !defined(AFX_CONSOLIDATEDLG_H__1FD4A321_8EDE_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_CONSOLIDATEDLG_H__1FD4A321_8EDE_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ConsolidateDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CConsolidateDlg dialog +#include "gzcombo.h" +#include "gzrset.h" + +class CConsolidateDlg : public CDialog +{ +// Construction +public: + ~CConsolidateDlg(); + CConsolidateDlg(CWnd* pParent = NULL); // standard constructor +CSpApp* m_pApp; +GZRset* rs; +// Dialog Data + //{{AFX_DATA(CConsolidateDlg) + enum { IDD = IDD_CONSOLIDATE }; + CgzCombo m_cbTo; + CgzCombo m_cbFrom; + CButton m_btnDone; + CButton m_btnConsolidate; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CConsolidateDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CConsolidateDlg) + virtual void OnOK(); + afx_msg void OnBtndone(); + afx_msg void OnBtnconsolidate(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONSOLIDATEDLG_H__1FD4A321_8EDE_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.cpp new file mode 100644 index 0000000..3c1c724 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.cpp @@ -0,0 +1,212 @@ +// ContactDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ContactDlg.h" +#include "mailmsgdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CContactDlg dialog + + +CContactDlg::CContactDlg(CWnd* pParent /*=NULL*/) +: CDialog(CContactDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CContactDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: ContactDlg screen"); + rs->SetConnect(m_pApp->strConnectString); + */ +//Initialize recordset pointer +rs=m_pApp->rsPool->GetRS("CContactDlg"); +m_bEditMode=false;//add mode by default +} + +CContactDlg::~CContactDlg() +{ + //delete rs; +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CContactDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CContactDlg) + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_DTTIME, m_dtTime); + DDX_Control(pDX, IDC_DTDATE, m_dtDate); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CContactDlg, CDialog) +//{{AFX_MSG_MAP(CContactDlg) +ON_BN_CLICKED(IDC_BTNFOLLOWUP, OnBtnfollowup) +ON_BN_CLICKED(IDC_BTNEXITNOSAVE, OnBtnexitnosave) +ON_BN_CLICKED(IDC_BTNEXITSAVE, OnBtnexitsave) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CContactDlg message handlers + + + + + + + +//***************************************************** +void CContactDlg::Setup(CString strClientID,CString strRecordID) +{ + m_strClientID=strClientID; + m_strRecordID=strRecordID; + if(m_strRecordID!="0") + m_bEditMode=true; + +} + + + +//**************************************************** +BOOL CContactDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + if(m_bEditMode) + FillFields(); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + +void CContactDlg::OnBtnfollowup() +{ + CString msg,sub,q,clientname; + COleDateTime dtData; + CString datestring; + + m_edNotes.GetWindowText(msg); + if(msg.IsEmpty()) + { + AfxMessageBox("There are no notes to send"); + return; + + } + //1.9.3.0 + msg.Replace("\"","''"); + //Get date + m_dtDate.GetTime(dtData); + datestring = dtData.Format(VAR_DATEVALUEONLY); + + //Get time + m_dtTime.GetTime(dtData); + datestring += " " + dtData.Format(VAR_TIMEVALUEONLY); + + //jam together + dtData.ParseDateTime(datestring); + + + q.Format("SELECT IIf(IsNull([clients].[company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]) AS cname " + "FROM clients WHERE (((clients.id)=%s));",m_strClientID); + rs->Query(q); + if(!rs->IsEmpty()) + { + rs->FetchField("cname",&clientname); + sub="Note on client: " + clientname + " " + dtData.Format(); + } + else + { + sub="Note on client: " + dtData.Format(); + } + + CMailMsgDlg d; + d.m_bNoRE=true;//don't put a RE: in front of subject or >'s in front of text lines + d.SetForwardInfo(&sub,&msg); + d.DoModal(); +} + +void CContactDlg::OnBtnexitnosave() +{ + CDialog::OnOK(); + +} + +void CContactDlg::OnBtnexitsave() +{ + COleDateTime dtData; + CString datestring,notes; + + m_edNotes.GetWindowText(notes); + if(notes.IsEmpty()) + { + AfxMessageBox("No data to save"); + return; + + } + + //1.9.3.0 + notes.Replace("\"","''"); + + //Get date + m_dtDate.GetTime(dtData); + datestring = dtData.Format(VAR_DATEVALUEONLY); + + //Get time + m_dtTime.GetTime(dtData); + datestring += " " + dtData.Format(VAR_TIMEVALUEONLY); + + //jam together + dtData.ParseDateTime(datestring); + + + CString q; + if(m_bEditMode) + { + q.Format("UPDATE contacts SET contacts.[date] = #%s#, contacts.staff = %u, " + "contacts.notes = \"%s\", contacts.clientlink = %s, contacts.indexed = False " + "WHERE (((contacts.id)=%s));",dtData.Format(_T("%m/%d/%Y %H:%M:%S")),m_pApp->m_lusrID,notes,m_strClientID, + m_strRecordID); + } + else + { + q.Format("INSERT INTO contacts ( [date], staff, notes, clientlink ) " + "SELECT #%s#, %u,\"%s\", %s;",dtData.Format(_T("%m/%d/%Y %H:%M:%S")),m_pApp->m_lusrID,notes,m_strClientID); + } + + + rs->Ex(q); + rs->Close(); + rs->Close(); + CDialog::OnOK(); +} + + +//Populate with existing data if in edit mode +void CContactDlg::FillFields() +{ + CString q,notes; + COleDateTime dtData; + q.Format("SELECT contacts.date, contacts.notes FROM contacts " + "WHERE (((contacts.id)=%s));",m_strRecordID); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + rs->FetchField("notes",¬es); + rs->FetchField("date",&dtData); + m_dtDate.SetTime(dtData); + m_dtTime.SetTime(dtData); + m_edNotes.SetWindowText(notes); + } + rs->Close(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.h new file mode 100644 index 0000000..cbccf3b --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactDlg.h @@ -0,0 +1,64 @@ +#if !defined(AFX_CONTACTDLG_H__126794C1_2CE8_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_CONTACTDLG_H__126794C1_2CE8_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ContactDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CContactDlg dialog + #include "gzrset.h" +#include "label.h" +class CContactDlg : public CDialog +{ +// Construction +public: + void FillFields(); + CString m_strRecordID; + bool m_bEditMode; + ~CContactDlg(); + CSpApp* m_pApp; + GZRset* rs; + CString m_strClientID; + bool* m_pbDelete; + void Setup(CString strClientID,CString strRecordID); + CContactDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CContactDlg) + enum { IDD = IDD_CONTACTS }; + CEdit m_edNotes; + CDateTimeCtrl m_dtTime; + CDateTimeCtrl m_dtDate; + + + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CContactDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CContactDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnBtnfollowup(); + afx_msg void OnBtnexitnosave(); + afx_msg void OnBtnexitsave(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONTACTDLG_H__126794C1_2CE8_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.cpp new file mode 100644 index 0000000..c02423c --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.cpp @@ -0,0 +1,225 @@ +// ContactsViewDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ContactsViewDlg.h" +#include "ContactDlg.h" +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CContactsViewDlg dialog + + +CContactsViewDlg::CContactsViewDlg(CWnd* pParent /*=NULL*/) +: CDialog(CContactsViewDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CContactsViewDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + //Initialize recordset pointer + + rs=m_pApp->rsPool->GetRS("CContactsViewDlg"); + +} + +CContactsViewDlg::~CContactsViewDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CContactsViewDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CContactsViewDlg) + DDX_Control(pDX, IDC_LSTNBRECS, m_lstNBRecs); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CContactsViewDlg, CDialog) +//{{AFX_MSG_MAP(CContactsViewDlg) +ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_LBN_SELCHANGE(IDC_LSTNBRECS, OnSelchangeLstnbrecs) +ON_BN_CLICKED(IDC_BTNEDIT, OnBtnedit) +ON_BN_CLICKED(IDC_BTNDEL, OnBtndel) + ON_LBN_DBLCLK(IDC_LSTNBRECS, OnDblclkLstnbrecs) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CContactsViewDlg message handlers + + +void CContactsViewDlg::OnBtnadd() +{ + CContactDlg d; + d.Setup(m_strClientID,"0"); + d.DoModal(); + rs->Close(); + FillView(); + +} + +void CContactsViewDlg::Setup(CString strClientID) +{ + if(strClientID.IsEmpty()) + { + AfxMessageBox("Invalid client ID"); + CDialog::OnOK(); + } + m_strClientID=strClientID; + + +} + +void CContactsViewDlg::FillView() +{ + CString q,username,notes,allnotes,header,strID; + COleDateTime dtData; + long lData; + m_lstNBRecs.Clear(); + q.Format("SELECT contacts.id, contacts.date " + "FROM contacts " + "WHERE (((contacts.clientlink)=%s)) ORDER BY contacts.date DESC;",m_strClientID); + //m_pApp->ShowStuff(q); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + { + m_edNotes.SetWindowText("No items to display"); + } + else + { + rs->MoveFirst(); + + do + { + + rs->FetchField("date",&dtData); + rs->FetchField("id",&lData); + strID.Format("%u",lData); + m_lstNBRecs.AddRow(dtData.Format(),strID); + + }while(rs->MoveForward()); + m_lstNBRecs.SetCurSel(0); + OnSelchangeLstnbrecs(); + } + + + +} + + + +BOOL CContactsViewDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + CString q; + q.Format("SELECT IIf(IsNull([clients].[company]),[clients].[first] & \" \" & [clients].[last],[clients].[company]) AS clientname " + "FROM clients WHERE (((clients.id)=%s));",m_strClientID); + rs->QueryReadOnly(q); + + if(!rs->IsEmpty()) + { + rs->FetchField("clientname",&q); + q="Client notes for: " + q; + SetWindowText(q); + + } + + FillView(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CContactsViewDlg::OnBtndone() +{ + CDialog::OnOK(); + +} + + +//sc.exe gpf here somewhere +void CContactsViewDlg::OnSelchangeLstnbrecs() +{ + CString q,username,notes,allnotes,header,strID; + COleDateTime dtData; + /* + if(m_bJustOpened) + strID=m_strFirstRecordID; + else + {*/ + //AfxMessageBox("Calling: GetSelectedItem"); + m_lstNBRecs.RebuildIndex();//<--------FIXES PROBLEM + strID=m_lstNBRecs.GetSelectedItem(0);//<-------problem + //} + + q.Format("SELECT contacts.id, [users].[first] & \" \" & [users].[last] AS username, contacts.date, contacts.notes " + "FROM contacts LEFT JOIN users ON contacts.staff = users.id " + "WHERE (((contacts.id)=%s));",strID); + + rs->QueryReadOnly(q); + + if(rs->IsEmpty()) + { + m_edNotes.SetWindowText("No data"); + return; + } + + + rs->FetchField("username",&username); + rs->FetchField("notes",¬es); + rs->FetchField("date",&dtData); + + header=dtData.Format() + " - " + username; + + allnotes=allnotes+"--< "+header+" >--\r\n"+notes+"\r\n\r\n"; + m_edNotes.SetWindowText(allnotes); + + +} + +void CContactsViewDlg::OnBtnedit() +{ + CContactDlg d; + d.Setup(m_strClientID,m_lstNBRecs.GetSelectedItem(0)); + d.DoModal(); + rs->Close(); + FillView(); + +} + +void CContactsViewDlg::OnBtndel() +{ + CString q; + if(AfxMessageBox("Delete selected record?",MB_YESNO)==IDYES) + { + q.Format("DELETE contacts.*, contacts.id " + "FROM contacts " + "WHERE (((contacts.id)=%s));",m_lstNBRecs.GetSelectedItem(0)); + + rs->Ex(q); + rs->Close(); + FillView(); + } + + +} + +void CContactsViewDlg::OnDblclkLstnbrecs() +{ +OnBtnedit(); +} + +void CContactsViewDlg::OnOK() +{ + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.h new file mode 100644 index 0000000..ab61f2c --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContactsViewDlg.h @@ -0,0 +1,63 @@ +#if !defined(AFX_CONTACTSVIEWDLG_H__D9199E03_7CD5_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_CONTACTSVIEWDLG_H__D9199E03_7CD5_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ContactsViewDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CContactsViewDlg dialog +#include "gzrset.h" +#include "label.h" +#include "gzlistbox.h" +class CContactsViewDlg : public CDialog +{ +// Construction +public: + CString m_strFirstRecordID; + ~CContactsViewDlg(); + CSpApp* m_pApp; + GZRset* rs; + void FillView(); + CString m_strClientID; + void Setup(CString strClientID); + CContactsViewDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CContactsViewDlg) + enum { IDD = IDD_CONTACTS_VIEW }; + CgzListBox m_lstNBRecs; + CEdit m_edNotes; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CContactsViewDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CContactsViewDlg) + afx_msg void OnBtnadd(); + virtual BOOL OnInitDialog(); + afx_msg void OnBtndone(); + afx_msg void OnSelchangeLstnbrecs(); + afx_msg void OnBtnedit(); + afx_msg void OnBtndel(); + afx_msg void OnDblclkLstnbrecs(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONTACTSVIEWDLG_H__D9199E03_7CD5_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.cpp new file mode 100644 index 0000000..d1b9d09 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.cpp @@ -0,0 +1,300 @@ +// ContractsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ContractsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CContractsDlg dialog + + +CContractsDlg::CContractsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CContractsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CContractsDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); +//Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CContractsDlg"); + +} + +CContractsDlg::~CContractsDlg() +{ +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + + +void CContractsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CContractsDlg) + DDX_Control(pDX, IDC_CONTRACT_LIST_LABEL, m_lblContractList); + DDX_Control(pDX, IDC_CONTRACT_DELETE, m_btnContractDelete); + DDX_Control(pDX, IDC_CONTRACT_ADD, m_btnContractAdd); + DDX_Control(pDX, IDC_CONTRACTTERMS, m_edContractTerms); + DDX_Control(pDX, IDC_CONTRACTNAME, m_edContractName); + DDX_Control(pDX, IDC_CONTRACT_COMBO, m_cbContracts); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CContractsDlg, CDialog) +//{{AFX_MSG_MAP(CContractsDlg) +ON_BN_CLICKED(IDC_CONTRACT_DELETE, OnContractDelete) +ON_BN_CLICKED(IDC_CONTRACT_ADD, OnContractAdd) +ON_CBN_CLOSEUP(IDC_CONTRACT_COMBO, OnCloseupContractCombo) + ON_EN_KILLFOCUS(IDC_CONTRACTNAME, OnKillfocusContractname) + ON_EN_KILLFOCUS(IDC_CONTRACTTERMS, OnKillfocusContractterms) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CContractsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + + return true; +} + + + + +bool CContractsDlg::FillContractsList() +{ + CString strData; + CString strIndex; + long lData; + m_cbContracts.Clear(); + rs->Query("SELECT contracts.* FROM contracts ORDER BY contracts.name;"); + if(rs->IsEmpty()) + { + EnableFields(false); + return false; + } + else + { + EnableFields(true); + //fill combo box with available zones + rs->MoveFirst(); + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbContracts.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbContracts.AddRow(strData,strIndex); + } + + } + + //pretend user has selected so that other fields get filled in + if(m_strSelectedContract.IsEmpty()) //first time in + { + m_cbContracts.SetCurSel(0); + } + else//something valid was selected before so stick with it + m_cbContracts.Select(m_strSelectedContract); + + OnCloseupContractCombo(); + return true; +} + + + + +///////////////////////////////////////////////////////////////////////////// +// CContractsDlg message handlers + +void CContractsDlg::OnContractDelete() +{ + CString q,strData; + q.Format("SELECT * FROM clients WHERE (contract = %s );",m_cbContracts.GetCurrentRowID()); + + + + rs->Query(q); + if(rs->IsEmpty())//no clients in that zone + { + + q.Format("DELETE contracts.*, contracts.id FROM contracts WHERE (((contracts.id)=%s));",m_cbContracts.GetCurrentRowID()); + if(AfxMessageBox("Are you sure?",MB_YESNO)==IDYES) + { + rs->Ex(q); + //a deleted zone can't be selected + m_strSelectedContract=""; + } + } + else + { + q="DATA INTEGRITY PROTECTION:\r\nYou cannot delete this contract because\r\nthe following clients are set to use it:\r\n"; + + //fill combo box with available zones + rs->MoveFirst(); + rs->FetchField("company",&strData); + q=q+strData+"\r\n"; + + + while(rs->MoveForward()) + { + rs->FetchField("company",&strData); + q=q+strData+"\r\n"; + } + AfxMessageBox(q); + } + FillContractsList(); + +} + + + + + +//******************************************************************* +void CContractsDlg::OnContractAdd() +{ + CString q,name,info; + + if(m_bAddMode) + { + m_bAddMode=false;//saving: + m_cbContracts.ShowWindow(TRUE); + m_lblContractList.ShowWindow(TRUE); + m_btnContractAdd.SetWindowText("Add"); + m_btnContractDelete.ShowWindow(TRUE); + m_edContractTerms.GetWindowText(info); + m_edContractName.GetWindowText(name); + if(name.IsEmpty()) + { + AfxMessageBox("You must enter a contract name"); + } + else + { + q.Format("INSERT INTO contracts ( name, terms ) SELECT \"%s\", \"%s\";",name,info); + rs->Ex(q); + rs->Close(); + //rs->AddNewRecord(); + //rs->UpdateField("name",&name); + //rs->UpdateField("zoneinfo",&info); + + + } + + FillContractsList(); + + + } + else//Go into add mode + { + EnableFields(true); + m_cbContracts.ShowWindow(FALSE); + m_lblContractList.ShowWindow(FALSE); + m_btnContractAdd.SetWindowText("SAVE"); + m_btnContractDelete.ShowWindow(FALSE); + m_edContractTerms.SetWindowText(""); + m_edContractName.SetWindowText(""); + m_edContractName.SetFocus(); + m_bAddMode=true; + } +} + + + +//************************************************8 +void CContractsDlg::OnCloseupContractCombo() +{ + //user has made a selection, update the visible list + CString q; + CString strData; + q.Format("SELECT contracts.* FROM contracts WHERE (((contracts.id)=%s));",m_cbContracts.GetCurrentRowID()); + rs->Query(q); + if(!rs->IsEmpty()) + { + rs->FetchField("name",&strData); + m_edContractName.SetWindowText(strData); + rs->FetchField("terms",&strData); + m_edContractTerms.SetWindowText(strData); + + + } + //save current selection so that updates and changes + //will still show what was last selected + m_strSelectedContract=m_cbContracts.GetCurrentRowID(); + +} + + + +//****************************************************** +BOOL CContractsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_edContractName.SetLimitText(25); + + FillContractsList(); + m_bAddMode=false; + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CContractsDlg::EnableFields(bool bEnable) +{ + BOOL enable= bEnable ? TRUE : FALSE; + m_btnContractDelete.EnableWindow(enable); + m_cbContracts.EnableWindow(enable); + m_edContractName.EnableWindow(enable); + m_edContractTerms.EnableWindow(enable); + + + +} + +void CContractsDlg::OnKillfocusContractname() +{ + SaveField(&m_edContractName,"name",false); + +} + +void CContractsDlg::OnKillfocusContractterms() +{ + SaveField(&m_edContractTerms,"terms",false); + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.h new file mode 100644 index 0000000..c14c0d2 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ContractsDlg.h @@ -0,0 +1,65 @@ +#if !defined(AFX_CONTRACTSDLG_H__1DCAA4C1_143C_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_CONTRACTSDLG_H__1DCAA4C1_143C_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ContractsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CContractsDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" + +class CContractsDlg : public CDialog +{ +// Construction +public: + void EnableFields(bool bEnable); + ~CContractsDlg(); + CContractsDlg(CWnd* pParent = NULL); // standard constructor +CString m_strSelectedContract; + bool SaveField(CEdit *edControl,CString fldname,bool AllowEmpty); + bool m_bAddMode; + bool FillContractsList(); + CSpApp* m_pApp; +// Dialog Data + //{{AFX_DATA(CContractsDlg) + enum { IDD = IDD_CONTRACTS }; + CStatic m_lblContractList; + CButton m_btnContractDelete; + CButton m_btnContractAdd; + CEdit m_edContractTerms; + CEdit m_edContractName; + CgzCombo m_cbContracts; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CContractsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + GZRset* rs; + // Generated message map functions + //{{AFX_MSG(CContractsDlg) + afx_msg void OnContractDelete(); + afx_msg void OnContractAdd(); + afx_msg void OnCloseupContractCombo(); + virtual BOOL OnInitDialog(); + afx_msg void OnKillfocusContractname(); + afx_msg void OnKillfocusContractterms(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONTRACTSDLG_H__1DCAA4C1_143C_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.cpp new file mode 100644 index 0000000..3ed8499 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.cpp @@ -0,0 +1,435 @@ +#include "stdafx.h" +#include "Crc32Static.h" +//#include +#include +using namespace std; +// Static CRC table +DWORD CCrc32Static::s_arrdwCrc32Table[256] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +}; + +//*********************************************** +CCrc32Static::CCrc32Static() +{ +} + +//*********************************************** +CCrc32Static::~CCrc32Static() +{ +} + +//*********************************************** +inline void CCrc32Static::CalcCrc32(const BYTE byte, DWORD &dwCrc32) +{ + dwCrc32 = ((dwCrc32) >> 8) ^ s_arrdwCrc32Table[(byte) ^ ((dwCrc32) & 0x000000FF)]; +} + +//*********************************************** +bool CCrc32Static::GetFileSizeQW(const HANDLE hFile, QWORD &qwSize) +{ + _ASSERTE(hFile != INVALID_HANDLE_VALUE); + + bool bSuccess = true; + + try + { + DWORD dwLo = 0, dwHi = 0; + dwLo = GetFileSize(hFile, &dwHi); + + if(dwLo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) + { + bSuccess = false; + qwSize = 0; + } + else + { + qwSize = MAKEQWORD(dwHi, dwLo); + } + } + catch(...) + { + bSuccess = false; + } + + return bSuccess; +} + +//*********************************************** +DWORD CCrc32Static::StringCrc32(LPCTSTR szString, DWORD &dwCrc32) +{ + _ASSERTE(szString); + + DWORD dwErrorCode = NO_ERROR; + + dwCrc32 = 0xFFFFFFFF; + + try + { + while(*szString != _T('\0')) + { + CalcCrc32((BYTE)*szString, dwCrc32); + szString++; + } + } + catch(...) + { + // An unknown exception happened + dwErrorCode = ERROR_CRC; + } + + dwCrc32 = ~dwCrc32; + + return dwErrorCode; +} + +//*********************************************** +//DWORD CCrc32Static::FileCrc32Streams(LPCTSTR szFilename, DWORD &dwCrc32) +//{ +//#if UNICODE || _UNICODE +// return ERROR_NOT_SUPPORTED; +//#else +// _ASSERTE(szFilename); +// _ASSERTE(lstrlen(szFilename)); +// +// DWORD dwErrorCode = NO_ERROR; +// ifstream file; +// +// dwCrc32 = 0xFFFFFFFF; +// +// try +// { +// // Open the file +// file.open(szFilename, ios::in | ios::nocreate | ios::binary, filebuf::sh_read); +// +// if(file.is_open()) +// { +// char buffer[MAX_BUFFER_SIZE]; +// int nLoop, nCount; +// nCount = file.read(buffer, sizeof(buffer)).gcount(); +// while(nCount) +// { +// for(nLoop = 0; nLoop < nCount; nLoop++) +// CalcCrc32(buffer[nLoop], dwCrc32); +// nCount = file.read(buffer, sizeof(buffer)).gcount(); +// } +// +// file.close(); +// } +// } +// catch(...) +// { +// // An unknown exception happened +// dwErrorCode = ERROR_CRC; +// } +// +// if(file.is_open()) file.close(); +// +// dwCrc32 = ~dwCrc32; +// +// return dwErrorCode; +//#endif +//} + +//*********************************************** +DWORD CCrc32Static::FileCrc32Win32(LPCTSTR szFilename, DWORD &dwCrc32) +{ + _ASSERTE(szFilename); + _ASSERTE(lstrlen(szFilename)); + + DWORD dwErrorCode = NO_ERROR; + HANDLE hFile = NULL; + + dwCrc32 = 0xFFFFFFFF; + + try + { + // Open the file + hFile = CreateFile(szFilename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + dwErrorCode = GetLastError(); + else + { + BYTE buffer[MAX_BUFFER_SIZE]; + DWORD dwBytesRead, dwLoop; + BOOL bSuccess = ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL); + while(bSuccess && dwBytesRead) + { + for(dwLoop = 0; dwLoop < dwBytesRead; dwLoop++) + CalcCrc32(buffer[dwLoop], dwCrc32); + bSuccess = ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL); + } + } + } + catch(...) + { + // An unknown exception happened + dwErrorCode = ERROR_CRC; + } + + if(hFile != NULL) CloseHandle(hFile); + + dwCrc32 = ~dwCrc32; + + return dwErrorCode; +} + +//*********************************************** +DWORD CCrc32Static::FileCrc32Filemap(LPCTSTR szFilename, DWORD &dwCrc32) +{ + _ASSERTE(szFilename); + _ASSERTE(lstrlen(szFilename)); + + DWORD dwErrorCode = NO_ERROR; + HANDLE hFile = NULL, hFilemap = NULL; + + dwCrc32 = 0xFFFFFFFF; + + try + { + // Open the file + hFile = CreateFile(szFilename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + dwErrorCode = GetLastError(); + else + { + QWORD qwFileSize = 0, qwFileOffset = 0; + DWORD dwByteCount, dwViewSize; + DWORD dwBaseAddress; + + // Get the file size + if(!GetFileSizeQW(hFile, qwFileSize)) + dwErrorCode = ERROR_BAD_LENGTH; + else if(qwFileSize != 0) // We cannot CRC zero byte files + { + // Create the file mapping + hFilemap = CreateFileMapping(hFile, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + if(hFilemap == NULL) + dwErrorCode = GetLastError(); + else + { + LPBYTE pByte; + + // Loop while we map a section of the file and CRC it + while(qwFileSize > 0) + { + if(qwFileSize < MAX_VIEW_SIZE) + dwViewSize = LODWORD(qwFileSize); + else + dwViewSize = MAX_VIEW_SIZE; + + dwBaseAddress = (DWORD)MapViewOfFile(hFilemap, + FILE_MAP_READ, + HIDWORD(qwFileOffset), + LODWORD(qwFileOffset), + dwViewSize); + + dwByteCount = dwViewSize; + pByte = (LPBYTE)dwBaseAddress; + while(dwByteCount-- > 0) + { + CalcCrc32(*pByte, dwCrc32); + pByte++; + } + + UnmapViewOfFile((LPVOID)dwBaseAddress); + qwFileOffset += dwViewSize; + qwFileSize -= dwViewSize; + } + } + } + } + } + catch(...) + { + // An unknown exception happened + dwErrorCode = ERROR_CRC; + } + + if(hFile != NULL) CloseHandle(hFile); + if(hFilemap != NULL) CloseHandle(hFilemap); + + dwCrc32 = ~dwCrc32; + + return dwErrorCode; +} + +//*********************************************** +DWORD CCrc32Static::FileCrc32Assembly(LPCTSTR szFilename, DWORD &dwCrc32) +{ + _ASSERTE(szFilename); + _ASSERTE(lstrlen(szFilename)); + + DWORD dwErrorCode = NO_ERROR; + HANDLE hFile = NULL; + + dwCrc32 = 0xFFFFFFFF; + + try + { + // Open the file + hFile = CreateFile(szFilename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(hFile == INVALID_HANDLE_VALUE) + dwErrorCode = GetLastError(); + else + { + // There is a bug in the Microsoft compilers where inline assembly + // code cannot access static member variables. This is a work around + // for that bug. For more info see Knowledgebase article Q88092 + LPVOID ptrCrc32Table = &s_arrdwCrc32Table; + + BYTE buffer[MAX_BUFFER_SIZE]; + DWORD dwBytesRead; + BOOL bSuccess = ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL); + while(bSuccess && dwBytesRead) + { + // Register use: + // eax - CRC32 value + // ebx - a lot of things + // ecx - CRC32 value + // edx - address of end of buffer + // esi - address of start of buffer + // edi - CRC32 table + __asm + { + // Save the esi and edi registers + push esi + push edi + + mov eax, dwCrc32 // Load the pointer to dwCrc32 + mov ecx, [eax] // Dereference the pointer to load dwCrc32 + + mov edi, ptrCrc32Table // Load the CRC32 table + + lea esi, buffer // Load buffer + mov ebx, dwBytesRead // Load dwBytesRead + lea edx, [esi + ebx] // Calculate the end of the buffer + + crc32loop: + xor eax, eax // Clear the eax register + mov bl, byte ptr [esi] // Load the current source byte + + mov al, cl // Copy crc value into eax + inc esi // Advance the source pointer + + xor al, bl // Create the index into the CRC32 table + shr ecx, 8 + + mov ebx, [edi + eax * 4] // Get the value out of the table + xor ecx, ebx // xor with the current byte + + cmp edx, esi // Have we reached the end of the buffer? + jne crc32loop + + // Restore the edi and esi registers + pop edi + pop esi + + mov eax, dwCrc32 // Load the pointer to dwCrc32 + mov [eax], ecx // Write the result + } + bSuccess = ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL); + } + } + } + catch(...) + { + // An unknown exception happened + dwErrorCode = ERROR_CRC; + } + + if(hFile != NULL) CloseHandle(hFile); + + dwCrc32 = ~dwCrc32; + + return dwErrorCode; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.h new file mode 100644 index 0000000..bdda0b0 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Crc32Static.h @@ -0,0 +1,25 @@ +#ifndef _CRC32STATIC_H_ +#define _CRC32STATIC_H_ + +#include "Common.h" + +class CCrc32Static +{ +public: + CCrc32Static(); + virtual ~CCrc32Static(); + + static DWORD StringCrc32(LPCTSTR szString, DWORD &dwCrc32); + //static DWORD FileCrc32Streams(LPCTSTR szFilename, DWORD &dwCrc32); + static DWORD FileCrc32Win32(LPCTSTR szFilename, DWORD &dwCrc32); + static DWORD FileCrc32Filemap(LPCTSTR szFilename, DWORD &dwCrc32); + static DWORD FileCrc32Assembly(LPCTSTR szFilename, DWORD &dwCrc32); + +protected: + static bool GetFileSizeQW(const HANDLE hFile, QWORD &qwSize); + static inline void CalcCrc32(const BYTE byte, DWORD &dwCrc32); + + static DWORD s_arrdwCrc32Table[256]; +}; + +#endif diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.cpp new file mode 100644 index 0000000..9869ad6 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.cpp @@ -0,0 +1,7325 @@ +// DBUtils.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "DBUtils.h" +#include "Defaultsdlg.h" +#include "TED.h"//tiny editor +#include "kd.h" +#include "SimpleDate.h" +#include "gzCurrencyFormatter.h" +#include "xferdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define CUTOFF 100 //cutoff indexing after this many records for testing purposes used in suckwords +#define TRACING 0//1=enable runtime tracing, 0=don't +///////////////////////////////////////////////////////////////////////////// +// CDBUtils + +IMPLEMENT_DYNCREATE(CDBUtils, CFormView) + +CDBUtils::CDBUtils() +: CFormView(CDBUtils::IDD) +{ + //{{AFX_DATA_INIT(CDBUtils) + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + + //Initialize recordset pointer + + + rs=m_pApp->rsPool->GetRS("CDBUtils (RS)"); + rs2=m_pApp->rsPool->GetRS("CDBUtils (RS2)"); + rs3=m_pApp->rsPool->GetRS("CDBUtils (RS3)"); + + m_bBootScanDone=false; +} + +CDBUtils::~CDBUtils() +{ + DeActivate(); + +} + +void CDBUtils::DoDataExchange(CDataExchange* pDX) +{ + CFormView::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDBUtils) + DDX_Control(pDX, IDC_STAT11, m_st11); + DDX_Control(pDX, IDC_PROGRESS11, m_pg11); + DDX_Control(pDX, IDC_BTNTEST, m_btnTest); + DDX_Control(pDX, IDC_STAT99, m_st9); + DDX_Control(pDX, IDC_STAT88, m_st8); + DDX_Control(pDX, IDC_STAT77, m_st7); + DDX_Control(pDX, IDC_STAT66, m_st6); + DDX_Control(pDX, IDC_STAT1010, m_st10); + DDX_Control(pDX, IDC_PROGRESS99, m_pg9); + DDX_Control(pDX, IDC_PROGRESS88, m_pg8); + DDX_Control(pDX, IDC_PROGRESS77, m_pg7); + DDX_Control(pDX, IDC_PROGRESS66, m_pg6); + DDX_Control(pDX, IDC_PROGRESS1010, m_pg10); + DDX_Control(pDX, IDC_BTNDELETEALL, m_btnDelAll); + DDX_Control(pDX, IDC_BTNQUICKINDEX, m_btnQuickIndex); + DDX_Control(pDX, IDC_BTNINDEXALL, m_btnIndexAll); + DDX_Control(pDX, IDC_BTNDEFAULTS, m_btnDefaults); + DDX_Control(pDX, IDC_BTNCOMPACT, m_btnCompact); + DDX_Control(pDX, IDC_BTNCM3, m_btnCM3); + DDX_Control(pDX, IDC_LBLWORDCOUNT, m_lblWordCount); + DDX_Control(pDX, IDC_LBLPARTIALINFO, m_lblPartialInfo); + DDX_Control(pDX, IDC_LBLFULLINFO, m_lblFullInfo); + DDX_Control(pDX, IDC_STAT5, m_st5); + DDX_Control(pDX, IDC_STAT4, m_st4); + DDX_Control(pDX, IDC_STAT3, m_st3); + DDX_Control(pDX, IDC_STAT2, m_st2); + DDX_Control(pDX, IDC_STAT1, m_st1); + DDX_Control(pDX, IDC_PROGRESS5, m_pg5); + DDX_Control(pDX, IDC_PROGRESS4, m_pg4); + DDX_Control(pDX, IDC_PROGRESS3, m_pg3); + DDX_Control(pDX, IDC_PROGRESS2, m_pg2); + DDX_Control(pDX, IDC_PROGRESS1, m_pg1); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDBUtils, CFormView) +//{{AFX_MSG_MAP(CDBUtils) +ON_BN_CLICKED(IDC_BTNCOMPACT, OnBtncompact) +ON_BN_CLICKED(IDC_BTNDEFAULTS, OnBtndefaults) +ON_BN_CLICKED(IDC_BTNINDEXALL, OnBtnindexall) +ON_BN_CLICKED(IDC_BTNQUICKINDEX, OnBtnquickindex) +ON_WM_RBUTTONDBLCLK() +ON_BN_CLICKED(IDC_BTNCM3, OnBtncm3) +ON_BN_CLICKED(IDC_BTNDELETEALL, OnBtndeleteall) +ON_BN_CLICKED(IDC_BTNTEST, OnBtntest) +ON_BN_CLICKED(IDC_BTNEXPORT, OnBtnexport) +ON_BN_CLICKED(IDC_BTNIMPORT, OnBtnimport) +//}}AFX_MSG_MAP +ON_WM_HELPINFO() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDBUtils diagnostics + +#ifdef _DEBUG +void CDBUtils::AssertValid() const +{ + CFormView::AssertValid(); +} + +void CDBUtils::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CDBUtils message handlers +void CDBUtils::OnInitialUpdate() +{ + CFormView::OnInitialUpdate(); + if(m_pApp->m_lusrID==1) m_btnDelAll.ShowWindow(TRUE); + //registered? + if(m_pApp->m_uiFeatures&LICENSE_REGISTERED) + ; + else + m_btnDelAll.ShowWindow(FALSE); + + + ppg[0]=&m_pg1; + ppg[1]=&m_pg2; + ppg[2]=&m_pg3; + ppg[3]=&m_pg4; + ppg[4]=&m_pg5; + ppg[5]=&m_pg6; + ppg[6]=&m_pg7; + ppg[7]=&m_pg11; + ppg[8]=&m_pg9; + ppg[9]=&m_pg10; + ppg[10]=&m_pg8; + + //display index information + ShowIndexInfo(); + SetRights(); + + +#ifdef _DEBUG + m_btnTest.ShowWindow(TRUE); +#endif //_DEBUG + + +} + +void CDBUtils::Activate() +{ +#ifdef _WTF_ + AfxMessageBox("dbutils activate"); +#endif + //Process database updates if any. + if(m_pApp->m_bBadDatabaseVersion) + UpdateDatabaseSchema(); + + //daily maintenance + if(!m_bBootScanDone) + BootScan(); +} + +void CDBUtils::DeActivate() +{ +#ifdef _WTF_ + AfxMessageBox("dbutils De-activate"); +#endif + + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs2->m_nID); + m_pApp->rsPool->ReleaseRS(&rs3->m_nID); + +} + +CSpDoc* CDBUtils::GetDocument() +{ + return (CSpDoc*)m_pDocument; +} + +void CDBUtils::OnBtncompact() +{ + + ShowProgressControls(false); + if(!m_pApp->rsPool->GoExclusive()) + { + AfxMessageBox("All other users need to exit first\r\n" + "You need exclusive access in order to proceed."); + rs->m_bExclusiveConnection=false; + //back to shared mode + m_pApp->rsPool->GoShared(); + return ; + } + m_pApp->rsPool->Disconnect(); + GetDocument()->Compact(true);//compact and keep backup copy + + rs->m_bExclusiveConnection=false; + //rs->Close(); + + //Ok, everyone is out, go shared + m_pApp->rsPool->GoShared(); + AfxMessageBox("Finsihed"); +} + +void CDBUtils::OnBtndefaults() +{ + ShowProgressControls(false); + CDefaultsDlg d; + d.DoModal(); +} + + + +void CDBUtils::OnBtnindexall() +{ + if(ExclusiveAccess()) + Index(true); + + + +} + +void CDBUtils::OnBtnquickindex() +{ + if(ExclusiveAccess()) + Index(false); + + +} + + + + + +bool CDBUtils::ExclusiveAccess() +{ + + rs->m_bExclusiveConnection=true; + if(!m_pApp->rsPool->GoExclusive()) + { + AfxMessageBox("All other users need to exit first\r\n" + "You need exclusive access in order to proceed."); + rs->m_bExclusiveConnection=false; + //back to shared mode + m_pApp->rsPool->GoShared(); + return false; + } + + rs->m_bExclusiveConnection=false; + rs->Close(); + //Ok, everyone is out, go shared + m_pApp->rsPool->GoShared(); + return true; + +} + + +void CDBUtils::Index(bool bFullIndex) +{ + CString str,strText,strWord,lchar,q,strData; + long lData,lRecs,lUniqueWords; + + + COleDateTime dtStart,dtEnd; + COleDateTimeSpan dtsDuration; + float fData; + dtStart=COleDateTime::GetCurrentTime(); + //Open exclusive + CWaitCursor wait; + m_strErrorLog.Empty(); + ShowProgressControls(true); + PeekAndPump(); + wait.Restore(); + + + + //Empty temporary dictionary (should be empty anyway) + rs->Close(); + rs->Ex("DELETE srchtempdict.* FROM srchtempdict;"); + + + + + //If re-indexing *ALL* then + if(bFullIndex) + { //Flag all tables with an indexed field to no + rs->Ex("UPDATE probs SET probs.indexed = False;"); + rs->Ex("UPDATE labor SET labor.indexed = False;"); + rs->Ex("UPDATE subrepair SET subrepair.indexed = False;"); + rs->Ex("UPDATE rentals SET rentals.indexed = False;"); + rs->Ex("UPDATE clients SET clients.indexed = False;"); + //Added 8/29/00 + rs->Ex("UPDATE contacts SET contacts.indexed = False;"); + rs->Ex("UPDATE units SET units.indexed = False;"); + + //Added 05/09/2001 + rs->Ex("UPDATE wo SET wo.indexed = False;"); + + //ADD NEW ITEM HERE + + //Empty search keys and dictionary tables + rs->Ex("DELETE srchkey.* FROM srchkey;"); + rs->Ex("DELETE srchdict.* FROM srchdict;"); + + } + else + { + //REMOVE STALE DATA ASSOCIATED WITH RECORDS THAT WERE INDEXED BUT ARE NOW + //NOT DUE TO EDITS ETC + //flag stale search keys + //CLIENTS + rs->Ex("UPDATE clients INNER JOIN srchkey ON clients.id = srchkey.tableid SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=4) AND ((clients.indexed)=False));"); + + //LABOR + rs->Ex("UPDATE srchkey INNER JOIN labor ON [srchkey].[tableid]=[labor].[id] SET srchkey.remove = True " + "WHERE ((([srchkey].[tabletype])=1) And (([labor].[indexed])=False));"); + + //PROBS + rs->Ex("UPDATE srchkey INNER JOIN probs ON srchkey.tableid = probs.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=0) AND ((probs.indexed)=False));"); + + //RENTALS + rs->Ex("UPDATE rentals INNER JOIN srchkey ON rentals.id = srchkey.tableid SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=3) AND ((rentals.indexed)=False));"); + + //SUBREPAIRS + rs->Ex("UPDATE srchkey INNER JOIN subrepair ON srchkey.tableid = subrepair.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=2) AND ((subrepair.indexed)=False));"); + + //CONTACTS + rs->Ex("UPDATE contacts INNER JOIN srchkey ON contacts.id = srchkey.tableid SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=5) AND ((contacts.indexed)=False));"); + + //UNITS + rs->Ex("UPDATE srchkey INNER JOIN subrepair ON srchkey.tableid = subrepair.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=6) AND ((subrepair.indexed)=False));"); + + + //Added 05/09/2001 new table workorder header is table type 7 + //WORKORDER HEADERS + rs->Ex("UPDATE srchkey INNER JOIN wo ON srchkey.tableid = wo.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=7) AND ((wo.indexed)=False));"); + + //ADD NEW ITEM HERE AS TABLE TYPE 8 + + + //REMOVE previous search results here + rs->Ex("DELETE srch.* FROM srch;"); + + //remove stale search keys + rs->Ex("DELETE srchkey.*, srchkey.remove " + "FROM srchkey " + "WHERE (((srchkey.remove)=True));"); + + + + //flag stale dictionary words + rs->Ex("UPDATE srchkey RIGHT JOIN srchdict ON srchkey.wordid = srchdict.ID SET srchdict.remove = True " + "WHERE (((srchkey.wordid) Is Null));"); + + //Remove stale dictionary words not used anymore + rs->Ex("DELETE srchdict.*, srchdict.remove " + "FROM srchdict " + "WHERE (((srchdict.remove)=True));"); + + } + + + //Loop through each table + //pull out words and add each word to the temporary dictionary + //with the word and the record it came from + //srchkey.type: 0=probs,1labour,2subrepair,3rentals,4clients + //5-contacts (client notebook) 6=units, 7=workorder headers (wo) + //********************************************************* + //********************************************************* + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + //zTrace("index C",false); + //PROBS (table 0)* + //v1.9.4.5 added slight variation on query for performance gain + if(bFullIndex) + rs2->QueryReadOnly("SELECT probs.id, [brief], [probs].[notes], probs.created AS idate, wo.client AS iclient " + "FROM probs LEFT JOIN wo ON probs.wolink = wo.id;"); + else + rs2->QueryReadOnly("SELECT probs.id, [brief], [probs].[notes], probs.created AS idate, wo.client AS iclient " + "FROM probs LEFT JOIN wo ON probs.wolink = wo.id " + "WHERE (((probs.indexed)=False));"); + + if(!rs2->IsEmpty()) + { + + SuckWords(0); + } + ppg[0]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //zTrace("index D",false); + //LABOUR (table 1)* + //v1.9.4.5 added slight variation on query for performance gain + if(bFullIndex) + rs2->QueryReadOnly("SELECT labor.id, labor.details , labor.stop AS idate, wo.client AS iclient " + "FROM (labor LEFT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id;"); + else + rs2->QueryReadOnly("SELECT labor.id, labor.details, labor.stop AS idate, wo.client AS iclient " + "FROM (labor LEFT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id " + "WHERE (((labor.indexed)=False));"); + + if(!rs2->IsEmpty()) + { + SuckWords(1); + } + + //AfxMessageBox("Done labour starting subrepair"); + ppg[1]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //zTrace("index E",false); + //SUBREPAIR (table2)* + rs2->QueryReadOnly("SELECT subrepair.id, subrepair.notes, subrepair.created AS idate, wo.client AS iclient " + "FROM (subrepair LEFT JOIN probs ON subrepair.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id " + "WHERE (((subrepair.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(2); + } + //AfxMessageBox("Done subrepair, starting rentals"); + ppg[2]->SetPos(100); + PeekAndPump(); + wait.Restore(); + //RENTALS (table 3)* + rs2->QueryReadOnly("SELECT rentals.id, [notes], [loanedto], [description], rentals.dateout AS idate, rentals.clientlink AS iclient " + "FROM rentals " + "WHERE (((rentals.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(3); + } + ppg[3]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //CLIENTS (table 4)* + rs2->QueryReadOnly("SELECT clients.id, clients.id AS iclient, clients.created AS idate, [generalnotes] , " + "[technotes] , [alert] , " + "[first] , [last] , [company] " + " , [mailaddress] , " + "[streetaddress] , [city] , " + "[stateprov] , [postal] , " + "[country] , [bizphone] , " + "[fax] , [email] , [acctnumber] , [phone2] , [phone3] " + "FROM clients WHERE (((clients.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(4); + } + ppg[4]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //CONTACTS (table 5)* + rs2->QueryReadOnly( + "SELECT contacts.id, contacts.notes, contacts.date AS idate, " + "contacts.clientlink AS iclient FROM contacts " + "WHERE (((contacts.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(5); + } + ppg[5]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //UNITS (table 6)* + rs2->QueryReadOnly("SELECT units.id, [units].[receipt] , [units].[sn] , [units].[id1] , " + "[units].[id2] , [units].[id3] , [units].[notes] , " + "[units].[description], units.client AS iclient, " + "IIf(IsNull([units].[purchasedate]),IIf(IsNull([units].[created]), " + "IIf(IsNull([units].[modified]),#1/1/2000#,[units].[modified]),[units].[created]), " + "[units].[purchasedate]) AS idate " + "FROM units " + "WHERE (((units.indexed)=False) AND ((units.client)<>0));"); + + if(!rs2->IsEmpty()) + { + SuckWords(6); + } + ppg[6]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + + //WORKORDER HEADER (TABLE 7) added 05/09/2001 + //v1.9.4.5 added slight variation on query for performance gain + if(bFullIndex) + rs2->QueryReadOnly("SELECT wo.id, [wo].[notes], [wo].[invoice], [wo].[clientrefnum], " + "[wo].[clientcontact], [wo].[ourref], wo.created AS idate, wo.client AS iclient " + "FROM wo;"); + else + rs2->QueryReadOnly("SELECT wo.id, [wo].[notes], [wo].[invoice], [wo].[clientrefnum], " + "[wo].[clientcontact], [wo].[ourref], wo.created AS idate, wo.client AS iclient " + "FROM wo " + "WHERE (((wo.indexed)=False));"); + + if(!rs2->IsEmpty()) + { + SuckWords(7); + } + ppg[7]->SetPos(100); + PeekAndPump(); + wait.Restore(); + //================================= + + //ADD new indexed items here. + + //To do: add wo header and woparts + + //================================= + + + + + //Make the dictionary: Stage 6 + //Pull out all the unique words from the temporary dictionary + //that do *not* appear in the stop words table of words to ignore + //and insert each one into the SearchDictionary, assigning + //each one an id number (new method now will do this automatically?) + + //05/09/2001 changed progress control to 10 as 7 is now wo table + //see initial update for more info + + rs2->QueryReadOnly("SELECT srchtempdict.word " + "FROM (srchtempdict LEFT JOIN srchstopwords ON srchtempdict.word = " + "srchstopwords.word) LEFT JOIN srchdict ON srchtempdict.word = srchdict.word " + "WHERE (((srchstopwords.word) Is Null)) " + "GROUP BY srchtempdict.word, srchdict.word;"); + if(rs2->IsEmpty()) + { + AfxMessageBox("No data to index"); + rs->Close(); + rs2->Close(); + return; + } + + wait.Restore(); + lUniqueWords=lRecs=rs2->FetchRecordCount(); + rs2->MoveFirst(); + lData=0; + ppg[10]->SetRange32(0,(int)lRecs); + //pConnection->BeginTrans(); + rs2->pTheConnection->BeginTrans(); + do{ + rs2->FetchField("word",&strData); + lData++; + q.Format("INSERT INTO srchdict ( ID, word ) SELECT %u , \"%s\";",lData,strData); + + rs->Ex(q); + + + + }while(rs2->MoveForward()); + rs2->pTheConnection->CommitTrans(); + + //pConnection->CommitTrans(); + + ppg[10]->SetPos((int)lData); + PeekAndPump(); + wait.Restore(); + + //Make keys: + //match up the words and tempdictionary and insert a single match from + //each record into the keys so that if the same word appears more + //than once in a record, it actually only causes one entry since at + //this point we don't care where in the actual record each repetition + //appears, only that there is at least one in record X. + //srchkey.type: 0=probs,1labour,2subrepair,3rentals,4clients + ppg[8]->SetPos(50); + rs->Ex("INSERT INTO srchkey ( [tableid], wordid, tabletype, client, [date] ) " + "SELECT DISTINCT srchtempdict.id, srchdict.ID, srchtempdict.type, srchtempdict.client, [srchtempdict].[date] " + "FROM srchdict RIGHT JOIN srchtempdict ON srchdict.word = srchtempdict.word " + "WHERE (((srchdict.word) Is Not Null));"); + + ppg[8]->SetPos(100); + PeekAndPump(); + //AfxMessageBox("passed stage 6"); + wait.Restore(); + + //final cleanup********************* + ppg[9]->SetPos(1); + PeekAndPump(); + wait.Restore(); + //Clean out the tempdict + +//************************************************ + + + + + + // TEST TO RESOLVE LOCK PROBLEM + //03/09/2004 + rs->Close(); + rs2->Close(); + + + //Empty temporary dictionary (should be empty anyway) + rs3->Ex("DELETE srchtempdict.* FROM srchtempdict;"); + ppg[9]->SetPos(12); + PeekAndPump(); + wait.Restore(); + //Flag all indexed tables as being indexed + rs->Ex("UPDATE clients SET clients.indexed = True;"); + ppg[9]->SetPos(24); + PeekAndPump(); + wait.Restore(); + rs->Ex("UPDATE probs SET probs.indexed = True;"); + ppg[9]->SetPos(36); + PeekAndPump(); + wait.Restore(); + rs->Ex("UPDATE labor SET labor.indexed = True;"); + ppg[9]->SetPos(48); + PeekAndPump(); + wait.Restore(); + //AfxMessageBox("48% done..."); + rs->Ex("UPDATE subrepair SET subrepair.indexed = True;"); + ppg[9]->SetPos(60); + PeekAndPump(); + wait.Restore(); + //AfxMessageBox("60% done..."); + rs->Ex("UPDATE rentals SET rentals.indexed = True;"); + ppg[9]->SetPos(72); + PeekAndPump(); + wait.Restore(); + + //added may 9th 2001 for wo table + rs->Ex("UPDATE wo SET wo.indexed = True;"); + ppg[9]->SetPos(75); + PeekAndPump(); + wait.Restore(); + + + //compact the database + //close the recordsets first + + rs->Close(); + rs2->Close(); + //pConnection->Close(); + //pConnection->Release(); + + m_pApp->rsPool->Disconnect(); + GetDocument()->Compact(false);//compact and dump old copy + m_pApp->rsPool->GoShared(); + + + ppg[9]->SetPos(90); + PeekAndPump(); + wait.Restore(); + + //AfxMessageBox("90% done..."); + + //mark index date in the global defaults table + //nice touch would be to also indicate how many unique words are + //indexed + + //re-open the recordset to update the defaults table + + + dtEnd=COleDateTime::GetCurrentTime(); + dtsDuration=dtEnd-dtStart; + fData=(float)(dtsDuration.GetTotalSeconds()/60); + if(bFullIndex) + { + + q.Format("UPDATE defaults SET defaults.lastfullindex = " + "#%s#, defaults.dictsize = %u, defaults.fullindextime = %f;",dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),lUniqueWords,fData); + } + else + { + + q.Format("UPDATE defaults SET defaults.lastpartindex = " + "#%s#, defaults.dictsize = %u, defaults.partindextime = %f;",dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),lUniqueWords,fData); + } + + rs->Ex(q); + + + + + ppg[9]->SetPos(100); + PeekAndPump(); + wait.Restore(); + rs->Close(); + + ShowIndexInfo(); + wait.Restore(); + CString strTemp; + strTemp.Format("Index complete!\r\n%u:%u:%u (HH:MM:SS).", + dtsDuration.GetHours(),dtsDuration.GetMinutes(),dtsDuration.GetSeconds()); + AfxMessageBox(strTemp); + + + +} + + + +/* +void CDBUtils::Index(bool bFullIndex) +{ +CString str,strText,strWord,lchar,q,strData; +long lData,lRecs,lUniqueWords; + + + COleDateTime dtStart,dtEnd; + COleDateTimeSpan dtsDuration; + float fData; + dtStart=COleDateTime::GetCurrentTime(); + //Open exclusive + CWaitCursor wait; + m_strErrorLog.Empty(); + ShowProgressControls(true); + PeekAndPump(); + wait.Restore(); + + + //connection stuff here to avoid overhead + //of using one in gzrset + //create a pointer to a connection + _bstr_t strSQL; + //_ConnectionPtr pConnection = NULL; + + //instantiate it: + pConnection.CreateInstance(__uuidof(Connection)); + + //get connect string + _bstr_t strCnn(m_pApp->strConnectString); + + //open the connection + pConnection->Open (strCnn, "", "", adConnectUnspecified); + + //zTrace("Start of index",false); + + + + + //Empty temporary dictionary (should be empty anyway) + rs->Close(); + rs->Ex("DELETE srchtempdict.* FROM srchtempdict;"); + + + + + //If re-indexing *ALL* then + if(bFullIndex) + { //Flag all tables with an indexed field to no + rs->Ex("UPDATE probs SET probs.indexed = False;"); + rs->Ex("UPDATE labor SET labor.indexed = False;"); + rs->Ex("UPDATE subrepair SET subrepair.indexed = False;"); + rs->Ex("UPDATE rentals SET rentals.indexed = False;"); + rs->Ex("UPDATE clients SET clients.indexed = False;"); + //Added 8/29/00 + rs->Ex("UPDATE contacts SET contacts.indexed = False;"); + rs->Ex("UPDATE units SET units.indexed = False;"); + + //Added 05/09/2001 + rs->Ex("UPDATE wo SET wo.indexed = False;"); + + //ADD NEW ITEM HERE + + //Empty search keys and dictionary tables + rs->Ex("DELETE srchkey.* FROM srchkey;"); + rs->Ex("DELETE srchdict.* FROM srchdict;"); + + } + else + { + //REMOVE STALE DATA ASSOCIATED WITH RECORDS THAT WERE INDEXED BUT ARE NOW + //NOT DUE TO EDITS ETC + //flag stale search keys + //CLIENTS + rs->Ex("UPDATE clients INNER JOIN srchkey ON clients.id = srchkey.tableid SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=4) AND ((clients.indexed)=False));"); + + //LABOR + rs->Ex("UPDATE srchkey INNER JOIN labor ON [srchkey].[tableid]=[labor].[id] SET srchkey.remove = True " + "WHERE ((([srchkey].[tabletype])=1) And (([labor].[indexed])=False));"); + + //PROBS + rs->Ex("UPDATE srchkey INNER JOIN probs ON srchkey.tableid = probs.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=0) AND ((probs.indexed)=False));"); + + //RENTALS + rs->Ex("UPDATE rentals INNER JOIN srchkey ON rentals.id = srchkey.tableid SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=3) AND ((rentals.indexed)=False));"); + + //SUBREPAIRS + rs->Ex("UPDATE srchkey INNER JOIN subrepair ON srchkey.tableid = subrepair.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=2) AND ((subrepair.indexed)=False));"); + + //CONTACTS + rs->Ex("UPDATE contacts INNER JOIN srchkey ON contacts.id = srchkey.tableid SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=5) AND ((contacts.indexed)=False));"); + + //UNITS + rs->Ex("UPDATE srchkey INNER JOIN subrepair ON srchkey.tableid = subrepair.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=6) AND ((subrepair.indexed)=False));"); + + + //Added 05/09/2001 new table workorder header is table type 7 + //WORKORDER HEADERS + rs->Ex("UPDATE srchkey INNER JOIN wo ON srchkey.tableid = wo.id SET srchkey.remove = True " + "WHERE (((srchkey.tabletype)=7) AND ((wo.indexed)=False));"); + + //ADD NEW ITEM HERE AS TABLE TYPE 8 + + + //REMOVE previous search results here + rs->Ex("DELETE srch.* FROM srch;"); + + //remove stale search keys + rs->Ex("DELETE srchkey.*, srchkey.remove " + "FROM srchkey " + "WHERE (((srchkey.remove)=True));"); + + + + //flag stale dictionary words + rs->Ex("UPDATE srchkey RIGHT JOIN srchdict ON srchkey.wordid = srchdict.ID SET srchdict.remove = True " + "WHERE (((srchkey.wordid) Is Null));"); + + //Remove stale dictionary words not used anymore + rs->Ex("DELETE srchdict.*, srchdict.remove " + "FROM srchdict " + "WHERE (((srchdict.remove)=True));"); + + } + + + //Loop through each table + //pull out words and add each word to the temporary dictionary + //with the word and the record it came from + //srchkey.type: 0=probs,1labour,2subrepair,3rentals,4clients + //5-contacts (client notebook) 6=units, 7=workorder headers (wo) + //********************************************************* + //********************************************************* + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + //zTrace("index C",false); + //PROBS (table 0)* + rs2->QueryReadOnly("SELECT probs.id, [brief] & \" \" & [probs].[notes] AS [text], probs.created AS idate, wo.client AS iclient " + "FROM probs LEFT JOIN wo ON probs.wolink = wo.id " + "WHERE (((probs.indexed)=False));"); + + if(!rs2->IsEmpty()) + { + + SuckWords(0); + } + ppg[0]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //zTrace("index D",false); + //LABOUR (table 1)* + rs2->QueryReadOnly("SELECT labor.id, labor.details AS [text], labor.stop AS idate, wo.client AS iclient " + "FROM (labor LEFT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id " + "WHERE (((labor.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(1); + } + + //AfxMessageBox("Done labour starting subrepair"); + ppg[1]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //zTrace("index E",false); + //SUBREPAIR (table2)* + rs2->QueryReadOnly("SELECT subrepair.id, subrepair.notes AS [text], subrepair.created AS idate, wo.client AS iclient " + "FROM (subrepair LEFT JOIN probs ON subrepair.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id " + "WHERE (((subrepair.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(2); + } + //AfxMessageBox("Done subrepair, starting rentals"); + ppg[2]->SetPos(100); + PeekAndPump(); + wait.Restore(); + //RENTALS (table 3)* + rs2->QueryReadOnly("SELECT rentals.id, [notes] & \" \" & [loanedto] & \" \" & [description] AS [text], rentals.dateout AS idate, rentals.clientlink AS iclient " + "FROM rentals " + "WHERE (((rentals.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(3); + } + ppg[3]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //CLIENTS (table 4)* + rs2->QueryReadOnly("SELECT clients.id, clients.id AS iclient, clients.created AS idate, [generalnotes] & \" \" & " + "[technotes] & \" \" & [alert] & \" \" & " + "[first] & \" \" & [last] & \" \" & [company] " + "& \" \" & [mailaddress] & \" \" & " + "[streetaddress] & \" \" & [city] & \" \" & " + "[stateprov] & \" \" & [postal] & \" \" & " + "[country] & \" \" & [bizphone] & \" \" & " + "[fax] & \" \" & [email] & \" \" & [acctnumber] AS [text] " + "FROM clients WHERE (((clients.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(4); + } + ppg[4]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //CONTACTS (table 5)* + rs2->QueryReadOnly( + "SELECT contacts.id, contacts.notes AS [text], contacts.date AS idate, " + "contacts.clientlink AS iclient FROM contacts " + "WHERE (((contacts.indexed)=False));"); + if(!rs2->IsEmpty()) + { + SuckWords(5); + } + ppg[5]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + //UNITS (table 6)* + rs2->QueryReadOnly("SELECT units.id, [units].[receipt] & \" \" & [units].[sn] & \" \" & [units].[id1] & \" \" & " + "[units].[id2] & \" \" & [units].[id3] & \" \" & [units].[notes] & \" \" & " + "[units].[description] AS [text], units.client AS iclient, " + "IIf(IsNull([units].[purchasedate]),IIf(IsNull([units].[created]), " + "IIf(IsNull([units].[modified]),#1/1/2000#,[units].[modified]),[units].[created]), " + "[units].[purchasedate]) AS idate " + "FROM units " + "WHERE (((units.indexed)=False) AND ((units.client)<>0));"); + + if(!rs2->IsEmpty()) + { + SuckWords(6); + } + ppg[6]->SetPos(100); + PeekAndPump(); + wait.Restore(); + + + //WORKORDER HEADER (TABLE 7) added 05/09/2001 + rs2->QueryReadOnly("SELECT wo.id, [wo].[notes] & \" \" & [wo].[invoice] & \" \" & [wo].[clientrefnum] & \" \" & " + "[wo].[clientcontact] & \" \" & [wo].[ourref] AS [text], wo.created AS idate, wo.client AS iclient " + "FROM wo " + "WHERE (((wo.indexed)=False));"); + + if(!rs2->IsEmpty()) + { + SuckWords(7); + } + ppg[7]->SetPos(100); + PeekAndPump(); + wait.Restore(); + //================================= + + //ADD new indexed items here. + + //To do: add wo header and woparts + + //================================= + + + + + //Make the dictionary: Stage 6 + //Pull out all the unique words from the temporary dictionary + //that do *not* appear in the stop words table of words to ignore + //and insert each one into the SearchDictionary, assigning + //each one an id number (new method now will do this automatically?) + + //05/09/2001 changed progress control to 10 as 7 is now wo table + //see initial update for more info + + rs2->QueryReadOnly("SELECT srchtempdict.word " + "FROM (srchtempdict LEFT JOIN srchstopwords ON srchtempdict.word = " + "srchstopwords.word) LEFT JOIN srchdict ON srchtempdict.word = srchdict.word " + "WHERE (((srchstopwords.word) Is Null)) " + "GROUP BY srchtempdict.word, srchdict.word;"); + if(rs2->IsEmpty()) + { + AfxMessageBox("No data to index"); + rs->Close(); + rs2->Close(); + return; + } + + wait.Restore(); + lUniqueWords=lRecs=rs2->FetchRecordCount(); + rs2->MoveFirst(); + lData=0; + ppg[10]->SetRange32(0,(int)lRecs); + pConnection->BeginTrans(); + do{ + rs2->FetchField("word",&strData); + lData++; + q.Format("INSERT INTO srchdict ( ID, word ) SELECT %u , \"%s\";",lData,strData); + + + + + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs2->MoveForward()); + pConnection->CommitTrans(); + + ppg[10]->SetPos((int)lData); + PeekAndPump(); + wait.Restore(); + + //Make keys: + //match up the words and tempdictionary and insert a single match from + //each record into the keys so that if the same word appears more + //than once in a record, it actually only causes one entry since at + //this point we don't care where in the actual record each repetition + //appears, only that there is at least one in record X. + //srchkey.type: 0=probs,1labour,2subrepair,3rentals,4clients + ppg[8]->SetPos(50); + rs->Ex("INSERT INTO srchkey ( [tableid], wordid, tabletype, client, [date] ) " + "SELECT DISTINCT srchtempdict.id, srchdict.ID, srchtempdict.type, srchtempdict.client, [srchtempdict].[date] " + "FROM srchdict RIGHT JOIN srchtempdict ON srchdict.word = srchtempdict.word " + "WHERE (((srchdict.word) Is Not Null));"); + + ppg[8]->SetPos(100); + PeekAndPump(); + //AfxMessageBox("passed stage 6"); + wait.Restore(); + + //final cleanup********************* + ppg[9]->SetPos(1); + PeekAndPump(); + wait.Restore(); + //Clean out the tempdict + //Empty temporary dictionary (should be empty anyway) + rs->Ex("DELETE srchtempdict.* FROM srchtempdict;"); + ppg[9]->SetPos(12); + PeekAndPump(); + wait.Restore(); + //Flag all indexed tables as being indexed + rs->Ex("UPDATE clients SET clients.indexed = True;"); + ppg[9]->SetPos(24); + PeekAndPump(); + wait.Restore(); + rs->Ex("UPDATE probs SET probs.indexed = True;"); + ppg[9]->SetPos(36); + PeekAndPump(); + wait.Restore(); + rs->Ex("UPDATE labor SET labor.indexed = True;"); + ppg[9]->SetPos(48); + PeekAndPump(); + wait.Restore(); + //AfxMessageBox("48% done..."); + rs->Ex("UPDATE subrepair SET subrepair.indexed = True;"); + ppg[9]->SetPos(60); + PeekAndPump(); + wait.Restore(); + //AfxMessageBox("60% done..."); + rs->Ex("UPDATE rentals SET rentals.indexed = True;"); + ppg[9]->SetPos(72); + PeekAndPump(); + wait.Restore(); + + //added may 9th 2001 for wo table + rs->Ex("UPDATE wo SET wo.indexed = True;"); + ppg[9]->SetPos(75); + PeekAndPump(); + wait.Restore(); + + + //compact the database + //close the recordsets first + + rs->Close(); + rs2->Close(); + pConnection->Close(); + //pConnection->Release(); + + m_pApp->rsPool->Disconnect(); + GetDocument()->Compact(false);//compact and dump old copy + m_pApp->rsPool->GoShared(); + + + ppg[9]->SetPos(90); + PeekAndPump(); + wait.Restore(); + + //AfxMessageBox("90% done..."); + + //mark index date in the global defaults table + //nice touch would be to also indicate how many unique words are + //indexed + + //re-open the recordset to update the defaults table + + + dtEnd=COleDateTime::GetCurrentTime(); + dtsDuration=dtEnd-dtStart; + fData=(float)(dtsDuration.GetTotalSeconds()/60); + if(bFullIndex) + { + + q.Format("UPDATE defaults SET defaults.lastfullindex = " + "#%s#, defaults.dictsize = %u, defaults.fullindextime = %f;",dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),lUniqueWords,fData); + } + else + { + + q.Format("UPDATE defaults SET defaults.lastpartindex = " + "#%s#, defaults.dictsize = %u, defaults.partindextime = %f;",dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),lUniqueWords,fData); + } + + rs->Ex(q); + + + + + ppg[9]->SetPos(100); + PeekAndPump(); + wait.Restore(); + rs->Close(); + + ShowIndexInfo(); + wait.Restore(); + AfxMessageBox("Index complete!"); + + + + } +*/ + + +void CDBUtils::ShowProgressControls(bool bShow) +{ + BOOL show = bShow ? TRUE : FALSE; + m_pg1.ShowWindow(show); + m_st1.ShowWindow(show); + m_pg2.ShowWindow(show); + m_st2.ShowWindow(show); + m_pg3.ShowWindow(show); + m_st3.ShowWindow(show); + m_pg4.ShowWindow(show); + m_st4.ShowWindow(show); + m_pg5.ShowWindow(show); + m_st5.ShowWindow(show); + m_pg6.ShowWindow(show); + m_st6.ShowWindow(show); + m_pg7.ShowWindow(show); + m_st7.ShowWindow(show); + m_st8.ShowWindow(show); + m_pg8.ShowWindow(show); + m_st9.ShowWindow(show); + m_pg9.ShowWindow(show); + m_st10.ShowWindow(show); + m_pg10.ShowWindow(show); + m_st11.ShowWindow(show); + m_pg11.ShowWindow(show); + + + for(int x=0;x<11;x++) + ppg[x]->SetPos(0); + + +} + +BOOL CDBUtils::PeekAndPump() +{ + + + static MSG msg; + + while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { + if (!AfxGetApp()->PumpMessage()) { + ::PostQuitMessage(0); + return FALSE; + } + } + + return TRUE; +} + + +long CDBUtils::FindMaxChar() +{ + long lBiggest=0; + int x; + CString strData; + rs2->MoveFirst(); + do{ + rs2->FetchField("text",&strData); + x=strData.GetLength(); + if(x>lBiggest) + lBiggest=x; + + + }while(rs2->MoveForward()); + rs2->MoveFirst(); + return lBiggest; +} + + + + + + +//suck the words out of the table in rs2 +bool CDBUtils::SuckWords(int nTable) +{ + CString str,strText,strWord,q,strDate,temp; + //register int lchar; + int nPos; + long lID; + //long lBiggest; + long lClient; + COleDateTime dtData; + + //Aug 6 2004 changes + //char ch; + TCHAR ch; + + + + //progress variables + //float currec,recs; + long currec,recs; + + //v1.9.4.5 re-wrote much of the code below + + //Aug 6th 2004 Replaced CStringList with CMapStringToString to + //aid in ensuring no duplicates here and no stop words + //as the real bottleneck is the insert sql command, not + //anything here + CMapStringToString ssWords; + CMapStringToString StopWords; + + StopWords.SetAt("about",0); + StopWords.SetAt("after",0); + StopWords.SetAt("all",0); + StopWords.SetAt("also",0); + StopWords.SetAt("an",0); + StopWords.SetAt("and",0); + StopWords.SetAt("another",0); + StopWords.SetAt("any",0); + StopWords.SetAt("are",0); + StopWords.SetAt("as",0); + StopWords.SetAt("at",0); + StopWords.SetAt("be",0); + StopWords.SetAt("because",0); + StopWords.SetAt("been",0); + StopWords.SetAt("before",0); + StopWords.SetAt("being",0); + StopWords.SetAt("between",0); + StopWords.SetAt("both",0); + StopWords.SetAt("but",0); + StopWords.SetAt("by",0); + StopWords.SetAt("came",0); + StopWords.SetAt("can",0); + StopWords.SetAt("come",0); + StopWords.SetAt("could",0); + StopWords.SetAt("did",0); + StopWords.SetAt("do",0); + StopWords.SetAt("does",0); + StopWords.SetAt("each",0); + StopWords.SetAt("else",0); + StopWords.SetAt("for",0); + StopWords.SetAt("from",0); + StopWords.SetAt("get",0); + StopWords.SetAt("got",0); + StopWords.SetAt("had",0); + StopWords.SetAt("has",0); + StopWords.SetAt("have",0); + StopWords.SetAt("he",0); + StopWords.SetAt("her",0); + StopWords.SetAt("here",0); + StopWords.SetAt("him",0); + StopWords.SetAt("himself",0); + StopWords.SetAt("his",0); + StopWords.SetAt("how",0); + StopWords.SetAt("if",0); + StopWords.SetAt("in",0); + StopWords.SetAt("into",0); + StopWords.SetAt("is",0); + StopWords.SetAt("it",0); + StopWords.SetAt("its",0); + StopWords.SetAt("just",0); + StopWords.SetAt("like",0); + StopWords.SetAt("make",0); + StopWords.SetAt("many",0); + StopWords.SetAt("me",0); + StopWords.SetAt("might",0); + StopWords.SetAt("more",0); + StopWords.SetAt("most",0); + StopWords.SetAt("much",0); + StopWords.SetAt("must",0); + StopWords.SetAt("my",0); + StopWords.SetAt("never",0); + StopWords.SetAt("now",0); + StopWords.SetAt("of",0); + StopWords.SetAt("on",0); + StopWords.SetAt("only",0); + StopWords.SetAt("or",0); + StopWords.SetAt("other",0); + StopWords.SetAt("our",0); + StopWords.SetAt("out",0); + StopWords.SetAt("over",0); + StopWords.SetAt("re",0); + StopWords.SetAt("said",0); + StopWords.SetAt("same",0); + StopWords.SetAt("see",0); + StopWords.SetAt("should",0); + StopWords.SetAt("since",0); + StopWords.SetAt("so",0); + StopWords.SetAt("some",0); + StopWords.SetAt("still",0); + StopWords.SetAt("such",0); + StopWords.SetAt("take",0); + StopWords.SetAt("than",0); + StopWords.SetAt("that",0); + StopWords.SetAt("the",0); + StopWords.SetAt("their",0); + StopWords.SetAt("them",0); + StopWords.SetAt("then",0); + StopWords.SetAt("there",0); + StopWords.SetAt("these",0); + StopWords.SetAt("they",0); + StopWords.SetAt("this",0); + StopWords.SetAt("those",0); + StopWords.SetAt("through",0); + StopWords.SetAt("to",0); + StopWords.SetAt("too",0); + StopWords.SetAt("under",0); + StopWords.SetAt("up",0); + StopWords.SetAt("use",0); + StopWords.SetAt("very",0); + StopWords.SetAt("want",0); + StopWords.SetAt("was",0); + StopWords.SetAt("way",0); + StopWords.SetAt("we",0); + StopWords.SetAt("well",0); + StopWords.SetAt("were",0); + StopWords.SetAt("what",0); + StopWords.SetAt("when",0); + StopWords.SetAt("where",0); + StopWords.SetAt("which",0); + StopWords.SetAt("while",0); + StopWords.SetAt("who",0); + StopWords.SetAt("will",0); + StopWords.SetAt("with",0); + StopWords.SetAt("would",0); + StopWords.SetAt("you",0); + StopWords.SetAt("your",0); + + //hand chosen items + StopWords.SetAt("ll",0); + + int nWords; + _bstr_t strSQL; + + + int nLength; + CWaitCursor wait; + + //Commented out Aug 4th 2004, + //what's the point really? + + //lBiggest=FindMaxChar(); + ////zTrace("Suck C",false); + ////don't waste time on an empty table + //if(lBiggest< 3) + //{ + // + // return true; + // + //} + + + //pnTable is actually supposed to be an unsigned char + //but there doesn't seem to be a good CString::Format() + //for that + ASSERT(nTable>-1 && nTable < 256); + recs=rs2->FetchRecordCount(); + currec=0; + + strText.Empty(); + strWord.Empty(); + nPos=0; + nLength=0; + //03/09/2003 changed to 100 + //to fix problem where it would show as incomplete when done + ppg[nTable]->SetRange32(0,100);//(int)recs); + ppg[nTable]->SetPos(0); + + do + { + + currec++; + + //TEST 03/09/2004 to put back user feedback + + /*if(currec % 500 == 0) + { + ppg[nTable]->SetPos(int(currec/recs*100)); + PeekAndPump(); + wait.Restore(); + }*/ + + //rs2->FetchField("text",&strText); + //Updated 1.9.4.6 09-May-2005 to fix problem with + //total amount of text exceeding 255 characters + rs2->FetchAllTextFieldsAsOneString(&strText); + strText.MakeLower(); //make all lower case + rs2->FetchField("id",&lID); + rs2->FetchField("iclient",&lClient); + rs2->FetchField("idate",&dtData); + strDate=dtData.Format(_T("%m/%d/%Y")); + if(strDate.IsEmpty()) + { + dtData=COleDateTime::GetCurrentTime(); + switch(nTable) + { + case 0: + temp="PROBLEMS"; + break; + case 1: + temp="LABOUR"; + break; + case 2: + temp="SUBREPAIRS"; + break; + case 3: + temp="RENTALS"; + break; + case 4: + temp="CLIENTS"; + break; + case 5: + temp="CONTACTS"; + break; + case 6: + temp="UNITS"; + break; + } + + strDate.Format( + "During indexing on %s while parsing records an error occured:\r\n" + "An internal date is missing from the following record\r\n" + "Table:%s, Record:%u\r\n" + "To keep things rolling, todays date was substituted instead\r\n" + "Consequences: This record will show as being created today in a search\r\n" + "although it was probably created at an earlier date. \r\n" + "Otherwise, you should be able to work as normal.\r\n" + "Please inform tech support with the details of this message.\r\n" + "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r\n" + ,dtData.Format(_T("%m/%d/%Y %H:%M:%S")),temp,lID); + LogError(strDate); + //strDate=dtData.Format(VAR_DATEVALUEONLY); + strDate=dtData.Format(_T("%m/%d/%Y")); + + } + + //zTrace("Suck G",false); + + //make sure there is something to parse + nLength=strText.GetLength(); + + //PROCESS BLOCK OF TEXT + int nWordLength=0; + if (nLength > 1) + { + + strWord.Empty(); + ssWords.RemoveAll(); + nWords=0; + + //loop through all characters in strText + for(nPos=0;nPos < nLength;nPos++) + { + ch=strText.GetAt(nPos); + if( (/*IsAlpha*/ch>=97 && ch<=122) || (/*IsDigit*/ ch >='0' && ch<='9') ) + { + strWord+=ch; + nWordLength++; + } + else if(strWord!="")//is a non-regular text character + { + if(nWordLength>1)//greater than one character + { + if(!StopWords.Lookup(strWord,temp)) + ssWords.SetAt(strWord,0); + } + + strWord.Empty(); + nWordLength=0; + }//end of else for a non regular character + }//lPos loop + + + //Manually add last word + if(strWord!="") + { + if(nWordLength>50) + strWord=strWord.Left(50); + + if(nWordLength>1) + { + if(!StopWords.Lookup(strWord,temp)) + ssWords.SetAt(strWord,"0"); + } + + } + + + + //SAVE all Words + + rs->pTheConnection->BeginTrans(); + + POSITION pos = ssWords.GetStartPosition( ); + while( pos != NULL ) + { + ssWords.GetNextAssoc( pos, strWord, temp ); + + q.Format("INSERT INTO srchtempdict ( word, id, type, client, [date] ) " + "SELECT '%s' , %u , %i, %u, #%s#;",strWord,lID,nTable,lClient, + strDate); + rs->Ex(q); + + } + + rs->pTheConnection->CommitTrans(); + + }//END PROCESS BLOCK OF TEXT + + + /* ORIGINAL (PRE AUG 6 2004) PROCESS BEFORE ATTEMPTED OPTIMIZATION + + //PROCESS BLOCK OF TEXT + if (nLength > 1) + { + + strWord.Empty(); + slWords.RemoveAll(); + nWords=0; + slWords.AddHead(".");//to save overhead of checking if first inside loop + //zTrace("Suck H",false); + //loop through all characters in strText + for(nPos=0;nPos < nLength;nPos++) + { + ch=strText.GetAt(nPos); + if(isalnum(ch)) + strWord+=ch; + else//is a non-regular text character + { + slWords.AddTail(strWord); + nWords++; + strWord.Empty(); + }//end of else for a non regular character + }//lPos loop + + + //have to add the very last strWord in manually, this may not really be necessary + //but does not hurt as all duplicates are purged anyway later on in the process + slWords.AddTail(strWord); + nWords++; + + //zTrace("Suck I",false); + + //SAVE all Words + rs->pTheConnection->BeginTrans(); + for(int x=1;x 1 )//changed 12/19/00 from 2 letters to 1 letters + { + if(strWord.GetLength()>50) strWord=strWord.Left(50);//added 07/06/2001 because db wordsize is only 50 + q.Format("INSERT INTO srchtempdict ( word, id, type, client, [date] ) " + "SELECT \"%s\" , %u , %i, %u, #%s#;",strWord,lID,nTable,lClient,dtData.Format(_T("%m/%d/%Y"))); + //_T("%m/%d/%Y %H:%M:%S") + rs->Ex(q); + } + } + + rs->pTheConnection->CommitTrans(); + //zTrace("Suck J",false); + }//END PROCESS BLOCK OF TEXT + */ + + + + + }while(rs2->MoveForward());// && currec < CUTOFF); + + //ppg[nTable]->SetPos(100); + //PeekAndPump(); + //wait.Restore(); + + + + return true; + +} + + +void CDBUtils::ShowIndexInfo() +{ + CString strData,txt; + long lData; + float fData; + COleDateTime dtData; + + rs->Query("SELECT defaults.* FROM defaults;"); + + rs->FetchField("lastpartindex",&dtData); + rs->FetchField("partindextime",&fData); + + if(dtData.GetYear()==1968)//no record yet + { + txt="Partial index has not yet been run."; + + } + else + { + txt.Format("Last partial index: %s took %.2f minutes to complete.",dtData.Format(_T("%m/%d/%Y %H:%M:%S")),fData); + } + m_lblPartialInfo.SetWindowText(txt); + + + txt.Empty(); + rs->FetchField("lastfullindex",&dtData); + rs->FetchField("fullindextime",&fData); + + if(dtData.GetYear()==1968)//no record yet + { + txt="Full index has not yet been run."; + + } + else + { + txt.Format("Last full index: %s took %.2f minutes to complete.",dtData.Format(_T("%m/%d/%Y %H:%M:%S")),fData); + } + m_lblFullInfo.SetWindowText(txt); + + txt.Empty(); + rs->FetchField("dictsize",&lData); + + txt.Format("Total unique searchable words: %u",lData); + m_lblWordCount.SetWindowText(txt); + rs->Close(); + +} + +void CDBUtils::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + bool PreEval; + CString strData; + //check if going from unregistered to registered + //if so, erase all data now automatically + if(m_pApp->m_uiFeatures&LICENSE_REGISTERED) + PreEval=false; + else + PreEval=true; + + if(m_pApp->m_lusrID!=1) + { + AfxMessageBox("You must log in using the manager account\r\n" + "to perform this action"); + return;//only the manager! + } + CKD d; + d.DoModal(); + + //check and see if were now unregistered + if(PreEval) + { + //lookup regto name + //if not "Evaluation" then erase data + + + rs->Query("SELECT regto FROM defaults;"); + rs->FetchField("regto",&strData); + rs->Close(); + + if(strData!="Evaluation" && strData!="AyaNova Evaluation") + { + if(AfxMessageBox("*** READ CAREFULLY ***\r\n\r\n" + + "All data in the AyaNova database is about to be erased.\r\n" + "This will remove all the sample data and any data you have entered\r\n" + "while evaluating AyaNova so that you can start with a fresh database.\r\n\r\n" + + "It is recommended that you answer yes to erase the data.\r\n\r\n" + + "Erase the AyaNova database?",MB_YESNO)==IDYES) + { + EraseAll(); + AfxMessageBox("Close and restart AyaNova now"); + } + else + { + AfxMessageBox("The data will not be erased.\r\n\r\n" + "You can erase it later using the\r\n" + "erase all data button on the database utilities screen.\r\n\r\n" + + "All technicians in the trial database will now be set to inactive\r\n" + "to ensure that you will not be locked out of the program when you restart it.\r\n"); + GZK k; + CString a,b,strTemp; + bool bValue=false; + + /* +SELECT users.active, users.a, users.b +FROM users +WHERE (((users.id)<>1) AND ((users.tech)=True) AND ((users.active)=True)); + + */ + if(!rs->Query(k.InLineDecrypt("A38sl+nbfd//IE2wby+SBMb8KnIh47GwGTMGXdofhDKwwdw2ui69FDkyDMaJsKxSKAPJ00vU" +"KPXl4BOk4qFk+7lURE/y7g/NVRVb1TgRUGLFdtnAPyaQa26Q882oAkJnmZCQ9b5jBm1W4TUy" +"5lmFLCDBYrQke0n9yeSogzoeLHdHvfntlbYwBAds6gckYs/M"))) + { + /* Unable to set technicians to inactive +Contact tech support */ + AfxMessageBox(k.InLineDecrypt("O5i0JrVLzlAwwEkvQIYCzr3YiwN0XqwuAu2j5geep7lPwJxQ0J1Jv7V/gy6XNK9N4LwHMUqC" +"c6cijWvlEjdYXA==")); + + } + do{ + //LOOP through all active tech users who are not manager account + //read in 'a' field + rs->FetchField(k.InLineDecrypt("zpiZm0o4SPSHizSP27V8lg"),&a); + //decrypt + k.GZDecrypt(&a,false); + //replace rightmost string "TRUE" with "FALSE" + //"TRUETRUE", "TRUEFALSE" + a.Replace(k.InLineDecrypt("nOmVnvypPUdu0dKmUO4Zuw"),k.InLineDecrypt("bMctUK0utAKMdgo8T9s4bQ")); + + //calc a hash of it, + b=a; + k.GZHash(&b); + + //re-encrypt a field + k.GZEncrypt(&a,false); + + //write 'a' back, write hash to b field, set active to false + rs->UpdateField(k.InLineDecrypt("zpiZm0o4SPSHizSP27V8lg"),&a); + rs->UpdateField(k.InLineDecrypt("lIgbn+v0h55FcZSl6rhR4A"),&b); + rs->UpdateField(k.InLineDecrypt("67gzOWhzGhgW7mlFH6aQfA"),&bValue); + //LOOP + }while(rs->MoveForward()); + AfxMessageBox("Close and restart AyaNova now"); + + } + } + + + } + + + + + +} + + + + + + + + + + +//************************************************************* +//************************************************************* +//************************************************************* +//************************************************************* +//************************************************************* +//************************************************************* +//************************************************************* + +void CDBUtils::OnBtncm3() +{ + + CString q,strData,strWOID,strOriginalID,str; + long lData,lLink,lTechID,recs,currec; + COleDateTime dtData,dtTime,dtDate,dtStart,dtStop; + float fData; + bool bData,bMissingClient=false; + int pct=0; + m_pg1.ShowWindow(TRUE); + m_pg1.SetPos(0); + AfxMessageBox("Before proceeding ensure you have\r\n" + "the following tables linked in from CM3:\r\n" + "Calls, Customers, Techs, Type of call"); + + if(AfxMessageBox("Ready?",MB_YESNO)==IDNO) return; + + CWaitCursor wait; + + + + //********* IMPORT TABLES FIRST ************** + //These will only import records that do not exist + //not duplicates will be created + + //CLIENTS + rs->Ex("INSERT INTO clients ( company ) " + "SELECT Customers.[Customer Name] " + "FROM Customers LEFT JOIN clients ON Customers.[Customer Name] = clients.company " + "WHERE (((clients.company) Is Null));"); + + //TECHS + rs->Ex("INSERT INTO users ( [first], [last], initials, active, login, pass, tech ) " + "SELECT \"IMPORTED\" AS Expr4, Techs.Technician, Techs.[Tech Code Abbreviation], False AS Expr1, \"IMPORTED\" AS Expr2, \"IMPORTED\" AS Expr3, True AS Expr5 " + "FROM Techs LEFT JOIN users ON Techs.[Tech Code Abbreviation] = users.initials " + "WHERE (((users.initials) Is Null));"); + + //RATES + rs->Ex("INSERT INTO rates ( name, rate, active, travelrate ) " + "SELECT [Type of Call].Description, [Type of Call].HourlyWork, [Type of Call].Active, False AS typerate " + "FROM [Type of Call] LEFT JOIN rates ON [Type of Call].Description = rates.name " + "WHERE (((rates.name) Is Null));"); + + //************** import workorders ************** + //trickier operation, can only be done once? + rs->Query("SELECT Calls.[Master Invoice Number], Calls.Customer, Calls.Description, Calls.[Billable Hours], Calls.Date, clients.id AS clientid, users.id AS techid, Calls.[Arrival Time], Calls.[Departure Time], Calls.[Billing Invoice Number], Calls.[Travel hours], rates.id AS rateid " + "FROM rates RIGHT JOIN (((Calls LEFT JOIN clients ON Calls.Customer = clients.company) LEFT JOIN users ON Calls.Technician = users.last) LEFT JOIN [Type of Call] ON Calls.[Call type] = [Type of Call].ID) ON rates.name = [Type of Call].Description;"); + + if(!rs->IsEmpty()) + { + currec=0; + recs=rs->FetchRecordCount(); + m_pg1.SetRange32(0,(int)recs); + rs->MoveFirst(); + do{//************ SEE SIMPLE WO TO SAVE TIME THIS MORNING!! + //create a workorder header record flagged as quick wo + //keep message queue flowing + currec++; + //pct=(int)((float)(currec/recs)*100); + //pct=(int)(((float)currec/(float)recs)*100); + m_pg1.SetPos(currec); + PeekAndPump(); + wait.Restore(); + /* + if(currec== 150) + if(AfxMessageBox("150 - Stop now?",MB_YESNO)==IDYES) + return; + if(currec== 300) + if(AfxMessageBox("300 - Stop now?",MB_YESNO)==IDYES) + return; + */ + + bMissingClient=false; + + //FETCH AND SET VALUES FOR LATER USAGE + //GET TECH FOR LATER*********************************************** + rs->FetchField("techid",&lTechID); + //keep the date for later on processing + rs->FetchField("Date",&dtDate); + //GET START DATE/TIME + rs->FetchField("Arrival Time",&dtTime); + rs->FetchField("Date",&dtDate); + dtStart.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + //GET STOP DATE TIME + rs->FetchField("Departure Time",&dtTime); + dtStop.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + + + + //start a new workorder: + //open the workorder table with a query guaranteed to + //return no records as this is probably better performance + rs2->Query("SELECT wo.* FROM wo WHERE (((wo.id)=0));");// + + //now add the new record + rs2->AddNewRecord(); + rs2->UpdateField("creator",&lTechID); + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + rs2->UpdateField("created",&dtDate); + rs2->SaveRecord(); + + //now go back and find the record just created to get the id number + //by using some unique variables for the query + q.Format("SELECT wo.* FROM wo WHERE (((wo.creator)=%u) " + "AND ((wo.created)=#%s#) AND ((wo.client)=0));",lTechID,dtDate.Format(_T("%m/%d/%Y"))); + rs2->Query(q); + rs2->FetchField("id",&lData); + //save the workorder ID number + strWOID.Format("%u",lData); + + //CLIENT + rs->FetchField("clientid",&lData); + if(lData==0) + bMissingClient=true; + + rs2->UpdateField("client",&lData); + + //CATEGORY + lData=0; + rs2->UpdateField("type",&lData); + + //CLOSED - time workorder closed (now) + + rs2->UpdateField("closed",&dtDate); + + //ONSITE + bData= true;//TREAT all as onsite regardless + rs2->UpdateField("onsite",&bData); + + //STARTTIME + rs->FetchField("Arrival Time",&dtData); + rs2->UpdateField("starttime",&dtData); + + //STOPTIME + rs->FetchField("Departure Time",&dtData); + rs2->UpdateField("stoptime",&dtData); + + //QUICK - flag this as a quickie workorder + //so that it gets displayed on this screen + //when selected to view + bData=true; + rs2->UpdateField("quick",&bData); + + + + //INVOICE # + rs->FetchField("Billing Invoice Number",&strData); + rs2->UpdateField("invoice",&strData); + + + + rs2->SaveRecord(); + + + + //Create a problem record + + //open the probs table, return no records + rs2->Query("SELECT probs.* FROM probs WHERE (((probs.id)=0));"); + rs2->AddNewRecord(); + + + + //SAVE THE WORKORDER ID NUMBER + rs2->UpdateField("wolink",&strWOID); + + //STATUS to zero + lData=0; + rs2->UpdateField("status",&lData); + + //CREATOR + + rs2->UpdateField("creator",&lTechID); + + + //Save problem record + rs2->SaveRecord(); + + //get id of problem record + q.Format("SELECT probs.id FROM probs " + "WHERE (((probs.wolink)=%s) AND " + "((probs.status)=0) AND " + "((probs.creator)=%u));",strWOID,lTechID); + + + rs2->Query(q); + lLink=0; + rs2->FetchField("id",&lLink); + ASSERT(lLink!=0); + + + //************************************ + //************************************ + //Use id to create a labour table record + //firstly open the labor table in a way that returns no records + rs2->Query("SELECT labor.* FROM labor WHERE (((labor.link)=0));"); + rs2->AddNewRecord(); + //set labour record fields + + //LINK TO PROBLEM RECORD + rs2->UpdateField("link",&lLink); + + //TECH + + rs2->UpdateField("tech",&lTechID); + + + //HOURS + rs->FetchField("Billable Hours",&fData); + rs2->UpdateField("hours",&fData); + + //NOCHARGE HOURS + fData=0; + rs2->UpdateField("nchours",&fData); + + //TRAVEL HOURS + rs->FetchField("Travel hours",&fData); + rs2->UpdateField("travhours",&fData); + + //RATE + rs->FetchField("rateid",&lData); + rs2->UpdateField("rate",&lData); + + //TRAVEL RATE + rs->FetchField("rateid",&lData);//BUG BUG CHANGE FOR OTHERS WE DONT USE TRAVEL + //this is a lazy avoidance of figuring out the travel rate. + rs2->UpdateField("travrate",&lData); + + + + //START + + + rs2->UpdateField("start",&dtStart); + + //STOP + + rs2->UpdateField("stop",&dtStop); + + + + //DETAILS + + rs->FetchField("Master Invoice Number",&strOriginalID); + rs->FetchField("Description",&strData); + strData="< Original workorder #: " + strOriginalID + " >\r\n" + strData; + if(bMissingClient) + { + rs->FetchField("Customer",&str); + strData+="MISSING CUSTOMER DURING IMPORT! - WAS:" + str + "\r\n"; + } + rs2->UpdateField("details",&strData); + + + rs2->SaveRecord(); + + + + + + }while(rs->MoveForward()); + + + + AfxMessageBox("Finished"); + +}//not rs empty +rs->Close(); +rs2->Close(); + +} + +void CDBUtils::ShowMe(CString txt) +{ + CTED d; + d.m_strText=txt; + d.DoModal(); +} + +void CDBUtils::zTrace(CString msg,bool bShow) +{ + if(TRACING==1) + { + if(bShow) + ShowMe(msg); + else + AfxMessageBox(msg); + + + } + +} + +void CDBUtils::LogError(CString strError) +{ + m_strErrorLog+=strError+"\r\n"; + +} + +void CDBUtils::SetRights() +{ + int x=m_pApp->Allowed(RDBUTIL,true); + if(x==1) return;//full access + + + //default is read only + m_btnCM3.ShowWindow(FALSE); + m_btnCompact.ShowWindow(FALSE); + m_btnDefaults.ShowWindow(FALSE); + m_btnIndexAll.ShowWindow(FALSE); + m_btnQuickIndex.ShowWindow(FALSE); + + + +} + +void CDBUtils::OnBtndeleteall() +{ + if(AfxMessageBox( + "Warning: you are about to completely erase\r\n" + "ALL data. This operation can *not* be undone.\r\n" + "If you want to keep the current data \r\n" + "make a backup outside AyaNova first.\r\n\r\n" + "Do you wish to proceed?",MB_YESNO)==IDYES) + { + + if(AfxMessageBox("Are you certain you want to completely erase all data?",MB_YESNO)==IDYES) + EraseAll(); + + } + + +} + +void CDBUtils::EraseAll() +{ + + //Attempt to go Exclusive + if(!m_pApp->rsPool->GoExclusive()) + { + AfxMessageBox("In order to protect the integrity of your data\r\n" + "you need exclusive access to the database to access this function.\r\n" + "\r\nAll other users must exit before proceeding."); + //back to shared mode + m_pApp->rsPool->GoShared(); + return; + } + + + //Ok, everyone is out, go shared + m_pApp->rsPool->GoShared(); + + + + rs->Close(); + + rs->Ex("DELETE clients.* FROM clients;"); + rs->Ex("DELETE contacts.* FROM contacts;"); + rs->Ex("DELETE contracts.* FROM contracts;"); + rs->Ex("DELETE groups.*, groups.id FROM groups WHERE (((groups.id)<>1));"); + rs->Ex("DELETE labor.* FROM labor;"); + rs->Ex("DELETE mail.* FROM mail;"); + rs->Ex("DELETE mailroute.* FROM mailroute;"); + rs->Ex("DELETE nonclients.* FROM nonclients;"); + rs->Ex("DELETE parts.* FROM parts;"); + rs->Ex("DELETE pmparts.* FROM pmparts;"); + rs->Ex("DELETE pmhead.* FROM pmhead;"); + rs->Ex("DELETE pmitems.* FROM pmitems;"); + rs->Ex("DELETE probs.* FROM probs;"); + //rs->Ex("DELETE probstat.* FROM probstat;"); + rs->Ex("DELETE projects.* FROM projects;"); + rs->Ex("DELETE rentals.* FROM rentals;"); + rs->Ex("DELETE rates.* FROM rates;"); + rs->Ex("DELETE rptsusers.* FROM rptsusers;"); + rs->Ex("DELETE labor.* FROM labor;"); + rs->Ex("DELETE srch.* FROM srch;"); + rs->Ex("DELETE srchdict.* FROM srchdict;"); + rs->Ex("DELETE srchkey.* FROM srchkey;"); + rs->Ex("DELETE srchtempdict.* FROM srchtempdict;"); + rs->Ex("DELETE statusviews.*, statusviews.viewname FROM statusviews WHERE (((statusviews.viewname)<>\"< default >\"));"); + rs->Ex("DELETE subrepair.* FROM subrepair;"); + rs->Ex("DELETE tasks.* FROM tasks;"); + rs->Ex("DELETE unitmodelcats.* FROM unitmodelcats;"); + rs->Ex("DELETE unitmodels.* FROM unitmodels;"); + rs->Ex("DELETE units.* FROM units;"); + + rs->Ex("DELETE users.*, users.id FROM users WHERE (((users.id)<>1));"); + + rs->Ex("DELETE wo.* FROM wo;"); + rs->Ex("DELETE woparts.* FROM woparts;"); + rs->Ex("DELETE wotypes.* FROM wotypes;"); + rs->Ex("DELETE zones.* FROM zones;"); + + //Added 09/18/2001 + rs->Ex("DELETE schdets.* FROM schdets;"); + rs->Ex("DELETE schdgrps.* FROM schdgrps;"); + rs->Ex("DELETE schedmarkers.* FROM schedmarkers;"); + //------------------------------------------------- + + //reset manager password to login manager pw: letmein + rs->Ex("UPDATE users SET users.login = \"3029163104\", users.pass = \"1901781427\" " + "WHERE (((users.id)=1));"); + + //Added 08/27/2001 + rs->Ex("INSERT INTO zones ( name ) SELECT \"Default zone\";"); + rs->Ex("INSERT INTO clients ( company ) SELECT \"Default client\";"); + + rs->Ex("INSERT INTO rates ( name, rate, cost, expires, travelrate, partnum ) " + "SELECT \"Default rate\", 1,1, #1/1/3000#, False, 1;"); + + rs->Ex("INSERT INTO rates ( name, rate, cost, expires, travelrate, partnum ) " + "SELECT \"Default travel rate\", 1,1, #1/1/3000#,True, 1;"); + + + + + + + rs->Close(); + + + m_pApp->rsPool->GoExclusive(); + m_pApp->rsPool->Disconnect(); + GetDocument()->Compact(false);//compact and keep backup copy + rs->m_bExclusiveConnection=false; + //rs->Close(); + + //Ok, everyone is out, go shared + m_pApp->rsPool->GoShared(); + + /*AfxMessageBox("Finished"); + + //compact + GetDocument()->Compact(false);//compact and dont keep backup copy + */ + AfxMessageBox("Erase complete.\r\nNote: the manager account was set back to the default\r\n" + "login name which is: \"manager\"\r\nand the default password which is: \"letmein\"\r\n\r\nAyaNova will now close."); + PostQuitMessage(-1); + +} + + + + + + +//FUTURE READER keywords to find this method +//update database schema 171 1.9 scdata.sc ayanova ce +//etc etc etc +void CDBUtils::UpdateDatabaseSchema() +{ + + int nVersion; + CString msg,strTemp,strData; + //long lData; + + CString q,q2; + COleDateTime dtDefault; + dtDefault.SetDate(1968,03,12); + nVersion=atoi(m_pApp->m_strDataVersion); + bool buptodate=false; + m_bBootScanDone=true;//dont try to do both at once + bool bUpdateRanOK; + + //do whatever updates are necessary. + while (!buptodate) + { + switch (nVersion) + { + //================================================== + case 126://changed to 127 on 8/22/00 + { + //Added a record to the rptsmaster table for the + //workorder dispatch report + //Not a schema update only an added record + + + //see if the record is here already so it's not done twice: + rs->Query("SELECT rptsmaster.virtualname " + "FROM rptsmaster WHERE (((rptsmaster.virtualname)=\"Workorder dispatch\"));"); + if(rs->IsEmpty()) + { + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Workorder dispatch\", \"wodispst.rpt\", \"wodispatch\", False, 32767, 21;"); + + + + } + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"127\";"); + nVersion=127; + + + } + + break; + //====================================================== + case 127://changed to 128 on 8/24/00 + { + //Added a record to the rptsmaster table for the + //QUICK workorder dispatch report + //Not a schema update only an added record + + + //see if the record is here already so it's not done twice: + rs->Query("SELECT rptsmaster.virtualname " + "FROM rptsmaster WHERE (((rptsmaster.virtualname)=\"Workorder dispatch (Quick)\"));"); + if(rs->IsEmpty()) + { + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Workorder dispatch (Quick)\", \"wodispqu.rpt\", \"wodispatch\", False, 32767, 22;"); + + + + } + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"128\";"); + nVersion=128; + + } + + break; + + //===================================================== + case 128://changed to 129 on 8/28/00 + { + //Dropped contacts table fields: wolink, problink + //added fields: clientlink + + + rs->Ex("ALTER TABLE contacts DROP COLUMN wolink;"); + rs->Ex("ALTER TABLE contacts DROP COLUMN problink;"); + rs->Ex("ALTER TABLE contacts ADD COLUMN clientlink LONG;"); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"129\";"); + + nVersion=129; + } + + break; + case 129://changed to 130 on 8/29/00 - 8/31/00 + { + //contacts table added field:indexed + //units table added field:indexed + + rs->Ex("ALTER TABLE contacts ADD COLUMN indexed YESNO;"); + rs->Ex("UPDATE contacts SET contacts.indexed = False;"); + + rs->Ex("ALTER TABLE units ADD COLUMN indexed YESNO;"); + rs->Ex("UPDATE units SET units.indexed = False;"); + + //add the unit history to reports screen + q2="SELECT \"user\" AS zCurrentUser, probs.id, Format([start],\"Short Date\") AS " + "servdate, labor.details, IIf(IsNull([company]),[clients]![last] & \", \" & [clients]![first],[company]) " + "AS clientcompany, units.sn, unitmodels.model, users.initials, probs.meter, ztotalparts.totalparts, " + "ztotallabor.totallabor " + "FROM [SELECT Sum((labor.hours*rates.rate)+(labor.travhours*travrates.rate)) AS totallabor, " + "probs.id FROM probs INNER JOIN (rates INNER JOIN (rates AS travrates INNER JOIN labor ON " + "travrates.id = labor.rate) ON rates.id = labor.rate) ON probs.id = labor.link GROUP BY probs.id]. AS " + "ztotallabor RIGHT JOIN ([SELECT IIf(IsNull(Sum(woparts.quantity*woparts.price)),0, " + "Sum(woparts.quantity*woparts.price)) AS totalparts, probs.id FROM probs LEFT JOIN woparts " + "ON probs.id = woparts.link GROUP BY probs.id]. AS ztotalparts RIGHT JOIN (users RIGHT JOIN " + "((labor RIGHT JOIN (((wo RIGHT JOIN probs ON wo.id = probs.wolink) LEFT JOIN units ON " + "probs.unit = units.id) LEFT JOIN unitmodels ON units.model = unitmodels.id) ON labor.link = " + "probs.id) LEFT JOIN clients ON wo.client = clients.id) ON users.id = labor.tech) ON ztotalparts.id " + "= probs.id) ON ztotallabor.id = probs.id " + "WHERE (((probs.unit)~UNIT) AND ((units.sn) Is Not Null) AND ((labor.start) Between #~STRT# And #~END_#)) " + "ORDER BY labor.start DESC;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.x = True, rptsmaster.criteriafields = 400, rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=7));",q2); + + rs->Ex(q); + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"130\";"); + nVersion=130; + + + } + + break; + //===================================================== + case 130://changed to 131 on 9/12/00 + { + //PM module additions + + rs->Ex("ALTER TABLE pmschedules ADD COLUMN autoworkorder YESNO;"); + rs->Ex("UPDATE pmschedules SET pmschedules.autoworkorder = False;"); + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"131\";"); + + nVersion=131; + + + } + + break; + //*************************************************************************** + case 131://changed to 132 on 9/22/00 and now 133 on 10/02/00 + { //since it's unreleased, decided to bump up one more. + //PM module additions + + + //Add a last meter reading column to the units table + //this is updated when someone enters a workorder unit count. + //to make pm easier to deal with. + + rs->Ex("ALTER TABLE units ADD COLUMN lastmeter INTEGER;"); + //NOTE: CANT SET TO DEFAULT OF ZERO WITHOUT IT CRASHING OUT + + + + //Delete the pmschedules, superseded by pmhead table below + rs->Ex("DROP TABLE pmschedules;"); + + + //new pm header table + q.Format("CREATE TABLE pmhead (" + "id COUNTER CONSTRAINT PK_pmhead PRIMARY KEY, " + "description TEXT(50), " + "notes MEMO, " + "link INTEGER DEFAULT 0, "//link to client or unit id number + "type INTEGER DEFAULT 0, " //0-timebased,1-meter,2-agebased + "isclient YESNO DEFAULT False, " //true = client false=unitbased + "ismodel YESNO DEFAULT False, " //true = MODEL false=units or clients + "autowo YESNO DEFAULT False, " + "autorpt YESNO DEFAULT False, " + "dow INTEGER DEFAULT 0," //autoschedule day of week 0any 1-monday 2-tuesd etc + "tech INTEGER DEFAULT 0, " //HEREpreferred technician + "woconvert INTEGER DEFAULT 0, " //convert to workorder days / meter counts in advance + "nextsrvdate DATETIME DEFAULT #%s#, " + "nextsrvmeter INTEGER DEFAULT 0, "//next meter count to service on + "repeatevery INTEGER DEFAULT 0, "//repeat every meter / months + "agemonths INTEGER DEFAULT 0, "//Age based: months old to schedule + "ageyears INTEGER DEFAULT 0, "//Age based: years old to schedule + "active YESNO DEFAULT True, "//on hold or active? + "series INTEGER DEFAULT 0, "//schedule this many series at a time + "creator INTEGER DEFAULT 0, "//user who created record + "created DATETIME DEFAULT #%s#, " //date created + "modifier INTEGER DEFAULT 0, "//date modified who cares?? probably no one + "modified DATETIME DEFAULT #%s#, " + "wotype INTEGER DEFAULT 0, " + "woquick YESNO DEFAULT False, " + "woproject INTEGER DEFAULT 0, " + "woonsite YESNO DEFAULT False);" + ,dtDefault.Format(_T("%m/%d/%Y")),dtDefault.Format(_T("%m/%d/%Y")),dtDefault.Format(_T("%m/%d/%Y"))); + + rs->Ex(q); + + + + //new table to hold preventative maintenance items + //in schedule viewer + q.Format("CREATE TABLE pmitems (" + "id COUNTER CONSTRAINT PK_pmitem PRIMARY KEY, " + "pmschedlink INTEGER DEFAULT 0, " + "clientlink INTEGER DEFAULT 0, " + "schedate DATETIME DEFAULT #%s#, " + "schedmeter INTEGER DEFAULT 0, " + "autowo YESNO DEFAULT True, " + "hold YESNO DEFAULT False, " + "schedtech INTEGER DEFAULT 0, " + "link INTEGER DEFAULT 0, "//link to client or unit id number + "isclient YESNO DEFAULT False);",dtDefault.Format(_T("%m/%d/%Y"))); //true = client false=unitbased + + rs->Ex(q); + + + //clear out the pmparts table + rs->Ex("DELETE pmparts.* FROM pmparts;"); + + //set correct report control profile for PM check screen now 8 columns was 7 + rs->Ex("UPDATE users SET users.pmprofile = \"(8,8) 111 70 91 93 67 67 258 0 0 1 2 3 4 5 6 7\";"); + + //Add the lastmaintdate column to the defaults table + //this is used for maintenance to ensure that only one station + //tries to do it at a time: When SC is run, it checks to see if + //this date is older than the current date, if so, it "locks" it by + //updating to today's date, thereby effectively locking out any latecomers + //then runs any required maintenance. + rs->Ex("ALTER TABLE defaults ADD COLUMN lastmaintdate DATETIME;"); + q.Format("UPDATE defaults SET defaults.lastmaintdate = #%s#;",dtDefault.Format(_T("%m/%d/%Y"))); + rs->Ex(q); + + + //Add the woestimate column to the defaults table, this is to + //flag whether to use estimates on dispatch workorders or not. + //this is in response to TCCSI client that needs this and it + //will now be available to all users. This flag is settable under the + //defaults screen, program, not users + rs->Ex("ALTER TABLE defaults ADD COLUMN woestimate YESNO;"); + rs->Ex("UPDATE defaults SET defaults.woestimate = False;"); + + //Customer reference number and contact + //as suggested by Rob MacKay in Australia + rs->Ex("ALTER TABLE wo ADD COLUMN clientrefnum TEXT(50);"); + rs->Ex("ALTER TABLE wo ADD COLUMN clientcontact TEXT(50);"); + + + //Add a first boot field to detect new evaluation versions + //this will be used to show a friendly welcome to message and + //to fixup the dates in the demo data. + + //set to false because if this field isn't in the table already, + //it means user has older version so it just needs to be there + //not actually used + rs->Ex("ALTER TABLE defaults ADD COLUMN firstboot YESNO;"); + rs->Ex("UPDATE defaults SET defaults.firstboot = False;"); + + //refdate is used in an eval to fixup all the dates + //in the evaluation database. + //so that the evaluator sees the demo data as current + rs->Ex("ALTER TABLE defaults ADD COLUMN refdate DATETIME;"); + + + //DROP the pm columns no longer required in the units table + rs->Ex("ALTER TABLE units DROP COLUMN lastpmmetric;"); + rs->Ex("ALTER TABLE units DROP COLUMN lastpmdate;"); + rs->Ex("ALTER TABLE units DROP COLUMN nextpmmetric;"); + rs->Ex("ALTER TABLE units DROP COLUMN nextpmdate;"); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"133\";"); + + nVersion=133; + + + } + + break; + //===================================================== + case 133://changed to 134 for schedule view + { + CString strID,strName,strRights,strHash; + long lData; + GZK k; + + + //Add new right: + //loop through all the group records + rs->Query("SELECT groups.* FROM groups;"); + do{ + rs->FetchField("id",&lData); + rs->FetchField("a",&strName); + rs->FetchField("b",&strRights); + + //decrypt the original rights string + k.GZDecrypt(&strRights,false); + strRights=strRights+"1";//add on the extra right for schedule view + + //re-'crypt' + k.GZEncrypt(&strRights,false); + + //HASH + strHash.Format("%u%s%s",lData,strName,strRights); + k.GZHash(&strHash); + + //save the rights + rs->UpdateField("b",&strRights); + + //save the hash + rs->UpdateField("c",&strHash); + + //save the record + if(!rs->SaveRecord()) + AfxMessageBox("Error trying to save record"); + + + + + + + + }while(rs->MoveForward()); + + + + + + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Parts\", \"parts.rpt\", \".\", False, 32767, 23;"); + + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"134\";"); + + nVersion=134; + + + + } + + break; + //*************************************************************************** + + //===================================================== + case 134://changed to 135 on 12/19/00 + { + + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Search results\", \"srch.rpt\", \".\", False, 32767, 24;"); + + rs->Ex("ALTER TABLE users ADD COLUMN rpttext1 MEMO;"); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"135\";"); + + nVersion=135; + + } + + break; + + //===================================================== + case 135://changed to 136 on Jan 15 2001 + { + bUpdateRanOK=true; + + //USER RECORD CHANGES + rs->Ex("ALTER TABLE users ADD COLUMN defschedstarthour INTEGER;"); + rs->Ex("ALTER TABLE users ADD COLUMN defschedstophour INTEGER;"); + rs->Ex("ALTER TABLE users ALTER defschedstarthour SET DEFAULT '0';"); + rs->Ex("ALTER TABLE users ALTER defschedstophour SET DEFAULT '0';"); + if(!rs->Ex("UPDATE users SET users.defschedstarthour = 0, users.defschedstophour = 0;")) bUpdateRanOK=false; + + //WORKORDER COLUMN CHANGES + rs->Ex("ALTER TABLE wo ADD COLUMN status INTEGER;"); + rs->Ex("ALTER TABLE wo ALTER status SET DEFAULT '0';"); + rs->Ex("UPDATE wo SET wo.status = 0;"); + + rs->Ex("ALTER TABLE wo ADD COLUMN ourref TEXT(80);"); + + rs->Ex("ALTER TABLE wo ADD COLUMN esthours REAL;"); + rs->Ex("ALTER TABLE wo ADD COLUMN estrate INTEGER;"); + + rs->Ex("ALTER TABLE wo ALTER notes TEXT(110)"); + + //STATUS VIEW SCREEN CHANGE + rs->Ex("UPDATE statusviews SET statusviews.viewprofile = \"(17,17) 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16\";"); + + //fix the version number up as long as updates seem ok + if(bUpdateRanOK) + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"136\";"); + + AfxMessageBox("Part of this update modifies the main workorder list view screen.\r\n\r\n" + "You will need to re-order the columns in the main view to your preferences and re-save the views.\r\n\r\n" + "This update affects the column order only, not the underlying restriction settings."); + nVersion=136; + + } + + break; + + //===================================================== + case 136://changed to 137 on Jan 18 2001 + { + + + //NEW FIELDS TO ADD TO STATUS VIEW TABLE + rs->Ex("ALTER TABLE statusviews ADD COLUMN ourref INTEGER;"); + rs->Ex("ALTER TABLE statusviews ADD COLUMN status INTEGER;"); + rs->Ex("ALTER TABLE statusviews ALTER ourref SET DEFAULT '0';"); + rs->Ex("ALTER TABLE statusviews ALTER status SET DEFAULT '0';"); + + rs->Ex("UPDATE statusviews SET statusviews.status = 1;"); + rs->Ex("UPDATE statusviews SET statusviews.ourref = 1;"); + + rs->Ex("ALTER TABLE woparts ADD COLUMN sn TEXT(255);"); + + //client account number + rs->Ex("ALTER TABLE clients ADD COLUMN acctnumber TEXT(40);"); + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"137\";"); + nVersion=137; + } + + break; + case 137://changed to 138 on Jan 29 2001 -bug in tech billing summary + { + + q2="SELECT [users].[last] & \", \" & [users].[first] AS name, Sum(techsubq.hours) AS SumOfhours, Sum(techsubq.nchours) AS SumOfnchours, Sum(techsubq.travhours) AS SumOftravhours, Sum(techsubq.wototal) AS SumOfwototal " + "FROM [SELECT labor.tech, labor.hours, labor.nchours, labor.travhours, (rates.rate*labor.hours)+(travelrates.rate*labor.travhours) AS wototal " + "FROM rates AS travelrates RIGHT JOIN (((labor LEFT JOIN (probs LEFT JOIN wo ON probs.wolink = wo.id) ON labor.link = probs.id) LEFT JOIN rates ON labor.rate = rates.id) LEFT JOIN clients ON wo.client = clients.id) ON travelrates.id = labor.travrate " + "WHERE (((labor.tech)<>-1) AND ((labor.stop) Between #~STRT# And #~END_#) AND ((clients.czone)<>-1) AND ((wo.type)<>-1) AND ((wo.project)<>-1) AND ((wo.client)<>-1))]. AS techsubq INNER JOIN users ON techsubq.tech = users.id " + "GROUP BY techsubq.tech, [users].[last] & \", \" & [users].[first] " + "ORDER BY [users].[last] & \", \" & [users].[first];"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=17));",q2); + + rs->Ex(q); + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"138\";"); + nVersion=138; + + } + + break; + case 138://changed to 139 on Jan 29 2001 -bug in tech billing summary and didn't fix it the first time + { + + q2="SELECT [users].[last] & \", \" & [users].[first] AS name, Sum(techsubq.hours) AS SumOfhours, Sum(techsubq.nchours) AS SumOfnchours, Sum(techsubq.travhours) AS SumOftravhours, Sum(techsubq.wototal) AS SumOfwototal " + "FROM [SELECT labor.tech, labor.hours, labor.nchours, labor.travhours, (rates.rate*labor.hours)+(travelrates.rate*labor.travhours) AS wototal " + "FROM rates AS travelrates RIGHT JOIN (((labor LEFT JOIN (probs LEFT JOIN wo ON probs.wolink = wo.id) ON labor.link = probs.id) LEFT JOIN rates ON labor.rate = rates.id) LEFT JOIN clients ON wo.client = clients.id) ON travelrates.id = labor.travrate " + "WHERE (((labor.tech)~TECH) AND ((labor.stop) Between #~STRT# And #~END_#) AND ((clients.czone)~ZONE) AND ((wo.type)~CAT_) AND ((wo.project)~PROJ) AND ((wo.client)~CUST))]. AS techsubq INNER JOIN users ON techsubq.tech = users.id " + "GROUP BY techsubq.tech, [users].[last] & \", \" & [users].[first] " + "ORDER BY [users].[last] & \", \" & [users].[first];"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=17));",q2); + + rs->Ex(q); + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"139\";"); + nVersion=139; + + } + + break; + case 139://changed to 140 on Feb 15 2001 Added color to status items + { + + rs->Ex("ALTER TABLE probstat ADD COLUMN red INTEGER;"); + rs->Ex("ALTER TABLE probstat ADD COLUMN green INTEGER;"); + rs->Ex("ALTER TABLE probstat ADD COLUMN blue INTEGER;"); + + rs->Ex("ALTER TABLE probstat ALTER red SET DEFAULT '0';"); + rs->Ex("ALTER TABLE probstat ALTER green SET DEFAULT '0';"); + rs->Ex("ALTER TABLE probstat ALTER blue SET DEFAULT '0';"); + + + //set all to black initially + rs->Ex("UPDATE probstat SET probstat.red = 0;"); + rs->Ex("UPDATE probstat SET probstat.green = 0;"); + rs->Ex("UPDATE probstat SET probstat.blue = 0;"); + + + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"140\";"); + nVersion=140; + + + } + + break; + + + case 140://changed to 141 on March 7th 2001 bug in report: Billing summary - hours/parts/3rd party + { + + q2="SELECT IIf(IsNull([clients].[company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]) AS company, Choose([typeUNIONsub].[type],\"Service\",\"3rd party\",\"Parts\") AS chargesfrom, Sum(typeUNIONsub.total) AS total " + "FROM ([SELECT probs.wolink AS link, \"1\" AS type, (rates.rate*labor.hours)+(travelrates.rate*labor.travhours) AS total " + "FROM (rates INNER JOIN (rates AS travelrates INNER JOIN labor ON travelrates.id = labor.travrate) ON rates.id = labor.rate) INNER JOIN (clients INNER JOIN (wo INNER JOIN probs ON wo.id = probs.wolink) ON clients.id = wo.client) ON labor.link = probs.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((clients.czone)~ZONE) AND ((wo.client)~CUST) AND ((wo.type)~CAT_) AND ((wo.project)~PROJ)) " + "UNION ALL (SELECT probs.wolink AS link, \"2\" AS type, subrepair.charge AS total " + "FROM subrepair INNER JOIN (clients INNER JOIN (wo INNER JOIN probs ON wo.id = probs.wolink) ON clients.id = wo.client) ON subrepair.link = probs.id " + "WHERE (((subrepair.charge)<>0) AND ((wo.created) Between #~STRT# And #~END_#) AND ((clients.czone)~ZONE) AND ((wo.client)~CUST) AND ((wo.type)~CAT_) AND ((wo.project)~PROJ)) " + "UNION ALL (SELECT probs.wolink, \"3\" AS type, woparts.quantity*woparts.price AS total " + "FROM woparts INNER JOIN (clients INNER JOIN (wo INNER JOIN probs ON wo.id = probs.wolink) ON clients.id = wo.client) ON woparts.link = probs.id " + "WHERE (((clients.czone)~ZONE) AND ((wo.created) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((wo.type)~CAT_) AND ((wo.project)~PROJ))) " + " )]. AS typeUNIONsub INNER JOIN wo ON typeUNIONsub.link = wo.id) INNER JOIN clients ON wo.client = clients.id " + "GROUP BY IIf(IsNull([clients].[company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]), Choose([typeUNIONsub].[type],\"Service\",\"3rd party\",\"Parts\");"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=4));",q2); + + rs->Ex(q); + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"141\";"); + nVersion=141; + + + } + + break; + + + case 141://changed to 142 on March 26th 2001 various updates + { + + + //Add zone field to users + rs->Ex("ALTER TABLE users ADD COLUMN defzone INTEGER;"); + rs->Ex("ALTER TABLE users ALTER defzone SET DEFAULT '0';"); + + //set all zones to 0 initially + rs->Ex("UPDATE users SET users.defzone = 0;"); + + //Add default wo status fields to defaults + rs->Ex("ALTER TABLE defaults ADD COLUMN wonewstat INTEGER;"); + rs->Ex("ALTER TABLE defaults ADD COLUMN woclosestat INTEGER;"); + rs->Ex("ALTER TABLE defaults ADD COLUMN woreopenstat INTEGER;"); + + //add default schedule screen refresh time period + rs->Ex("ALTER TABLE defaults ADD COLUMN schedrfrshsecs INTEGER;"); + + //set all 0 initially + rs->Ex("UPDATE defaults SET defaults.wonewstat = 0, defaults.woclosestat = 0, defaults.woreopenstat = 0, defaults.schedrfrshsecs = 60;"); + + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"142\";"); + nVersion=142; + + } + + break; + + + + case 142://changed to 143 on April 6th 2001 various updates + { + + //Add default wo status fields to defaults + rs->Ex("ALTER TABLE defaults ADD COLUMN schedwindow INTEGER;"); + + + + //set to 30 day window by default + rs->Ex("UPDATE defaults SET defaults.schedwindow = 30;"); + + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"143\";"); + nVersion=143; + + } + + break; + + case 143://changed to 144 on May 8th 2001 various updates + { + + //Add xfertempl table and set values. This is for import export + + q=("CREATE TABLE xfertempl (" + "name TEXT(80) CONSTRAINT PK_name PRIMARY KEY, " + "import YESNO DEFAULT False, " + "delimiter TEXT(1), " + "fields MEMO, " + "builtin YESNO DEFAULT False, " + "fieldnames YESNO DEFAULT False, " + "path MEMO, " + "[sql] MEMO, " + "[table] TEXT(50));"); + + rs->Ex(q); + + rs->Close(); + + + q2="\"+first\",\"+last\",\"+company\",\"+mailaddress\",\"+streetaddress\",\"+city\",\"+stateprov\",\"+postal\",\"+country\",\"+bizphone\",\"+extension\",\"+fax\",\"+email\",\"+technotes\",\"+alert\",\"+generalnotes\",\"-acctnumber\""; + q.Format("INSERT INTO xfertempl ( name, import, delimiter, fields, builtin, fieldnames, path, [sql], [table] ) " + "SELECT \"Clients\" , False, \",\",'%s', True, True, \"c:\\\", \"SELECT * FROM clients;\",\"clients\";",q2); + rs->Ex(q); + + + q2="\"+partnumber\",\"+description\",\"+avgcost\",\"+retail\",\"+notes\",\"+supplierpart\",\"-upc\""; + q.Format("INSERT INTO xfertempl ( name, import, delimiter, fields, builtin, fieldnames, path, [sql], [table] ) " + "SELECT \"Parts\" , False, \",\",'%s', True, True, \"c:\\\", \"SELECT * FROM parts;\",\"parts\";",q2); + rs->Ex(q); + + + q2="\"+Customer\",\"+Contact\",\"+Phone\",\"+Fax\",\"+Address\",\"+Notes\",\"+Account\""; + q.Format("INSERT INTO xfertempl ( name, import, delimiter, fields, builtin, fieldnames, path, [sql], [table] ) " + "SELECT \"Quick Books - Clients\" , True, \"T\",'%s', True, False, \"c:\\\", \"\",\"QBCLIENTS\";",q2); + rs->Ex(q); + + q2="\"+id\",\"+sn\",\"+id1\",\"+id2\",\"+id3\",\"+company\",\"+first\",\"+last\",\"+receipt\",\"+purchasedate\",\"+model\",\"+manufacturer\",\"+name\",\"+loaner\",\"+lastmeter\""; + q.Format("INSERT INTO xfertempl ( name, import, delimiter, fields, builtin, fieldnames, path, [sql], [table] ) " + "SELECT \"Units\" , False, \",\",'%s', True, True, \"c:\\\", \"SELECT units.id, units.sn, units.id1, units.id2, units.id3, clients.company, clients.first, clients.last, units.receipt, units.purchasedate, unitmodels.model, nonclients.company_person AS manufacturer, unitmodelcats.name, units.loaner, units.lastmeter " + "FROM ((units LEFT JOIN (unitmodels LEFT JOIN unitmodelcats ON unitmodels.category = unitmodelcats.id) ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) LEFT JOIN clients ON units.client = clients.id;\",\"sql\";",q2); + rs->Ex(q); + + + rs->Ex("ALTER TABLE wo ADD COLUMN indexed YESNO;"); + rs->Ex("UPDATE wo SET wo.indexed = False;"); + + //new account number field for non-clients + rs->Ex("ALTER TABLE nonclients ADD COLUMN account TEXT(40);"); + + //new custref column stuff here: + rs->Ex("ALTER TABLE statusviews ADD COLUMN custref INTEGER;"); + rs->Ex("ALTER TABLE statusviews ALTER custref SET DEFAULT '0';"); + rs->Ex("UPDATE statusviews SET statusviews.custref = 1;"); + rs->Ex("UPDATE statusviews SET statusviews.viewprofile = \"(18,18) 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17\";"); + + + //fix of pmprofile bug where it defaults to 7 columns for new users rather + //then the actual value of 8 + //set correct report control profile for PM check screen now 8 columns was 7 + rs->Ex("UPDATE users SET users.pmprofile = \"(8,8) 111 70 91 93 67 67 258 0 0 1 2 3 4 5 6 7\";"); + rs->Ex("ALTER TABLE users ALTER pmprofile SET DEFAULT \"(8,8) 111 70 91 93 67 67 258 0 0 1 2 3 4 5 6 7\";"); + + + + + //Add new parts used on workorder reports to rptsmaster + //DETAILED + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Parts on workorders\", \"partwo.rpt\", \"mgr\", True, 397, 25;"); + //SUMMARY + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Parts on workorder - summarized\", \"prtwosum.rpt\", \"mgr\", True, 397, 26;"); + + + //DETAILED + q2="SELECT IIf(IsNull([company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]) AS CLIENT, wo.id AS WORKORDER, #~STRT# AS STARTDATE, #~END_# AS ENDDATE, wo.starttime AS SCHEDULED, IIf(IsNull([partnumber]),\"misc.\",[partnumber]) AS PART, IIf(IsNull([partnumber]),[misc],[description]) AS [DESC], woparts.quantity, woparts.sn, users.last AS TECH, wo.closed, woparts.price AS WOPRICE, parts.retail, clients.id AS CLIENTID, wo.created AS WOCREATED, wo.project, wo.type " + "FROM (((woparts RIGHT JOIN (probs RIGHT JOIN wo ON probs.wolink = wo.id) ON woparts.link = probs.id) LEFT JOIN parts ON woparts.partnum = parts.id) LEFT JOIN users ON wo.assigntech = users.id) LEFT JOIN clients ON wo.client = clients.id " + "WHERE (((clients.id)~CUST) AND ((wo.created) Between #~STRT# And #~END_#) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_) AND ((woparts.id) Is Not Null)) " + "ORDER BY IIf(IsNull([partnumber]),\"misc.\",[partnumber]);"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=25));",q2); + rs->Ex(q); + + + //SUMMARY + q2="SELECT IIf(IsNull([partnumber]),\"misc.\",[partnumber]) AS PART, IIf(IsNull([partnumber]),[misc],[description]) AS [DESC], #~STRT# AS STARTDATE, #~END_# AS ENDDATE, Sum(woparts.quantity) AS [TOTAL USED] " + "FROM (((woparts RIGHT JOIN (probs RIGHT JOIN wo ON probs.wolink = wo.id) ON woparts.link = probs.id) LEFT JOIN parts ON woparts.partnum = parts.id) LEFT JOIN users ON wo.assigntech = users.id) LEFT JOIN clients ON wo.client = clients.id " + "WHERE (((clients.id)~CUST) AND ((wo.created) Between #~STRT# And #~END_#) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_) AND ((woparts.id) Is Not Null)) " + "GROUP BY IIf(IsNull([partnumber]),\"misc.\",[partnumber]), IIf(IsNull([partnumber]),[misc],[description]) " + "ORDER BY IIf(IsNull([partnumber]),\"misc.\",[partnumber]);"; + + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=26));",q2); + rs->Ex(q); + + + //Add SUBREPAIR REPORTS AND QUERIES + //OUTSTANDING + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Subrepair status - outstanding\", \"subrepair.rpt\", \"mgr\", True, 401, 27;"); + //ALL + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Subrepair status - all\", \"subrepairall.rpt\", \"mgr\", True, 401, 28;"); + + + //OUTSTANDING + q2="SELECT IIf(IsNull([company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]) AS CLIENT, wo.id AS WORKORDER, #~STRT# AS STARTDATE, #~END_# AS ENDDATE, nonclients.company_person AS SENTTO, nonclients_1.company_person AS SENTVIA, subrepair.sent AS DATESENT, subrepair.eta AS RECEIVEETA, subrepair.received AS DATERECEIVED, [nonclients_2].[company_person] & \" \" & [unitmodels].[model] & \" \" & [unitmodels].[description] & \" sn: \" & [units].[sn] AS ITEM, units.sn, nonclients_2.company_person AS MANUFACTURER, unitmodels.model, unitmodels.description, subrepair.waybill, subrepair.rma, subrepair.isback " + "FROM nonclients AS nonclients_2 RIGHT JOIN (((units RIGHT JOIN ((clients RIGHT JOIN (subrepair RIGHT JOIN (probs RIGHT JOIN wo ON probs.wolink = wo.id) ON subrepair.link = probs.id) ON clients.id = wo.client) LEFT JOIN nonclients ON subrepair.where = nonclients.id) ON units.id = probs.unit) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients AS nonclients_1 ON subrepair.sentvia = nonclients_1.id) ON nonclients_2.id = unitmodels.manufacturer " + "WHERE (((subrepair.sent) Between #~STRT# And #~END_#) AND ((subrepair.id) Is Not Null) AND ((subrepair.isback)=False) AND ((wo.client)~CUST) AND ((units.id)~UNIT)) " + "ORDER BY subrepair.sent;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=27));",q2); + rs->Ex(q); + + + //ALL + q2="SELECT IIf(IsNull([company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]) AS CLIENT, wo.id AS WORKORDER, #~STRT# AS STARTDATE, #~END_# AS ENDDATE, nonclients.company_person AS SENTTO, nonclients_1.company_person AS SENTVIA, subrepair.sent AS DATESENT, subrepair.eta AS RECEIVEETA, subrepair.received AS DATERECEIVED, [nonclients_2].[company_person] & \" \" & [unitmodels].[model] & \" \" & [unitmodels].[description] & \" sn: \" & [units].[sn] AS ITEM, units.sn, nonclients_2.company_person AS MANUFACTURER, unitmodels.model, unitmodels.description, subrepair.waybill, subrepair.rma, subrepair.isback " + "FROM nonclients AS nonclients_2 RIGHT JOIN (((units RIGHT JOIN ((clients RIGHT JOIN (subrepair RIGHT JOIN (probs RIGHT JOIN wo ON probs.wolink = wo.id) ON subrepair.link = probs.id) ON clients.id = wo.client) LEFT JOIN nonclients ON subrepair.where = nonclients.id) ON units.id = probs.unit) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients AS nonclients_1 ON subrepair.sentvia = nonclients_1.id) ON nonclients_2.id = unitmodels.manufacturer " + "WHERE (((subrepair.sent) Between #~STRT# And #~END_#) AND ((subrepair.id) Is Not Null) AND ((wo.client)~CUST) AND ((units.id)~UNIT)) " + "ORDER BY subrepair.sent;"; + + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=28));",q2); + rs->Ex(q); + + + + + //WARNING MESSAGE ABOUT COLUMN FORMATS IN MAIN WORKORDER VIEW BEING MESSED UP + AfxMessageBox("Part of this update modifies the main workorder list view screen to add the \r\nCUSTOMER REFERENCE NUMBER column.\r\n\r\n" + "You will need to re-order the columns in the main view to your preferences and re-save the views.\r\n\r\n" + "This update affects the column order only, not the underlying restriction settings."); + + + + + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"144\";"); + nVersion=144; + + + } + + break; + case 144://changed to 145 on May 23rd 2001 various updates + { + + + + + //Add securenet's fields to wo header + rs->Ex("ALTER TABLE wo ADD COLUMN prob_reported TEXT(255);"); + rs->Ex("ALTER TABLE wo ADD COLUMN prob_found TEXT(255);"); + rs->Ex("ALTER TABLE wo ADD COLUMN action_taken TEXT(255);"); + + //Add corresponding entry to defaults to flag whether to show + //those new fields or not + rs->Ex("ALTER TABLE defaults ADD COLUMN showprobaction YESNO;"); + rs->Close(); + + //Default to no for everyone for now + rs->Ex("UPDATE defaults SET showprobaction = False;"); + + + + + + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"145\";"); + nVersion=145; + + + } + + break; + case 145://changed to 146 on May 27th 2001 various updates + { + + + //Add weeks and days fields to pm header + rs->Ex("ALTER TABLE pmhead ADD COLUMN rptweeks INTEGER;"); + rs->Ex("ALTER TABLE pmhead ADD COLUMN rptdays INTEGER;"); + + rs->Ex("ALTER TABLE pmhead ALTER rptweeks SET DEFAULT '0';"); + rs->Ex("ALTER TABLE pmhead ALTER rptdays SET DEFAULT '0';"); + + rs->Close(); + + //set all to 0 initially + rs->Ex("UPDATE pmhead SET rptweeks = 0;"); + rs->Ex("UPDATE pmhead SET rptdays = 0;"); + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"146\";"); + nVersion=146; + + + } + + break; + + case 146://changed to 147 on june 21th 2001 various updates + { + + + + //set all blank company fields to last, first names + rs->QueryReadOnly("SELECT clients.last, clients.first, clients.bizphone FROM clients " + "WHERE (((clients.first) In (SELECT [first] FROM [clients] As Tmp GROUP BY [first],[last] HAVING Count(*)>1 And [last] = [clients].[last])) AND ((clients.company) Is Null)) " + "ORDER BY clients.last;"); + if(rs->IsEmpty()) + { + rs->Ex("UPDATE clients SET clients.company = [last] & \", \" & [first] " + "WHERE (((clients.company) Is Null));"); + + rs->Close(); + + } + else + { + + AfxMessageBox( + "Warning: Due to a change in the clients table in the database\r\n" + "this update needs to move the contact first and last names to the former \r\n" + "\"Company\" field which is now the single client field.\r\n\r\n" + + "Your help is required to correct a problem before the update can finish:\r\n" + "You have duplicate non-company clients and need to change them in the clients screen.\r\n\r\n" + + "When this update completes and returns you to AyaNova, \r\n" + "go directly to the client screen (Options->Edit->Clients) where you will be given\r\n" + "more instructions on fixing the duplicate client names."); + + + //m_pApp->ShowStuff(strData); + //stop from doing anything further + buptodate=true; + break; + + } + + //---------------------------------------------------------------------------- + //Performance boost - new indexes + + rs->Ex("CREATE INDEX idxanytime ON wo (anytime);"); + rs->Ex("CREATE INDEX idxquick ON wo (quick);"); + rs->Ex("CREATE INDEX idxassigntech ON wo (assigntech);"); + rs->Ex("CREATE INDEX idxstarttime ON wo (starttime);"); + AfxMessageBox("This update contains speed improvements to the database.\r\n\r\n" + "This will not take effect until *after* you COMPACT the database after updating.\r\n" + "The COMPACT option is on the database utilities menu.\r\n" + "(Re-indexing is not necessary, only COMPACT)"); + + //----------------------------------------------------------------------------- + + + //---------------------------------------------------------------------------- + //Add new schedule groups tables + + q.Format( + "CREATE TABLE schdgrps (" + "id COUNTER CONSTRAINT PK_pmitem PRIMARY KEY, " + "name TEXT(80));"); + rs->Ex(q); + + q.Format("CREATE TABLE schdets (" + "grpid INTEGER DEFAULT 0, " + "techid INTEGER DEFAULT 0);"); + rs->Ex(q); + + rs->Close(); + + //group get's indexed because it's the searched and linked field + rs->Ex("CREATE INDEX idxgrpid ON schdets (grpid);"); + //techid's don't get indexed because they are simply retrieved + + + //----------------------------------------------------------------------------- + + + //create subunits table + q.Format("CREATE TABLE subunits (" + "masterunitid INTEGER DEFAULT 0, " + "unitid INTEGER DEFAULT 0, " + "creator INTEGER DEFAULT 0, "//user who created record + "created DATETIME, " //date created + "modifier INTEGER DEFAULT 0, "//date modified who cares?? probably no one + "modified DATETIME);"); + rs->Ex(q); + + rs->Ex("CREATE INDEX idxmstrunit " + "ON subunits (masterunitid);"); + + //----------------------------------------------------------------------------- + //add the master/sub unit report to reports screen + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Master and sub units (kits)\", \"unitkits.rpt\", \"mgr\", True, 3217, 29;"); + + q2="SELECT units.sn AS mastersn, units.id, units.client, unitmodels.manufacturer, units.model, unitmodels.description AS mastermodel, nonclients.company_person AS mastermake, unitmodelcats.name AS mastertype, units_1.sn AS subsn, unitmodels_1.description AS submodel, nonclients_1.company_person AS submake, unitmodelcats_1.name AS subtype " + "FROM ((((subunits RIGHT JOIN (((units LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) LEFT JOIN unitmodelcats ON unitmodels.category = unitmodelcats.id) ON subunits.masterunitid = units.id) LEFT JOIN units AS units_1 ON subunits.unitid = units_1.id) LEFT JOIN unitmodels AS unitmodels_1 ON units_1.model = unitmodels_1.id) LEFT JOIN unitmodelcats AS unitmodelcats_1 ON unitmodels_1.category = unitmodelcats_1.id) LEFT JOIN nonclients AS nonclients_1 ON unitmodels_1.manufacturer = nonclients_1.id " + "WHERE (((units.id)~UNIT) AND ((units.client)~CUST) AND ((unitmodels.manufacturer)~MANU) AND ((units.model)~MODL)) " + "ORDER BY units.sn, units.id;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=29));",q2); + + rs->Ex(q); + //----------------------------------------------------------------------------- + + //----------------------------------------------------------------------------- + //add the rate billing summary report to reports screen + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Billing summary by rate\", \"ratesums.rpt\", \"mgr\", True, 463, 30;"); + + q2="SELECT rates.name, Sum(labor.hours) AS SumOfhours, Sum(labor.nchours) AS SumOfnchours, Sum(labor.travhours) AS SumOftravhours, rates.rate, rates.travelrate " + "FROM ((wo RIGHT JOIN probs ON wo.id = probs.wolink) RIGHT JOIN labor ON probs.id = labor.link) LEFT JOIN rates ON labor.rate = rates.id " + "WHERE (((labor.start) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((labor.tech)~TECH) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_) AND ((rates.id)~RATE) AND ((rates.active)=True)) " + "GROUP BY rates.name, rates.rate, rates.travelrate, rates.id UNION (SELECT rates.name, Sum(labor.hours) AS SumOfhours, Sum(labor.nchours) AS SumOfnchours, Sum(labor.travhours) AS SumOftravhours, rates.rate, rates.travelrate " + "FROM ((wo RIGHT JOIN probs ON wo.id = probs.wolink) RIGHT JOIN labor ON probs.id = labor.link) LEFT JOIN rates ON labor.travrate = rates.id " + "WHERE (((labor.start) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((labor.tech)~TECH) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_) AND ((rates.id)~RATE) AND ((rates.active)=True)) " + "GROUP BY rates.name, rates.rate, rates.travelrate, rates.id) " + "ORDER BY rates.name;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=30));",q2); + + rs->Ex(q); + + + + + + + //----------------------------------------------------------------------------- + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"147\";"); + + nVersion=147; + //----------------------------------------------------------------------------- + + + + } + + break; + + case 147://changed to 148 on july 6th 2001 for version 1.7.1.7 + { + + //---------------------------------------------------------------------------- + //increase size of srchdict.word from 30 characters to 50 + rs->Ex("ALTER TABLE srchdict ALTER COLUMN word TEXT(50);"); + + //increase size of srch.client from 50 characters to 80 + rs->Ex("ALTER TABLE srch ALTER COLUMN client TEXT(80);"); + + //----------------------------------------------------------------------------- + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"148\";"); + + //----------------------------------------------------------------------------- + nVersion=148; + + } + + break; + case 148: + { + + //---------------------------------------------------------------------------- + //Add a program version number field to the database + rs->Ex("ALTER TABLE defaults ADD COLUMN min_exe TEXT(25);"); + + + + //----------------------------------------------------------- + //Add schedule markers table and indices + + rs->Ex( "CREATE TABLE schedmarkers (" + "id COUNTER CONSTRAINT PK_schedmrk PRIMARY KEY, " + "link INTEGER DEFAULT 0," + "startdate DATETIME, " + "enddate DATETIME, " + "notes TEXT(15), " + "red INTEGER DEFAULT 128, " + "green INTEGER DEFAULT 128, " + "blue INTEGER DEFAULT 128" + ");"); + rs->Ex("CREATE INDEX idxsmlink " + "ON schedmarkers (link);"); + + rs->Ex("CREATE INDEX idxsmstdate " + "ON schedmarkers (startdate);"); + + rs->Ex("CREATE INDEX idxsmendate " + "ON schedmarkers (enddate);"); + //---------------------------------------------------------- + + + //---------------------------------------------- + rs->Ex("ALTER TABLE wo ADD COLUMN starttime2 DATETIME;"); + rs->Ex("ALTER TABLE wo ADD COLUMN stoptime2 DATETIME;"); + rs->Ex("ALTER TABLE wo ADD COLUMN assigntech2 INTEGER;"); + + rs->Ex("ALTER TABLE wo ADD COLUMN starttime3 DATETIME;"); + rs->Ex("ALTER TABLE wo ADD COLUMN stoptime3 DATETIME;"); + rs->Ex("ALTER TABLE wo ADD COLUMN assigntech3 INTEGER;"); + + rs->Ex("ALTER TABLE wo ADD COLUMN starttime4 DATETIME;"); + rs->Ex("ALTER TABLE wo ADD COLUMN stoptime4 DATETIME;"); + rs->Ex("ALTER TABLE wo ADD COLUMN assigntech4 INTEGER;"); + + rs->Ex("ALTER TABLE wo ALTER assigntech SET DEFAULT '-1';"); + rs->Ex("ALTER TABLE wo ALTER assigntech2 SET DEFAULT '-1';"); + rs->Ex("ALTER TABLE wo ALTER assigntech3 SET DEFAULT '-1';"); + rs->Ex("ALTER TABLE wo ALTER assigntech4 SET DEFAULT '-1';"); + //---------------------------------------------- + rs->Ex("CREATE INDEX idxassigntech2 ON wo (assigntech2);"); + rs->Ex("CREATE INDEX idxstarttime2 ON wo (starttime2);"); + + rs->Ex("CREATE INDEX idxassigntech3 ON wo (assigntech3);"); + rs->Ex("CREATE INDEX idxstarttime3 ON wo (starttime3);"); + + rs->Ex("CREATE INDEX idxassigntech4 ON wo (assigntech4);"); + rs->Ex("CREATE INDEX idxstarttime4 ON wo (starttime4);"); + + //set extra techs to -1 meaning not assigned yet + rs->Ex("UPDATE wo SET wo.assigntech2 = -1, wo.assigntech3 = -1, wo.assigntech4 = -1;"); + + //set non-scheduled workorders first tech to non assigned -1 + rs->Ex("UPDATE wo SET wo.assigntech = -1 WHERE (((wo.anytime)=True));"); + + + //----------------------------------------------------------------------------- + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"149\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.7.2.0\";"); + + //----------------------------------------------------------------------------- + + nVersion=149; + + } + + break; + + case 149: + { + //Last modified 07/30/2001 - added category/type column + //COLUMNMOD + //new CATEGORY column stuff here: + rs->Ex("ALTER TABLE statusviews ADD COLUMN category INTEGER;"); + rs->Ex("ALTER TABLE statusviews ALTER category SET DEFAULT '0';"); + rs->Ex("UPDATE statusviews SET statusviews.category = -1;"); + + //new project column here + rs->Ex("ALTER TABLE statusviews ADD COLUMN project INTEGER;"); + rs->Ex("ALTER TABLE statusviews ALTER project SET DEFAULT '0';"); + rs->Ex("UPDATE statusviews SET statusviews.category = -1;"); + + + //update all views to handle extra columns + rs->Ex("UPDATE statusviews SET statusviews.viewprofile = \"(20,20) 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\";"); + + + + //fix the version number up as long as updates seem ok + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"150\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.7.2.0\";"); + + //WARNING MESSAGE ABOUT COLUMN FORMATS IN MAIN WORKORDER VIEW BEING MESSED UP + AfxMessageBox("Part of this update modifies the main workorder list view screen to add the \r\n" + "WORKORDER CATEGORY and PROJECT columns.\r\n\r\n" + "This change will affect *all* the views you have configured in AyaNova.\r\n" + "You will need to re-order the columns in the main view to your preferences and re-save each view separately.\r\n\r\n" + "This update affects the column order only, not the underlying restriction settings.\r\n" + "\r\nDo not attempt to edit your views until after you have restarted AyaNova when this update completes."); + + //----------------------------------------------------------------------------- + + nVersion=150; + + + } + + break; + + case 150: + { + //ADD AYANOTIFY TABLES + //--------------------------------------- + rs->Ex( + "CREATE TABLE notify_cfg (freq_mm INTEGER, [dow] INTEGER, stop_hour DATETIME, start_hour DATETIME, " + "[attempts] INTEGER, [mapi] YESNO, keeplogdays INTEGER, [verboseLog] YESNO, login_name TEXT(50), " + "login_pw TEXT(50), [connection] TEXT(120), from_address TEXT(80), [server] TEXT(120), " + "next_xmit DATETIME, [dialup] YESNO, last_xmit DATETIME, dayspast INTEGER , " + "daysfuture INTEGER);"); + + rs->Ex("ALTER TABLE notify_cfg ALTER freq_mm SET DEFAULT '0';"); + rs->Ex("ALTER TABLE notify_cfg ALTER dow SET DEFAULT '0';"); + rs->Ex("ALTER TABLE notify_cfg ALTER attempts SET DEFAULT '0';"); + rs->Ex("ALTER TABLE notify_cfg ALTER keeplogdays SET DEFAULT '30';"); + rs->Ex("ALTER TABLE notify_cfg ALTER dayspast SET DEFAULT '0';"); + rs->Ex("ALTER TABLE notify_cfg ALTER daysfuture SET DEFAULT '14';"); + + + + + + + + rs->Ex( + "INSERT INTO notify_cfg ( freq_mm, dow, stop_hour, start_hour, attempts, mapi, " + "keeplogdays, verboseLog, login_name, login_pw, [connection], from_address, server, " + "next_xmit, dialup, last_xmit, dayspast, daysfuture ) " + "SELECT 60 , 0, #12/30/1899 19:0:0#, #12/30/1899 7:0:0#, 0, False, 30, False, " + "\"login\", \"password\", \"My ISP\", \"from_me@my_isp.com\", \"smtp.mail.my_isp.com\", " + "#1/1/2000#, False, #1/1/2000#, 1, 14;"); + + + //log table + rs->Ex( "CREATE TABLE notify_log (" + "id INTEGER DEFAULT 0, " + "nwhen DATETIME, " + "nwho INTEGER DEFAULT 0, " + "nwhat TEXT(255), " + "ntype INTEGER DEFAULT 0, " + "nresult TEXT(255) " + ");"); + + //temp table for building notifications + rs->Ex( "CREATE TABLE notify_temp (" + "woid INTEGER DEFAULT 0, " + "scheddate DATETIME, " + "schedstop DATETIME, " + "schedtech INTEGER DEFAULT 0 " + ");"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"151\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.7.2.0\";"); + nVersion=151; + + + } + + break; + + + case 151: + { + + //--------------------------------------- + //add the WORKORDERS report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Workorders\", \"allwo.rpt\", \"mgr\", True, 397, 31;"); + + q2="SELECT ~CRITERIA AS CRITERIA, wo.id AS wonumber, \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) & \"Unit: \" & [nonclients].[company_person] & \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") AS probheader, \"test\" AS compname, wom.probnum, wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, wom.PROBBRIEF, wom.item, wom.linetotal, wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created AS wodate, wo.invoice, wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, clients.bizphone, clients.extension, clients.fax, clients.email, clients.company AS clientname, wom.details, wom.START, wom.STOP,wom.REGHOURS, wom.TRAVHOURS, wom.NCHOURS, projects.name AS PROJNAME, projects.notes AS PROJNOTES, wo.client, wo.project, wo.type, wotypes.category AS CATEGORY " + "FROM ((((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT \"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink AS wonum, \"Service: \" & users.first & \" \" & users.last & \" - \" & IIf(labor.hours>0,labor.hours & \" @ \" & Format(rates.rate,\"Currency\") & \" (pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" (\" & labor.nchours & \" no charge)\",\"\") & IIf(labor.travhours>0,\", \" & labor.travhours & \" travel @ \" & Format(travelrates.rate,\"Currency\") & IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" & travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) AS linetotal, labor.details , labor.start AS START, labor.stop AS STOP, labor.hours AS REGHOURS, labor.travhours AS TRAVHOURS, labor.nchours as NCHOURS FROM users INNER JOIN (rates AS travelrates INNER JOIN (rates INNER JOIN (labor INNER JOIN probs ON labor.link = probs.id) ON rates.id = labor.rate) ON travelrates.id = labor.travrate) ON users.id = labor.tech WHERE (((probs.wolink)<>0)) " + " UNION ALL (SELECT \"2\" AS ctype, \"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Parts: \" & IIf(woparts.misc= \"\",parts.partnumber & \" \" & parts.description & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") & \" ea.(sn:\" & woparts.sn & \")\",woparts.misc & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" & woparts.sn & \")\") AS item, woparts.quantity*woparts.price AS linetotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM (probs INNER JOIN woparts ON probs.id = woparts.link) " + " LEFT JOIN parts ON woparts.partnum = parts.id WHERE (((probs.wolink)<>0)) " + "UNION ALL (SELECT \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Third party service: \" AS item, subrepair.charge AS linettotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM probs INNER JOIN subrepair ON probs.id = subrepair.link WHERE (((probs.wolink)<>0) AND ((subrepair.charge)<>0))))]. AS wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN clients AS headoffices ON clients.headoffice = headoffices.id) ON probs.id = wom.probnum) ON units.id = probs.unit) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) LEFT JOIN projects ON wo.project = projects.id ) LEFT JOIN wotypes ON wo.type = wotypes.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_)) " + "ORDER BY wo.id;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=31));",q2); + rs->Ex(q); + //------------------------------------------------ + //--------------------------------------- + //add the WORKORDERS BRIEF report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Workorders - brief\", \"allwobrief.rpt\", \"mgr\", True, 397, 32;"); + + q2="SELECT ~CRITERIA AS CRITERIA, wo.id AS wonumber, \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) & \"Unit: \" & [nonclients].[company_person] & \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") AS probheader, \"test\" AS compname, wom.probnum, wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, wom.PROBBRIEF, wom.item, wom.linetotal, wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created AS wodate, wo.invoice, wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, clients.bizphone, clients.extension, clients.fax, clients.email, clients.company AS clientname, wom.details, wom.START, wom.STOP,wom.REGHOURS, wom.TRAVHOURS, wom.NCHOURS, projects.name AS PROJNAME, projects.notes AS PROJNOTES, wo.client, wo.project, wo.type, wotypes.category AS CATEGORY " + "FROM ((((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT \"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink AS wonum, \"Service: \" & users.first & \" \" & users.last & \" - \" & IIf(labor.hours>0,labor.hours & \" @ \" & Format(rates.rate,\"Currency\") & \" (pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" (\" & labor.nchours & \" no charge)\",\"\") & IIf(labor.travhours>0,\", \" & labor.travhours & \" travel @ \" & Format(travelrates.rate,\"Currency\") & IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" & travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) AS linetotal, labor.details , labor.start AS START, labor.stop AS STOP, labor.hours AS REGHOURS, labor.travhours AS TRAVHOURS, labor.nchours as NCHOURS FROM users INNER JOIN (rates AS travelrates INNER JOIN (rates INNER JOIN (labor INNER JOIN probs ON labor.link = probs.id) ON rates.id = labor.rate) ON travelrates.id = labor.travrate) ON users.id = labor.tech WHERE (((probs.wolink)<>0)) " + "UNION ALL (SELECT \"2\" AS ctype, \"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Parts: \" & IIf(woparts.misc= \"\",parts.partnumber & \" \" & parts.description & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") & \" ea.(sn:\" & woparts.sn & \")\",woparts.misc & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" & woparts.sn & \")\") AS item, woparts.quantity*woparts.price AS linetotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM (probs INNER JOIN woparts ON probs.id = woparts.link) " + "LEFT JOIN parts ON woparts.partnum = parts.id WHERE (((probs.wolink)<>0)) " + "UNION ALL (SELECT \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Third party service: \" AS item, subrepair.charge AS linettotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM probs INNER JOIN subrepair ON probs.id = subrepair.link WHERE (((probs.wolink)<>0) AND ((subrepair.charge)<>0))))]. AS wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN clients AS headoffices ON clients.headoffice = headoffices.id) ON probs.id = wom.probnum) ON units.id = probs.unit) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) LEFT JOIN projects ON wo.project = projects.id ) LEFT JOIN wotypes ON wo.type = wotypes.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_)) " + "ORDER BY wo.id;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=32));",q2); + rs->Ex(q); + //------------------------------------------------ + + //--------------------------------------- + //add the Units by P.M. report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Units by P.M.\", \"pmunits.rpt\", \"mgr\", True, 2193, 33;"); + + q2="SELECT ~CRITERIA AS CRITERIA, pmhead.id, nonclients.company_person AS MAKE, unitmodels.model, units.sn, unitmodels.description AS UNITDESC, units.id1, units.id2, units.id3, clients.company, nonclients.phone, pmhead.description, pmhead.notes, pmhead.nextsrvdate, pmhead.nextsrvmeter, units.lastmeter, pmhead.woconvert, pmhead.repeatevery AS rptmonths_count, pmhead.rptweeks, pmhead.rptdays, units.purchasedate, pmhead.ageyears, pmhead.agemonths, users.initials, users.first, users.last, pmhead.isclient " + "FROM ((pmhead LEFT JOIN ((units LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) ON pmhead.link = units.id) LEFT JOIN clients ON units.client = clients.id) LEFT JOIN users ON pmhead.tech = users.id " + "WHERE (((pmhead.isclient)=False) AND ((units.client)~CUST) AND ((units.id)~UNIT) AND ((units.model)~MODL)) " + "ORDER BY nonclients.company_person, unitmodels.model, units.sn, clients.company;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=33));",q2); + rs->Ex(q); + //------------------------------------------------ + + //--------------------------------------- + //add the P.M. by Units report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"P.M. by Units\", \"unitspm.rpt\", \"mgr\", True, 2193, 34;"); + + q2="SELECT ~CRITERIA AS CRITERIA, pmhead.id, nonclients.company_person AS MAKE, unitmodels.model, units.sn, unitmodels.description AS UNITDESC, units.id1, units.id2, units.id3, clients.company, nonclients.phone, pmhead.description, pmhead.notes, pmhead.nextsrvdate, pmhead.nextsrvmeter, units.lastmeter, pmhead.woconvert, pmhead.repeatevery AS rptmonths_count, pmhead.rptweeks, pmhead.rptdays, units.purchasedate, pmhead.ageyears, pmhead.agemonths, users.initials, users.first, users.last, pmhead.isclient " + "FROM ((pmhead LEFT JOIN ((units LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) ON pmhead.link = units.id) LEFT JOIN clients ON units.client = clients.id) LEFT JOIN users ON pmhead.tech = users.id " + "WHERE (((pmhead.isclient)=False) AND ((units.client)~CUST) AND ((units.id)~UNIT) AND ((units.model)~MODL)) " + "ORDER BY nonclients.company_person, unitmodels.model, units.sn, clients.company;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=34));",q2); + rs->Ex(q); + //------------------------------------------------ + + //--------------------------------------- + //add the P.M. by Client report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"P.M. by Client\", \"clientpm.rpt\", \"mgr\", True, 385, 35;"); + + q2="SELECT ~CRITERIA AS CRITERIA, clients.company, pmhead.description, pmhead.notes, pmhead.nextsrvdate, pmhead.link AS CLIENTID, pmhead.woconvert, pmhead.repeatevery AS rptmonths_count, pmhead.rptweeks, pmhead.rptdays, pmhead.ageyears, pmhead.agemonths, users.initials, users.first AS TECH_FIRST, users.last AS TECH_LAST " + "FROM clients RIGHT JOIN (pmhead LEFT JOIN users ON pmhead.tech = users.id) ON clients.id = pmhead.link " + "WHERE (((pmhead.nextsrvdate) Between #~STRT# And #~END_#) AND ((pmhead.link)~CUST) AND ((pmhead.isclient)=True)) " + "ORDER BY clients.company;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=35));",q2); + rs->Ex(q); + //------------------------------------------------ + + + //--------------------------------------- + //add the Workorders not invoiced report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Workorders not invoiced\", \"notbilled.rpt\", \"mgr\", True, 385, 36;"); + + q2=strData="SELECT ~CRITERIA AS CRITERIA, wo.id, clients.company, wo.modified, wo.ourref, wo.clientrefnum, wo.clientcontact, wo.closed, wo.invoice, wo.notes " + "FROM probstat RIGHT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON probstat.id = wo.status " + "WHERE (((wo.modified) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((wo.invoice) Is Null)) " + "ORDER BY wo.modified DESC;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=36));",q2); + rs->Ex(q); + //------------------------------------------------ + + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"152\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.7.2.0\";"); + nVersion=152; + + + } + + break; + + + + case 152: //update for v1720 added extra security rights items + { + CString strID,strName,strRights,strHash; + long lData; + GZK k; + + + //Add new right: + //loop through all the group records + rs->Query("SELECT groups.* FROM groups;"); + do{ + rs->FetchField("id",&lData); + rs->FetchField("a",&strName); + rs->FetchField("b",&strRights); + + //decrypt the original rights string + k.GZDecrypt(&strRights,false); + strRights=strRights+"111";//add on the extra right for schedule view + + //re-'crypt' + k.GZEncrypt(&strRights,false); + + //HASH + strHash.Format("%u%s%s",lData,strName,strRights); + k.GZHash(&strHash); + + //save the rights + rs->UpdateField("b",&strRights); + + //save the hash + rs->UpdateField("c",&strHash); + + //save the record + if(!rs->SaveRecord()) + AfxMessageBox("Error trying to save rights record"); + + + + + + + + }while(rs->MoveForward()); + + + + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"153\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.7.2.0\";"); + nVersion=153; + + + } + + break; + + case 153: //update for v1720 modified client equipment report query + //and added eval field for web server + { + + //"KJB3BoICxnQM9KvUO+1mzQ==" Evaluate 8 chars + rs->Ex("ALTER TABLE defaults ADD COLUMN mango TEXT(80);"); + rs->Ex("UPDATE defaults SET defaults.mango = \"KJB3BoICxnQM9KvUO+1mzQ\";"); + + /* + How web server mango column works: + if = Evaluate then means ready to be evaluated + first time webserver runs sets mango to expiry date + when expires sets column to Expired and web server stops working + */ + + + //ADD EMAIL NOTIFICATION FIELDS TO USERS TABLE (oops forgot to do it earlier) + rs->Ex("ALTER TABLE users ADD COLUMN email TEXT(120);"); + rs->Ex("ALTER TABLE users ADD COLUMN emailnotify YESNO;"); + rs->Ex("ALTER TABLE users ALTER emailnotify SET DEFAULT '0';"); + rs->Ex("UPDATE users SET users.emailnotify = False;"); + + + + //UPDATE CLIENT EQUIPMENT REPORT QUERY + + q2="SELECT clients.id, IIf(IsNull([clients].[company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]) AS client, [clients].[first] & \" \" & [clients].[last] AS clientcontact, clients.bizphone, [manufacturers].[company_person] & \" \" & [unitmodels].[model] AS item, units.sn, IIf([units].[boughthere],\"us\",[nonclients].[company_person]) AS vendor, units.purchasedate, units.receipt AS invoice, units.notes, units.description " + "FROM (((units LEFT JOIN clients ON units.client = clients.id) LEFT JOIN nonclients ON units.purchasedfrom = nonclients.id) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients AS manufacturers ON unitmodels.manufacturer = manufacturers.id " + "WHERE (((clients.id)~CUST) AND ((units.purchasedate) Between #~STRT# And #~END_#) AND ((units.loaner)=False)) " + "ORDER BY IIf(IsNull([clients].[company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]);"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=20));",q2); + rs->Ex(q); + + //UPDATE UNIT HISTORY REPORT QUERY + + q2="SELECT ~USERNAME AS zCurrentUser, probs.id, probs.wolink AS WORKORDERID, probs.brief AS PROBBRIEF, probs.notes " + "AS PROBNOTES, Format([start],\"Short Date\") AS servdate, labor.details, clients.company AS clientcompany, " + "units.sn, unitmodels.model, users.initials, probs.meter, ztotalparts.totalparts, ztotallabor.totallabor FROM " + "[SELECT Sum((labor.hours*rates.rate)+(labor.travhours*travrates.rate)) AS totallabor, probs.id FROM probs INNER " + "JOIN (rates INNER JOIN (rates AS travrates INNER JOIN labor ON travrates.id = labor.rate) ON rates.id = labor.rate) " + "ON probs.id = labor.link GROUP BY probs.id]. AS ztotallabor RIGHT JOIN ([SELECT IIf(IsNull(Sum(woparts.quantity*woparts.price)), 0,Sum(woparts.quantity*woparts.price)) AS totalparts, " + "probs.id FROM probs LEFT JOIN woparts ON probs.id = woparts.link GROUP BY probs.id]. AS ztotalparts RIGHT " + "JOIN (users RIGHT JOIN ((labor RIGHT JOIN (((wo RIGHT JOIN probs ON wo.id = probs.wolink) LEFT JOIN units " + "ON probs.unit = units.id) LEFT JOIN unitmodels ON units.model = unitmodels.id) ON labor.link = probs.id) LEFT " + "JOIN clients ON wo.client = clients.id) ON users.id = labor.tech) ON ztotalparts.id = probs.id) ON " + "ztotallabor.id = probs.id WHERE (((probs.unit)~UNIT) AND ((units.sn) Is Not Null) AND ((labor.start) " + "Between #~STRT# And #~END_#)) ORDER BY labor.start DESC;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=7));",q2); + rs->Ex(q); + + //UPDATE CALLBACKS BY DATE + + q="UPDATE rptsmaster SET rptsmaster.x = True " + "WHERE (((rptsmaster.id)=2));"; + rs->Ex(q); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"154\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.7.2.0\";"); + nVersion=154; + + } + + break; + + + case 154: //update for v1721 + + { + rs->Ex("ALTER TABLE users ADD COLUMN schedrnd YESNO;"); + rs->Ex("UPDATE users SET users.schedrnd = True;"); + + rs->Ex("ALTER TABLE users ADD COLUMN schedoneday YESNO;"); + rs->Ex("UPDATE users SET users.schedoneday = False;"); + + rs->Ex("ALTER TABLE rentals ADD COLUMN ref TEXT(80);"); + + rs->Ex("ALTER TABLE users ALTER COLUMN rentalprofile TEXT(80);"); + rs->Ex("ALTER TABLE users ALTER rentalprofile SET DEFAULT \"(9,9) 42 169 195 103 88 129 0 105 109 0 1 8 7 2 3 4 5 6\";"); + rs->Ex("UPDATE users SET users.rentalprofile = '(9,9) 42 169 195 103 88 129 0 105 109 0 1 8 7 2 3 4 5 6';"); + + + + //--------------------------------------- + //add the LOANERS report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"loaners\", \"loaners.rpt\", \"mgr\", False, 32767, 37;"); + + //------------------------------------------------ + + //--------------------------------------- + //add the RESPONSE TIME BY PROBLEM report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Response time by problem item (first response)\", \"respprob.rpt\", \"mgr\", True, 399, 38;"); + + q2="SELECT ~CRITERIA AS CRITERIA, probs.created AS prob_entered, probs.wolink, Min(labor.start) AS First_response, wo.id AS Workorder, wotypes.category AS CategoryName, projects.name AS ProjectName, clients.company AS ClientName, probs.brief " + "FROM (((labor LEFT JOIN (wo RIGHT JOIN probs ON wo.id = probs.wolink) ON labor.link = probs.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN projects ON wo.project = projects.id) LEFT JOIN wotypes ON wo.type = wotypes.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((wo.project)~PROJ) AND ((wo.client)~CUST) AND ((wo.type)~CAT_) AND ((labor.tech)~TECH) AND ((wo.quick)=False)) " + "GROUP BY probs.created, probs.wolink, wo.id, wotypes.category, projects.name, clients.company, probs.brief, wo.created " + "HAVING (((Min(labor.start)) Is Not Null)) " + "ORDER BY wo.created DESC , probs.wolink;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=38));",q2); + rs->Ex(q); + //------------------------------------------------ + //--------------------------------------- + //add the RESPONSE TIME BY WORKORDER report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Response time for standard WO (first response)\", \"respwo.rpt\", \"mgr\", True, 399, 39;"); + + q2="SELECT ~CRITERIA AS CRITERIA, wo.created AS wo_entered, probs.wolink, Min(labor.start) AS First_response, wo.id AS Workorder, wotypes.category AS CategoryName, projects.name AS ProjectName, clients.company AS ClientName " + "FROM (((labor LEFT JOIN (wo RIGHT JOIN probs ON wo.id = probs.wolink) ON labor.link = probs.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN projects ON wo.project = projects.id) LEFT JOIN wotypes ON wo.type = wotypes.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((wo.project)~PROJ) AND ((wo.client)~CUST) AND ((wo.type)~CAT_) AND ((labor.tech)~TECH) AND ((wo.quick)=False)) " + "GROUP BY wo.created, probs.wolink, wo.id, wotypes.category, projects.name, clients.company " + "HAVING (((Min(labor.start)) Is Not Null)) " + "ORDER BY wo.created DESC , probs.wolink;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=39));",q2); + rs->Ex(q); + //------------------------------------------------ + + + //ADD the tables for ARAS clients + //------------------------------------------------ + //clients_aras + rs->Ex( "CREATE TABLE clients_aras (" + "id COUNTER CONSTRAINT PK_clntaras PRIMARY KEY, " + "clientlink INTEGER DEFAULT 0," + "loginid TEXT(50), " + "loginpw TEXT(50), " + "view_wo_status YESNO DEFAULT False, " + "search_history YESNO DEFAULT False, " + "wo_view YESNO DEFAULT False, " + "wo_report YESNO DEFAULT False, " + "request_service YESNO DEFAULT False, " + "view_request_list YESNO DEFAULT False, " + "private_notes MEMO, " + "last_login_date DATETIME, " + "creator INTEGER DEFAULT 0, "//user who created record + "created DATETIME, " //date created + "modifier INTEGER DEFAULT 0, "//date modified + "modified DATETIME " + ");"); + //------------------------------------------------ + + //client_requests + rs->Ex( "CREATE TABLE client_requests (" + "id COUNTER CONSTRAINT PK_clntrqsts PRIMARY KEY, " + "clientlink INTEGER DEFAULT 0," + "requestor_id INTEGER DEFAULT 0," + "workorderid INTEGER DEFAULT 0," + "request TEXT(110), " + "probdetails MEMO, " + "prefertech INTEGER DEFAULT -1," + "refnum TEXT(80), " + "ournotes MEMO, " + "created DATETIME, " //date created + "urgency INTEGER DEFAULT 0"//0=not 2=extreme + + ");"); + //------------------------------------------------ + + //ADD new profile key to user table for ARAS request view screen + + + rs->Ex("ALTER TABLE users ADD COLUMN aras_req_profile TEXT(80);"); + rs->Ex("ALTER TABLE users ALTER aras_req_profile SET DEFAULT \"(7,7) 52 76 128 73 217 162 0 0 1 2 3 4 5 6\";"); + rs->Ex("UPDATE users SET users.aras_req_profile = '(7,7) 52 76 128 73 217 162 0 0 1 2 3 4 5 6';"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"155\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.7.2.1\";"); + nVersion=155; + + + } + + break; + + + case 155://changed to 156 on Sept 30th 2002 for version 1.9 + { + //Added field to turn on or off transaction support + //true=database execute queries are wrapped in transactions + //false=old style pre 1.9 not wrapped in transactions + //made it an option in case users have problems + //should improve data currency on a busy network + rs->Ex("ALTER TABLE defaults ADD COLUMN transact YESNO;"); + rs->Ex("UPDATE defaults SET defaults.transact = True;"); + + + //client alternate phone number + rs->Ex("ALTER TABLE clients ADD COLUMN phone2 TEXT(40);"); + rs->Ex("ALTER TABLE clients ADD COLUMN phone3 TEXT(40);"); + + + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"156\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=156; + + } + + break; + + case 156://changed to 157 on Oct 4th 2002 for version 1.9 + { + + //Horizontal grid on main work order list screen + //user preference field. Default to true so they + //know it's there and we can get all those emails + //bitching about it because they don't read the docs and know that + //they can turn it off + rs->Ex("ALTER TABLE users ADD COLUMN hgrid YESNO;"); + rs->Ex("UPDATE users SET users.hgrid = True;"); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"157\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=157; + + + break; + + } + + + case 157://changed to 158 on Oct 8th 2002 for version 1.9 + { + + //drop location field in wo which is not used and + //add a pmid field + rs->Ex("ALTER TABLE wo ADD COLUMN pmid INTEGER;"); + rs->Ex("ALTER TABLE wo ALTER pmid SET DEFAULT '0';"); + rs->Ex("UPDATE wo SET wo.pmid = 0;"); + rs->Ex("ALTER TABLE wo DROP COLUMN location;"); + + + //update pmhead table to include the two new time fields + rs->Ex("ALTER TABLE pmhead ADD COLUMN starttime DATETIME;"); + rs->Ex("ALTER TABLE pmhead ADD COLUMN endtime DATETIME;"); + rs->Ex("UPDATE pmhead SET pmhead.starttime = #10/8/2002 8:0:0#;"); + rs->Ex("UPDATE pmhead SET pmhead.endtime = #10/8/2002 9:0:0#;"); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"158\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=158; + break; + + } + + + + case 158://changed to 159 on Oct 9th 2002 for version 1.9 + { + + //-2 now means don't show scheduled tech column in workorder list + //where it used to be 0 for that so change all 0's to -2's + rs->Ex("UPDATE statusviews SET statusviews.schedtech = -2 " + "WHERE (((statusviews.schedtech)=0));"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"159\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=159; + break; + + } + + + case 159://changed to 160 on Oct 11th 2002 for version 1.9 + { + + //add created days column to status views table + rs->Ex("ALTER TABLE statusviews ADD COLUMN createddays INTEGER;"); + rs->Ex("ALTER TABLE statusviews ALTER createddays SET DEFAULT '0';"); + rs->Ex("UPDATE statusviews SET statusviews.createddays = 0;"); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"160\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=160; + break; + } + + + + case 160://changed to 161 on Oct 12th 2002 for version 1.9 + { + + //Add distance column to labor table + rs->Ex("ALTER TABLE labor ADD COLUMN distance REAL;"); + rs->Ex("ALTER TABLE labor ALTER distance SET DEFAULT '0';"); + rs->Ex("UPDATE labor SET labor.distance = 0;"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"161\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=161; + break; + + } + + + + case 161://changed to 162 on Oct 12th 2002 for version 1.9 + { + + //Add distance column to labor table + rs->Ex("ALTER TABLE clients ADD COLUMN inactive YESNO;"); + rs->Ex("ALTER TABLE clients ALTER inactive SET DEFAULT '0';"); + rs->Ex("UPDATE clients SET clients.inactive = False;"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"162\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=162; + + break; + + } + + + + case 162://changed to 163 on Oct 12th 2002 for version 1.9 + { + + //Set all woparts.misc to NULL as some may be empty + //other changes will ensure it is never set to empty in future + //this is just to catch any existing ones. + rs->Ex("UPDATE woparts SET woparts.misc = Null WHERE (((woparts.misc)=\"\"));"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"163\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=163; + + break; + + } + + + + case 163://changed to 164 on Oct 13th 2002 for version 1.9 + { + + //Add subquery field to rptsmaster + //required for parts printing on dispatch standard workorder + rs->Ex("ALTER TABLE rptsmaster ADD COLUMN subreportquery MEMO;"); + + + //REMOVE ANY OLD RPTS MASTER ENTRIES FOR WORKORDER REPORTS + + //STANDARD DISPATCH + q2="SELECT \"~ESTRATE\" AS estrate, \"~SCHEDTECH\" AS scheduledtech, " +"~ESTHOURS AS esthours, IIf(IsNull([clients].[company]),[clients].[last] " +"& \", \" & [clients].[first],[clients].[company]) " +"AS clientname, IIf(IsNull([clients].[streetaddress]),[clients].[mailaddress],[clients].[streetaddress]) ""& IIf(IsNull([clients].[city]),\"\",Chr(13) " +"& [clients].[city]) & IIf(IsNull([clients].[stateprov]),\"\",\", " +"\" & [clients].[stateprov] " +"& IIf(IsNull([clients].[postal]),\"\",\" " +"\" & [clients].[postal])) AS address, \"Work required: " +"\" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) " +"& \"Unit: \" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] " +"& \") SN: \" & [units].[sn],\"\") AS probheader, " +"\"~REGTO\" AS compname, wo.notes AS wonotes, " +"wo.clientrefnum, wo.clientcontact, wo.ourref, " +"wo.prob_reported, wo.prob_found, wo.action_taken, " +"wo.id AS wonumber, wo.created, labor.details, probs.notes, " +"IIf(IsNull(contracts_1.name),[contracts].[name],contracts_1.name) " +"AS contractinfo, IIf([probs].[unit]<>0,\"Unit: " +"\" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] & \" (\" " +"& [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") " +"AS Equipment, wo.starttime AS [Booked for], wo.stoptime " +"AS [Booked for END], wo.closed, probs.brief, " +"clients.mailaddress, clients.streetaddress, clients.city, " +"clients.stateprov, clients.postal, clients.country, " +"clients.bizphone, clients.extension, " +"clients.technotes, clients.first, clients.last, probstat.notes " +"AS STATUS, probstat_1.notes AS ITEMSTATUS, " +"projects.name AS PROJNAME, projects.notes AS " +"PROJNOTES FROM projects RIGHT JOIN ((((((labor RIGHT " +"JOIN (((units RIGHT JOIN probs ON units.id = " +"probs.unit) LEFT JOIN unitmodels ON units.model = " +"unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer " +"= nonclients.id) ON labor.link = probs.id) " +"RIGHT JOIN ((wo LEFT JOIN clients ON wo.client " +"= clients.id) LEFT JOIN clients AS headoffices " +"ON clients.headoffice = headoffices.id) ON probs.wolink " +"= wo.id) LEFT JOIN contracts ON clients.contract " +"= contracts.id) LEFT JOIN contracts AS contracts_1 " +"ON headoffices.contract = contracts_1.id) LEFT " +"JOIN probstat ON wo.status = probstat.id) LEFT " +"JOIN probstat AS probstat_1 ON probs.status = probstat_1.id) " +"ON projects.id = wo.project WHERE (((wo.id)=~WOID)); "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=21));",q2); + rs->Ex(q); + + + //***** SUBREPORT ****************** + q2="SELECT probs.id, woparts.quantity, woparts.sn, parts.partnumber, " +"woparts.misc, parts.description, parts.retail, " +"IIf(IsNull(woparts.misc),[parts].[partnumber] " +"& \" \" & [parts].[description] & \": \" & [woparts].[quantity] " +"& \" @ \" & Format([woparts].[price],\"Currency\") " +"& \" ea.\" & IIf(IsNull([woparts].[sn]),\"\",\" sn:\" & [woparts].[sn]) " +", [woparts].[misc] " +"& \": \" & [woparts].[quantity] & \" @ \" & Format([woparts].[price],\"Currency\") " +"& \" ea.sn:\" & [woparts].[sn] " +") AS item, [woparts].[quantity]*[woparts].[price] " +"AS linetotal FROM (woparts RIGHT JOIN " +"(probs RIGHT JOIN wo ON probs.wolink = wo.id) ON " +"woparts.link = probs.id) LEFT JOIN parts ON woparts.partnum " +"= parts.id WHERE (((woparts.quantity) " +"Is Not Null) AND ((wo.id)=~WOID));"; + + q.Format("UPDATE rptsmaster SET rptsmaster.subreportquery = '%s' " + "WHERE (((rptsmaster.id)=21));",q2); + rs->Ex(q); + //------------------------------------------------ + + //STANDARD BRIEF + q2="SELECT \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) " +"& \"Unit: \" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] " +"& \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") " +"AS probheader, \"~REGTO\" AS compname, wom.probnum, " +"wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, " +"wom.PROBBRIEF, wom.item, wom.linetotal, " +"wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created " +"AS wodate, wo.id AS wonumber, wo.invoice, " +"wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, " +"clients.billheadoffice, clients.first, clients.last, " +"clients.mailaddress, clients.streetaddress, " +"clients.city, clients.stateprov, clients.postal, " +"clients.country, clients.bizphone, clients.extension, " +"clients.fax, clients.email, [clients].[company] " +"AS clientname, IIf(IsNull([headoffices].[company]),[headoffices].[last] " +"& \", \" & [headoffices].[first],[headoffices].[company]) " +"AS headname, wom.details, " +"wom.STARTDATE, wom.STOPDATE, projects.name " +"AS PROJNAME, projects.notes AS PROJNOTES FROM " +"(((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT " +"\"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum " +"AS TRAVPN, probs.notes AS PROBNOTES, probs.brief " +"AS PROBBRIEF, probs.id AS probnum, probs.wolink " +"AS wonum, \"Service: \" & users.first & \" \" & " +"users.last & \" - \" & IIf(labor.hours>0,labor.hours " +"& \" hrs. @ \" & Format(rates.rate,\"Currency\") & \" " +"(pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" " +"(\" & labor.nchours & \" hrs. no charge)\",\"\") " +"& IIf(labor.travhours>0,\", \" & labor.travhours & \" " +"hrs. travel @ \" & Format(travelrates.rate,\"Currency\") " +"& IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" " +"& travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) " +"AS linetotal,labor.details, labor.start AS STARTDATE, " +"labor.stop as STOPDATE FROM users INNER JOIN " +"(rates AS travelrates INNER JOIN (rates INNER JOIN " +"(labor INNER JOIN probs ON labor.link = probs.id) " +"ON rates.id = labor.rate) ON travelrates.id = labor.travrate) " +"ON users.id = labor.tech WHERE (((probs.wolink)=~WOID)) " +"UNION ALL (SELECT \"2\" AS ctype, " +"\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, " +"probs.brief AS PROBBRIEF, probs.id AS probnum, " +" probs.wolink as wonum, \"Parts: \" & IIf(IsNull(woparts.misc),parts.partnumber " +"& \" \" & parts.description " +"& \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") " +"& \" ea.(sn:\" & woparts.sn " +"& \")\",woparts.misc & \": \" & woparts.quantity " +"& \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" " +"& woparts.sn & \")\") AS item, woparts.quantity*woparts.price " +"AS linetotal,\"\" AS details, #03/12/1968# " +"AS STARTDATE, #03/12/1968# AS STOPDATE FROM " +"(probs INNER JOIN woparts ON probs.id = woparts.link) " +"LEFT JOIN parts ON woparts.partnum = parts.id " +"WHERE (((probs.wolink)=~WOID)) UNION ALL (SELECT " +" \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes " +"AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id " +"AS probnum, probs.wolink as wonum, \"Third party " +"service: \" AS item, subrepair.charge AS linettotal, " +"\"\" AS details, #03/12/1968# AS STARTDATE, #03/12/1968# " +"AS STOPDATE FROM probs INNER JOIN subrepair " +"ON probs.id = subrepair.link WHERE (((probs.wolink)=~WOID) " +"AND ((subrepair.charge)<>0))))]. AS " +"wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN " +"clients ON wo.client = clients.id) LEFT JOIN clients " +"AS headoffices ON clients.headoffice = headoffices.id) " +"ON probs.id = wom.probnum) ON units.id = probs.unit) " +"LEFT JOIN unitmodels ON units.model = unitmodels.id) " +"LEFT JOIN nonclients ON unitmodels.manufacturer " +"= nonclients.id) LEFT JOIN projects ON " +"wo.project = projects.id ORDER BY wom.STARTDATE DESC; "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=1));",q2); + rs->Ex(q); + //------------------------------------------------ + + //STANDARD COMPLETED + q2="SELECT \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) " +"& \"Unit: \" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] " +"& \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") " +"AS probheader, \"~REGTO\" AS compname, wom.probnum, " +"wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, " +"wom.PROBBRIEF, wom.item, wom.linetotal, " +"wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created " +"AS wodate, wo.id AS wonumber, wo.invoice, " +"wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, " +"clients.billheadoffice, clients.first, clients.last, " +"clients.mailaddress, clients.streetaddress, " +"clients.city, clients.stateprov, clients.postal, " +"clients.country, clients.bizphone, clients.extension, " +"clients.fax, clients.email, [clients].[company] " +"AS clientname, IIf(IsNull([headoffices].[company]),[headoffices].[last] " +"& \", \" & [headoffices].[first],[headoffices].[company]) " +"AS headname, wom.details, " +"wom.STARTDATE, wom.STOPDATE, projects.name " +"AS PROJNAME, projects.notes AS PROJNOTES FROM " +"(((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT " +"\"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum " +"AS TRAVPN, probs.notes AS PROBNOTES, probs.brief " +"AS PROBBRIEF, probs.id AS probnum, probs.wolink " +"AS wonum, \"Service: \" & users.first & \" \" & " +"users.last & \" - \" & IIf(labor.hours>0,labor.hours " +"& \" hrs. @ \" & Format(rates.rate,\"Currency\") & \" " +"(pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" " +"(\" & labor.nchours & \" hrs. no charge)\",\"\") " +"& IIf(labor.travhours>0,\", \" & labor.travhours & \" " +"hrs. travel @ \" & Format(travelrates.rate,\"Currency\") " +"& IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" " +"& travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) " +"AS linetotal,labor.details, labor.start AS STARTDATE, " +"labor.stop as STOPDATE FROM users INNER JOIN " +"(rates AS travelrates INNER JOIN (rates INNER JOIN " +"(labor INNER JOIN probs ON labor.link = probs.id) " +"ON rates.id = labor.rate) ON travelrates.id = labor.travrate) " +"ON users.id = labor.tech WHERE (((probs.wolink)=~WOID)) " +"UNION ALL (SELECT \"2\" AS ctype, " +"\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, " +"probs.brief AS PROBBRIEF, probs.id AS probnum, " +" probs.wolink as wonum, \"Parts: \" & IIf(IsNull(woparts.misc),parts.partnumber " +"& \" \" & parts.description " +"& \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") " +"& \" ea.(sn:\" & woparts.sn " +"& \")\",woparts.misc & \": \" & woparts.quantity " +"& \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" " +"& woparts.sn & \")\") AS item, woparts.quantity*woparts.price " +"AS linetotal,\"\" AS details, #03/12/1968# " +"AS STARTDATE, #03/12/1968# AS STOPDATE FROM " +"(probs INNER JOIN woparts ON probs.id = woparts.link) " +"LEFT JOIN parts ON woparts.partnum = parts.id " +"WHERE (((probs.wolink)=~WOID)) UNION ALL (SELECT " +" \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes " +"AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id " +"AS probnum, probs.wolink as wonum, \"Third party " +"service: \" AS item, subrepair.charge AS linettotal, " +"\"\" AS details, #03/12/1968# AS STARTDATE, #03/12/1968# " +"AS STOPDATE FROM probs INNER JOIN subrepair " +"ON probs.id = subrepair.link WHERE (((probs.wolink)=~WOID) " +"AND ((subrepair.charge)<>0))))]. AS " +"wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN " +"clients ON wo.client = clients.id) LEFT JOIN clients " +"AS headoffices ON clients.headoffice = headoffices.id) " +"ON probs.id = wom.probnum) ON units.id = probs.unit) " +"LEFT JOIN unitmodels ON units.model = unitmodels.id) " +"LEFT JOIN nonclients ON unitmodels.manufacturer " +"= nonclients.id) LEFT JOIN projects ON " +"wo.project = projects.id ORDER BY wom.STARTDATE DESC; "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=19));",q2); + rs->Ex(q); + //------------------------------------------------ + + + + + //QUICK DISPATCH WORKORDER + q2="SELECT IIf(IsNull([clients].[company]),[clients].[last] " +"& \", \" & [clients].[first],[clients].[company]) " +"AS clientname, IIf(IsNull([clients].[streetaddress]),[clients].[mailaddress],[clients].[streetaddress]) ""& IIf(IsNull([clients].[city]),\"\",[clients].[city]) " +"& IIf(IsNull([clients].[stateprov]),\"\",\", " +"\" & [clients].[stateprov] & IIf(IsNull([clients].[postal]),\"\",\" " +"\" & [clients].[postal])) AS address, " +"\"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) " +"& \"Unit: \" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] & " +"\" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") " +"AS probheader, \"~REGTO\" AS compname, wo.id " +"AS wonumber, wo.created, labor.details, probs.notes, " +"IIf(IsNull(contracts_1.name),[contracts].[name],contracts_1.name) " +"AS contractinfo, IIf([probs].[unit]<>0,\"Unit: " +"\" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] " +"& \") SN: \" & [units].[sn],\"\") AS " +"Equipment, wo.starttime AS [Booked for], probs.brief, " +"clients.mailaddress, clients.streetaddress, " +"clients.city, clients.stateprov, clients.postal, clients.country, " +"clients.bizphone, clients.extension, " +"clients.technotes, clients.first, clients.last, " +"wo.clientrefnum, wo.ourref, wo.clientcontact FROM " +"(((labor RIGHT JOIN (((units RIGHT JOIN probs ON " +"units.id = probs.unit) LEFT JOIN unitmodels ON units.model " +"= unitmodels.id) LEFT JOIN nonclients ON " +"unitmodels.manufacturer = nonclients.id) ON labor.link " +"= probs.id) RIGHT JOIN ((wo LEFT JOIN clients " +"ON wo.client = clients.id) LEFT JOIN clients AS headoffices " +"ON clients.headoffice = headoffices.id) " +"ON probs.wolink = wo.id) LEFT JOIN contracts ON clients.contract " +"= contracts.id) LEFT JOIN contracts " +"AS contracts_1 ON headoffices.contract = contracts_1.id " +"WHERE (((wo.id)=~WOID));"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=22));",q2); + rs->Ex(q); + //------------------------------------------------ + + + //QUICK COMPLETED FORMAT WORKORDER REPORT + q2="SELECT \"~REGTO\" AS zCompName, wo.id, wo.clientrefnum, " +"wo.clientcontact, clients.company AS clientcompany, " +"Format(wo.closed,\"Short Date\") AS wodate, " +"[users]![first] & \" \" & [users]![last] AS wotech, " +"labor.hours, labor.travhours, labor.nchours, rates_1.name " +"AS workrate, rates.name AS travrate, labor.start " +"AS starttime, labor.stop AS stoptime, wo.invoice, " +"labor.details, wo.onsite FROM (((users " +"RIGHT JOIN (labor RIGHT JOIN (wo LEFT JOIN probs ON " +"wo.id = probs.wolink) ON labor.link = probs.id) " +"ON users.id = labor.tech) LEFT JOIN clients ON wo.client " +"= clients.id) LEFT JOIN rates ON labor.travrate " +"= rates.id) LEFT JOIN rates AS rates_1 ON " +"labor.rate = rates_1.id WHERE (((wo.id)=~WOID)); "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=0));",q2); + rs->Ex(q); + //------------------------------------------------ + + //fixup the dispatch report recordset fields + rs->Ex("UPDATE rptsmaster SET rptsmaster.recordset = \"wostandard\" " + "WHERE (((rptsmaster.id)=21));"); + + + rs->Ex("UPDATE rptsmaster SET rptsmaster.recordset = \"woquick\" " + "WHERE (((rptsmaster.id)=22));"); + + //Fix the workorder virtual names so they are + //the same as the original menu commands that called them + rs->Ex("UPDATE rptsmaster SET rptsmaster.virtualname = \"&Dispatch format work order\" " + "WHERE (((rptsmaster.id)=22));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.virtualname = \"&Completed work order\" " + "WHERE (((rptsmaster.id)=0));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.virtualname = \"&Dispatch work order\" " + "WHERE (((rptsmaster.id)=21));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.virtualname = \"&Brief completed work order\" " + "WHERE (((rptsmaster.id)=1));"); + rs->Ex("UPDATE rptsmaster SET rptsmaster.virtualname = \"D&etailed completed work order\" " + "WHERE (((rptsmaster.id)=19));"); + + + //Add the subreport filename field + rs->Ex("ALTER TABLE rptsmaster ADD COLUMN subfilename TEXT(255);"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.subfilename = \"wodispstpartssub.rpt\" " + "WHERE (((rptsmaster.id)=21));"); + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"164\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=164; + + + break; + + } + + + case 164://changed to 165 on Oct 14th 2002 for version 1.9 + { + + //Add cost of parts to woparts + //this is used to record cost at time of use + rs->Ex("ALTER TABLE woparts ADD COLUMN cost CURRENCY;"); + rs->Ex("ALTER TABLE woparts ALTER cost SET DEFAULT '0';"); + rs->Ex("UPDATE woparts SET woparts.cost = 0;"); + + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"165\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=165; + break; + + } + + + + case 165://changed to 166 on Oct 14th 2002 for version 1.9 + { + + /* + Add new fields for rptsusers + long m_lPaperOrientation; + long m_lPaperSize; + long m_lPaperSource; + long m_lDuplexType; + */ + + rs->Ex("ALTER TABLE rptsusers ADD COLUMN porient INTEGER;"); + rs->Ex("ALTER TABLE rptsusers ALTER porient SET DEFAULT '0';"); + rs->Ex("UPDATE rptsusers SET rptsusers.porient = 0;"); + + rs->Ex("ALTER TABLE rptsusers ADD COLUMN psize INTEGER;"); + rs->Ex("ALTER TABLE rptsusers ALTER psize SET DEFAULT '0';"); + rs->Ex("UPDATE rptsusers SET rptsusers.psize = 0;"); + + rs->Ex("ALTER TABLE rptsusers ADD COLUMN psource INTEGER;"); + rs->Ex("ALTER TABLE rptsusers ALTER psource SET DEFAULT '0';"); + rs->Ex("UPDATE rptsusers SET rptsusers.psource = 0;"); + + rs->Ex("ALTER TABLE rptsusers ADD COLUMN pduplex INTEGER;"); + rs->Ex("ALTER TABLE rptsusers ALTER pduplex SET DEFAULT '0';"); + rs->Ex("UPDATE rptsusers SET rptsusers.pduplex = 0;"); + + rs->Ex("ALTER TABLE rptsusers DROP COLUMN devmode;"); + rs->Ex("ALTER TABLE rptsusers DROP COLUMN devmodesize;"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"166\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=166; + break; + + } + + case 166://changed to 167 on Oct 16th 2002 for version 1.9 + { + + + + + //--------------------------------------- + /* + Add new wodispst2.rpt + Dispatch work order (with labor) + */ + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename,subfilename, recordset, x, criteriafields, id ) " + "SELECT \"Dispatch work order (with &labor)\", \"wodispst2.rpt\", \"wodispstpartssub.rpt\", \"wostandard\", False, 32767, 40;"); + + q2="SELECT \"~ESTRATE\" AS estrate, \"~SCHEDTECH\" AS scheduledtech, " +"~ESTHOURS AS esthours, IIf(IsNull([clients].[company]),[clients].[last] " +"& \", \" & [clients].[first],[clients].[company]) " +"AS clientname, IIf(IsNull([clients].[streetaddress]),[clients].[mailaddress],[clients].[streetaddress]) ""& IIf(IsNull([clients].[city]),\"\",Chr(13) " +"& [clients].[city]) & IIf(IsNull([clients].[stateprov]),\"\",\", " +"\" & [clients].[stateprov] " +"& IIf(IsNull([clients].[postal]),\"\",\" " +"\" & [clients].[postal])) AS address, \"Work required: " +"\" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) " +"& \"Unit: \" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] " +"& \") SN: \" & [units].[sn],\"\") AS probheader, " +"\"~REGTO\" AS compname, wo.notes AS wonotes, " +"wo.clientrefnum, wo.clientcontact, wo.ourref, " +"wo.prob_reported, wo.prob_found, wo.action_taken, " +"wo.id AS wonumber, wo.created, labor.details, probs.notes, " +"IIf(IsNull(contracts_1.name),[contracts].[name],contracts_1.name) " +"AS contractinfo, IIf([probs].[unit]<>0,\"Unit: " +"\" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] & \" (\" " +"& [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") " +"AS Equipment, wo.starttime AS [Booked for], wo.stoptime " +"AS [Booked for END], wo.closed, probs.brief, " +"clients.mailaddress, clients.streetaddress, clients.city, " +"clients.stateprov, clients.postal, clients.country, " +"clients.bizphone, clients.extension, " +"clients.technotes, clients.first, clients.last, probstat.notes " +"AS STATUS, probstat_1.notes AS ITEMSTATUS, " +"projects.name AS PROJNAME, projects.notes AS " +"PROJNOTES, users.first, users.last, users.initials, " +"labor.hours, labor.nchours, labor.travhours, labor.start, " +"labor.stop, labor.distance FROM (projects " +"RIGHT JOIN ((((((labor RIGHT JOIN (((units RIGHT " +"JOIN probs ON units.id = probs.unit) LEFT JOIN " +"unitmodels ON units.model = unitmodels.id) LEFT JOIN " +"nonclients ON unitmodels.manufacturer = nonclients.id) " +"ON labor.link = probs.id) RIGHT JOIN ((wo " +"LEFT JOIN clients ON wo.client = clients.id) LEFT " +"JOIN clients AS headoffices ON clients.headoffice " +"= headoffices.id) ON probs.wolink = wo.id) LEFT JOIN " +"contracts ON clients.contract = contracts.id) LEFT " +"JOIN contracts AS contracts_1 ON headoffices.contract " +"= contracts_1.id) LEFT JOIN probstat ON wo.status " +"= probstat.id) LEFT JOIN probstat AS probstat_1 " +"ON probs.status = probstat_1.id) ON projects.id " +"= wo.project) LEFT JOIN users ON labor.tech = " +"users.id WHERE (((wo.id)=~WOID));"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=40));",q2); + rs->Ex(q); + + + //subreport query + q2="SELECT probs.id, woparts.quantity, woparts.sn, parts.partnumber, " +"woparts.misc, parts.description, parts.retail, " +"IIf(IsNull(woparts.misc),[parts].[partnumber] " +"& \" \" & [parts].[description] & \": \" & [woparts].[quantity] " +"& \" @ \" & Format([woparts].[price],\"Currency\") " +"& \" ea.\" & IIf(IsNull([woparts].[sn]),\"\",\" " +"sn:\" & [woparts].[sn]) , [woparts].[misc] " +"& \": \" & [woparts].[quantity] & \" @ \" & Format([woparts].[price],\"Currency\") " +"& \" ea.sn:\" & [woparts].[sn] " +") AS item, [woparts].[quantity]*[woparts].[price] " +"AS linetotal FROM (woparts RIGHT JOIN (probs " +"RIGHT JOIN wo ON probs.wolink = wo.id) ON woparts.link " +"= probs.id) LEFT JOIN parts ON woparts.partnum " +"= parts.id WHERE (((woparts.quantity) Is Not Null) " +"AND ((wo.id)=~WOID));"; + q.Format("UPDATE rptsmaster SET rptsmaster.subreportquery = '%s' " + "WHERE (((rptsmaster.id)=40));",q2); + rs->Ex(q); + //------------------------------------------------ + + + //---------- ADD DISPLAY ORDER FIELD TO RPTS MASTER + rs->Ex("ALTER TABLE rptsmaster ADD COLUMN wodisplayorder INTEGER;"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.wodisplayorder = 1 " + "WHERE (((rptsmaster.virtualname)=\"&Dispatch format work order\"));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.wodisplayorder = 2 " + "WHERE (((rptsmaster.virtualname)=\"&Completed work order\"));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.wodisplayorder = 3 " + "WHERE (((rptsmaster.virtualname)=\"&Dispatch work order\"));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.wodisplayorder = 4 " + "WHERE (((rptsmaster.virtualname)=\"Dispatch work order (with &labor)\"));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.wodisplayorder = 5 " + "WHERE (((rptsmaster.virtualname)=\"&Brief completed work order\"));"); + + rs->Ex("UPDATE rptsmaster SET rptsmaster.wodisplayorder = 6 " + "WHERE (((rptsmaster.virtualname)=\"D&etailed completed work order\"));"); + + + + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"167\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=167; + + break; + + } + + + + case 167: + { + + //Addition of client address book Report + rs->Ex("INSERT INTO rptsmaster ( virtualname, filename, recordset, x, criteriafields, id ) " + "SELECT \"Client address book\", \"clntadd.rpt\", \"mgr\", True, 32767, 41;"); + + q2="SELECT clients.*, HEADS.* FROM clients LEFT JOIN clients " + "AS HEADS ON clients.headoffice = HEADS.id WHERE " + "(((clients.id)~CUST)) ORDER BY clients.company; "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=41));",q2); + rs->Ex(q); + + + //Set STATUS column in statusviews to -1 if it was previously 1 as -1 + //now means any status where 1 used to mean any status + q.Format("UPDATE statusviews SET statusviews.status = -1 WHERE (((statusviews.status)=1));"); + rs->Ex(q); + + + //10/26/2002 + //set assigntech to correct value on old quick work orders + q="UPDATE labor RIGHT JOIN (probs RIGHT JOIN wo ON probs.wolink = wo.id) " + "ON labor.link = probs.id SET wo.assigntech = [labor].[tech] " + "WHERE (((wo.quick)=True) AND ((wo.assigntech)=-1));"; + rs->Ex(q); + + //Add aras_client field to rptsmaster + rs->Ex("ALTER TABLE rptsmaster ADD COLUMN client_aras YESNO;"); + rs->Ex("ALTER TABLE rptsmaster ALTER client_aras SET DEFAULT '-1';"); + rs->Ex("UPDATE rptsmaster SET rptsmaster.client_aras = True;"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"168\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.0.0\";"); + nVersion=168; + //buptodate=true;//<<==========CRITICAL!!!!!, should be at end of last case statement only + break; + + } + + case 168: + { + + //Changed ....... + rs->Ex("ALTER TABLE probs ALTER COLUMN meter INTEGER;"); + + + //Update report 31 to fix bug in query causing part descriptions to be blank + q2="SELECT ~CRITERIA AS CRITERIA, wo.id AS wonumber, \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) & \"Unit: \" & [nonclients].[company_person] & \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") AS probheader, \"test\" AS compname, wom.probnum, wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, wom.PROBBRIEF, wom.item, wom.linetotal, wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created AS wodate, wo.invoice, wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, clients.bizphone, clients.extension, clients.fax, clients.email, clients.company AS clientname, wom.details, wom.START, wom.STOP,wom.REGHOURS, wom.TRAVHOURS, wom.NCHOURS, projects.name AS PROJNAME, projects.notes AS PROJNOTES, wo.client, wo.project, wo.type, wotypes.category AS CATEGORY " + "FROM ((((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT \"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink AS wonum, \"Service: \" & users.first & \" \" & users.last & \" - \" & IIf(labor.hours>0,labor.hours & \" hrs. @ \" & Format(rates.rate,\"Currency\") & \" (pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" (\" & labor.nchours & \" hrs. no charge)\",\"\") & IIf(labor.travhours>0,\", \" & labor.travhours & \" hrs. travel @ \" & Format(travelrates.rate,\"Currency\") & IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" & travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) AS linetotal, labor.details , labor.start AS START, labor.stop AS STOP, labor.hours AS REGHOURS, labor.travhours AS TRAVHOURS, labor.nchours as NCHOURS FROM users INNER JOIN (rates AS travelrates INNER JOIN (rates INNER JOIN (labor INNER JOIN probs ON labor.link = probs.id) ON rates.id = labor.rate) ON travelrates.id = labor.travrate) ON users.id = labor.tech WHERE (((probs.wolink)<>0)) " + " UNION ALL (SELECT \"2\" AS ctype, \"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Parts: \" & IIf(IsNull(woparts.misc), parts.partnumber & \" \" & parts.description & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") & \" ea.(sn:\" & woparts.sn & \")\",woparts.misc & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" & woparts.sn & \")\") AS item, woparts.quantity*woparts.price AS linetotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM (probs INNER JOIN woparts ON probs.id = woparts.link) " + " LEFT JOIN parts ON woparts.partnum = parts.id WHERE (((probs.wolink)<>0)) " + "UNION ALL (SELECT \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Third party service: \" AS item, subrepair.charge AS linettotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM probs INNER JOIN subrepair ON probs.id = subrepair.link WHERE (((probs.wolink)<>0) AND ((subrepair.charge)<>0))))]. AS wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN clients AS headoffices ON clients.headoffice = headoffices.id) ON probs.id = wom.probnum) ON units.id = probs.unit) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) LEFT JOIN projects ON wo.project = projects.id ) LEFT JOIN wotypes ON wo.type = wotypes.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_)) " + "ORDER BY wo.id;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=31));",q2); + rs->Ex(q); + + //************* change any client aras logins that match ayanova user logins ********** + CString strReportDupes,str; + CString sLoginARAS,sLoginARASHash,sCompany,sNewLogin; + GZK k; + long l=0; + long lARASID=0; + //check for and zap any aras client login names that match AyaNova login names + //loop through all aras login names + //for each that hashes out to same as ayanova login name, change login name to prepend unique string + q="SELECT clients.company AS COMP1, clients_aras.loginid, " + "clients_aras.id AS ARASID FROM clients_aras LEFT " + "JOIN clients ON clients_aras.clientlink = clients.id " + "ORDER BY clients.company, clients_aras.loginid;"; + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty()) + { + do{ + + rs2->FetchField("loginid",&sLoginARAS); + sLoginARASHash=sLoginARAS; + k.GZHash(&sLoginARASHash); + q.Format("SELECT users.login FROM users WHERE (((users.login)=\"%s\"));",sLoginARASHash); + rs3->QueryReadOnly(q); + if(!rs3->IsEmpty())//This ARAS client login matches AyaNova login + { + + l++; + sNewLogin.Format("Temporary%u",l); + rs2->FetchField("COMP1",&sCompany); + str.Format("Client %s ARAS login account %s changed to %s\r\n",sCompany,sLoginARAS,sNewLogin); + strReportDupes+=str; + rs2->FetchField("ARASID",&lARASID); + q.Format("UPDATE clients_aras SET clients_aras.loginid = \"%s\" " + "WHERE (((clients_aras.id) = %u ));",sNewLogin,lARASID); + rs->Ex(q); + + + + } + + }while(rs2->MoveForward()); + + + } + + + + + //Check for duplicate ARAS client login names + + q="SELECT clients_aras.loginid, clients_aras.id AS ARASID, clients.company AS COMP1 " +"FROM clients_aras LEFT JOIN clients ON " +"clients_aras.clientlink = clients.id WHERE (((clients_aras.loginid) " +"In (SELECT [loginid] FROM [clients_aras] " +"As Tmp GROUP BY [loginid] HAVING Count(*)>1 " +"))) ORDER BY clients_aras.loginid;"; + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty())//there are dupes + { + do{ + l++; + sNewLogin.Format("Temporary%u",l); + rs2->FetchField("COMP1",&sCompany); + str.Format("Client %s ARAS login account %s changed to %s\r\n",sCompany,sLoginARAS,sNewLogin); + strReportDupes+=str; + rs2->FetchField("ARASID",&lARASID); + q.Format("UPDATE clients_aras SET clients_aras.loginid = \"%s\" " + "WHERE (((clients_aras.id) = %u ));",sNewLogin,lARASID); + rs->Ex(q); + + + }while(rs2->MoveForward()); + + + } + + if(!strReportDupes.IsEmpty()) + { + strReportDupes= + "******** READ THIS CAREFULLY ********\r\n" + "The following client(s) ARAS login ID's we're changed for security reasons.\r\n\r\n" + + "You should save this information now and change them after the update has\r\n" + "completed. (otherwise they will not be able to log in)\r\n\r\n" + + "To save this information click on the copy all text.. button, open a word processor or\r\n" + "Microsoft Notepad and paste. You can then save / print this list.\r\n" + "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r\n"+strReportDupes; + m_pApp->ShowStuff(strReportDupes); + strReportDupes.Empty(); + + } + + + +//****************************************************************************** + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"169\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.3.0\";"); + nVersion=169; + //buptodate=true;//<<==========CRITICAL!!!!!, should be at end of last case statement only + break; + + } + case 169: + { + + //------------------------------------------------ + //REMOVE Hrs. FROM WORK ORDER REPORT QUERIES + //STANDARD BRIEF + q2="SELECT \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) " +"& \"Unit: \" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] " +"& \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") " +"AS probheader, \"~REGTO\" AS compname, wom.probnum, " +"wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, " +"wom.PROBBRIEF, wom.item, wom.linetotal, " +"wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created " +"AS wodate, wo.id AS wonumber, wo.invoice, " +"wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, " +"clients.billheadoffice, clients.first, clients.last, " +"clients.mailaddress, clients.streetaddress, " +"clients.city, clients.stateprov, clients.postal, " +"clients.country, clients.bizphone, clients.extension, " +"clients.fax, clients.email, [clients].[company] " +"AS clientname, IIf(IsNull([headoffices].[company]),[headoffices].[last] " +"& \", \" & [headoffices].[first],[headoffices].[company]) " +"AS headname, wom.details, " +"wom.STARTDATE, wom.STOPDATE, projects.name " +"AS PROJNAME, projects.notes AS PROJNOTES FROM " +"(((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT " +"\"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum " +"AS TRAVPN, probs.notes AS PROBNOTES, probs.brief " +"AS PROBBRIEF, probs.id AS probnum, probs.wolink " +"AS wonum, \"Service: \" & users.first & \" \" & " +"users.last & \" - \" & IIf(labor.hours>0,labor.hours " +"& \" @ \" & Format(rates.rate,\"Currency\") & \" " +"(pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" " +"(\" & labor.nchours & \" no charge)\",\"\") " +"& IIf(labor.travhours>0,\", \" & labor.travhours & \" " +"travel @ \" & Format(travelrates.rate,\"Currency\") " +"& IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" " +"& travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) " +"AS linetotal,labor.details, labor.start AS STARTDATE, " +"labor.stop as STOPDATE FROM users INNER JOIN " +"(rates AS travelrates INNER JOIN (rates INNER JOIN " +"(labor INNER JOIN probs ON labor.link = probs.id) " +"ON rates.id = labor.rate) ON travelrates.id = labor.travrate) " +"ON users.id = labor.tech WHERE (((probs.wolink)=~WOID)) " +"UNION ALL (SELECT \"2\" AS ctype, " +"\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, " +"probs.brief AS PROBBRIEF, probs.id AS probnum, " +" probs.wolink as wonum, \"Parts: \" & IIf(IsNull(woparts.misc),parts.partnumber " +"& \" \" & parts.description " +"& \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") " +"& \" ea.(sn:\" & woparts.sn " +"& \")\",woparts.misc & \": \" & woparts.quantity " +"& \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" " +"& woparts.sn & \")\") AS item, woparts.quantity*woparts.price " +"AS linetotal,\"\" AS details, #03/12/1968# " +"AS STARTDATE, #03/12/1968# AS STOPDATE FROM " +"(probs INNER JOIN woparts ON probs.id = woparts.link) " +"LEFT JOIN parts ON woparts.partnum = parts.id " +"WHERE (((probs.wolink)=~WOID)) UNION ALL (SELECT " +" \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes " +"AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id " +"AS probnum, probs.wolink as wonum, \"Third party " +"service: \" AS item, subrepair.charge AS linettotal, " +"\"\" AS details, #03/12/1968# AS STARTDATE, #03/12/1968# " +"AS STOPDATE FROM probs INNER JOIN subrepair " +"ON probs.id = subrepair.link WHERE (((probs.wolink)=~WOID) " +"AND ((subrepair.charge)<>0))))]. AS " +"wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN " +"clients ON wo.client = clients.id) LEFT JOIN clients " +"AS headoffices ON clients.headoffice = headoffices.id) " +"ON probs.id = wom.probnum) ON units.id = probs.unit) " +"LEFT JOIN unitmodels ON units.model = unitmodels.id) " +"LEFT JOIN nonclients ON unitmodels.manufacturer " +"= nonclients.id) LEFT JOIN projects ON " +"wo.project = projects.id ORDER BY wom.STARTDATE DESC; "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=1));",q2); + rs->Ex(q); + + //------------------------------------------------ + + //STANDARD COMPLETED + q2="SELECT \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) " +"& \"Unit: \" & [nonclients].[company_person] " +"& \" \" & [unitmodels].[description] " +"& \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") " +"AS probheader, \"~REGTO\" AS compname, wom.probnum, " +"wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, " +"wom.PROBBRIEF, wom.item, wom.linetotal, " +"wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created " +"AS wodate, wo.id AS wonumber, wo.invoice, " +"wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, " +"clients.billheadoffice, clients.first, clients.last, " +"clients.mailaddress, clients.streetaddress, " +"clients.city, clients.stateprov, clients.postal, " +"clients.country, clients.bizphone, clients.extension, " +"clients.fax, clients.email, [clients].[company] " +"AS clientname, IIf(IsNull([headoffices].[company]),[headoffices].[last] " +"& \", \" & [headoffices].[first],[headoffices].[company]) " +"AS headname, wom.details, " +"wom.STARTDATE, wom.STOPDATE, projects.name " +"AS PROJNAME, projects.notes AS PROJNOTES FROM " +"(((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT " +"\"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum " +"AS TRAVPN, probs.notes AS PROBNOTES, probs.brief " +"AS PROBBRIEF, probs.id AS probnum, probs.wolink " +"AS wonum, \"Service: \" & users.first & \" \" & " +"users.last & \" - \" & IIf(labor.hours>0,labor.hours " +"& \" @ \" & Format(rates.rate,\"Currency\") & \" " +"(pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" " +"(\" & labor.nchours & \" no charge)\",\"\") " +"& IIf(labor.travhours>0,\", \" & labor.travhours & \" " +"travel @ \" & Format(travelrates.rate,\"Currency\") " +"& IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" " +"& travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) " +"AS linetotal,labor.details, labor.start AS STARTDATE, " +"labor.stop as STOPDATE FROM users INNER JOIN " +"(rates AS travelrates INNER JOIN (rates INNER JOIN " +"(labor INNER JOIN probs ON labor.link = probs.id) " +"ON rates.id = labor.rate) ON travelrates.id = labor.travrate) " +"ON users.id = labor.tech WHERE (((probs.wolink)=~WOID)) " +"UNION ALL (SELECT \"2\" AS ctype, " +"\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, " +"probs.brief AS PROBBRIEF, probs.id AS probnum, " +" probs.wolink as wonum, \"Parts: \" & IIf(IsNull(woparts.misc),parts.partnumber " +"& \" \" & parts.description " +"& \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") " +"& \" ea.(sn:\" & woparts.sn " +"& \")\",woparts.misc & \": \" & woparts.quantity " +"& \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" " +"& woparts.sn & \")\") AS item, woparts.quantity*woparts.price " +"AS linetotal,\"\" AS details, #03/12/1968# " +"AS STARTDATE, #03/12/1968# AS STOPDATE FROM " +"(probs INNER JOIN woparts ON probs.id = woparts.link) " +"LEFT JOIN parts ON woparts.partnum = parts.id " +"WHERE (((probs.wolink)=~WOID)) UNION ALL (SELECT " +" \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes " +"AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id " +"AS probnum, probs.wolink as wonum, \"Third party " +"service: \" AS item, subrepair.charge AS linettotal, " +"\"\" AS details, #03/12/1968# AS STARTDATE, #03/12/1968# " +"AS STOPDATE FROM probs INNER JOIN subrepair " +"ON probs.id = subrepair.link WHERE (((probs.wolink)=~WOID) " +"AND ((subrepair.charge)<>0))))]. AS " +"wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN " +"clients ON wo.client = clients.id) LEFT JOIN clients " +"AS headoffices ON clients.headoffice = headoffices.id) " +"ON probs.id = wom.probnum) ON units.id = probs.unit) " +"LEFT JOIN unitmodels ON units.model = unitmodels.id) " +"LEFT JOIN nonclients ON unitmodels.manufacturer " +"= nonclients.id) LEFT JOIN projects ON " +"wo.project = projects.id ORDER BY wom.STARTDATE DESC; "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=19));",q2); + rs->Ex(q); + //------------------------------------------------ + + //WORKORDERS BRIEF + q2="SELECT ~CRITERIA AS CRITERIA, wo.id AS wonumber, \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) & \"Unit: \" & [nonclients].[company_person] & \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") AS probheader, \"test\" AS compname, wom.probnum, wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, wom.PROBBRIEF, wom.item, wom.linetotal, wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created AS wodate, wo.invoice, wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, clients.bizphone, clients.extension, clients.fax, clients.email, clients.company AS clientname, wom.details, wom.START, wom.STOP,wom.REGHOURS, wom.TRAVHOURS, wom.NCHOURS, projects.name AS PROJNAME, projects.notes AS PROJNOTES, wo.client, wo.project, wo.type, wotypes.category AS CATEGORY " + "FROM ((((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT \"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink AS wonum, \"Service: \" & users.first & \" \" & users.last & \" - \" & IIf(labor.hours>0,labor.hours & \" @ \" & Format(rates.rate,\"Currency\") & \" (pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" (\" & labor.nchours & \" no charge)\",\"\") & IIf(labor.travhours>0,\", \" & labor.travhours & \" travel @ \" & Format(travelrates.rate,\"Currency\") & IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" & travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) AS linetotal, labor.details , labor.start AS START, labor.stop AS STOP, labor.hours AS REGHOURS, labor.travhours AS TRAVHOURS, labor.nchours as NCHOURS FROM users INNER JOIN (rates AS travelrates INNER JOIN (rates INNER JOIN (labor INNER JOIN probs ON labor.link = probs.id) ON rates.id = labor.rate) ON travelrates.id = labor.travrate) ON users.id = labor.tech WHERE (((probs.wolink)<>0)) " + "UNION ALL (SELECT \"2\" AS ctype, \"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Parts: \" & IIf(woparts.misc= \"\",parts.partnumber & \" \" & parts.description & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") & \" ea.(sn:\" & woparts.sn & \")\",woparts.misc & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" & woparts.sn & \")\") AS item, woparts.quantity*woparts.price AS linetotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM (probs INNER JOIN woparts ON probs.id = woparts.link) " + "LEFT JOIN parts ON woparts.partnum = parts.id WHERE (((probs.wolink)<>0)) " + "UNION ALL (SELECT \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Third party service: \" AS item, subrepair.charge AS linettotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM probs INNER JOIN subrepair ON probs.id = subrepair.link WHERE (((probs.wolink)<>0) AND ((subrepair.charge)<>0))))]. AS wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN clients AS headoffices ON clients.headoffice = headoffices.id) ON probs.id = wom.probnum) ON units.id = probs.unit) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) LEFT JOIN projects ON wo.project = projects.id ) LEFT JOIN wotypes ON wo.type = wotypes.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_)) " + "ORDER BY wo.id;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=32));",q2); + rs->Ex(q); + + //WORKORDERS DETAILED + + + q2="SELECT ~CRITERIA AS CRITERIA, wo.id AS wonumber, \"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) & \"Unit: \" & [nonclients].[company_person] & \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") AS probheader, \"test\" AS compname, wom.probnum, wom.ctype, wom.LABPN, wom.TRAVPN, wom.PROBNOTES, wom.PROBBRIEF, wom.item, wom.linetotal, wo.clientrefnum, wo.clientcontact, wo.ourref, wo.created AS wodate, wo.invoice, wo.notes, wo.prob_reported, wo.prob_found, wo.action_taken, clients.bizphone, clients.extension, clients.fax, clients.email, clients.company AS clientname, wom.details, wom.START, wom.STOP,wom.REGHOURS, wom.TRAVHOURS, wom.NCHOURS, projects.name AS PROJNAME, projects.notes AS PROJNOTES, wo.client, wo.project, wo.type, wotypes.category AS CATEGORY " + "FROM ((((units RIGHT JOIN (probs RIGHT JOIN ((([SELECT \"1\" AS ctype, rates.partnum AS LABPN, travelrates.partnum AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink AS wonum, \"Service: \" & users.first & \" \" & users.last & \" - \" & IIf(labor.hours>0,labor.hours & \" @ \" & Format(rates.rate,\"Currency\") & \" (pn:\" & rates.partnum & \")\",\"\") & IIf(labor.nchours>0,\" (\" & labor.nchours & \" no charge)\",\"\") & IIf(labor.travhours>0,\", \" & labor.travhours & \" travel @ \" & Format(travelrates.rate,\"Currency\") & IIf(IsNull(travelrates.partnum),\"\",\" (pn:\" & travelrates.partnum & \")\"),\"\") AS item, (labor.hours*rates.rate)+(labor.travhours*travelrates.rate) AS linetotal, labor.details , labor.start AS START, labor.stop AS STOP, labor.hours AS REGHOURS, labor.travhours AS TRAVHOURS, labor.nchours as NCHOURS FROM users INNER JOIN (rates AS travelrates INNER JOIN (rates INNER JOIN (labor INNER JOIN probs ON labor.link = probs.id) ON rates.id = labor.rate) ON travelrates.id = labor.travrate) ON users.id = labor.tech WHERE (((probs.wolink)<>0)) " + " UNION ALL (SELECT \"2\" AS ctype, \"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Parts: \" & IIf(IsNull(woparts.misc), parts.partnumber & \" \" & parts.description & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\") & \" ea.(sn:\" & woparts.sn & \")\",woparts.misc & \": \" & woparts.quantity & \" @ \" & Format(woparts.price,\"Currency\")& \" ea.(sn:\" & woparts.sn & \")\") AS item, woparts.quantity*woparts.price AS linetotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM (probs INNER JOIN woparts ON probs.id = woparts.link) " + " LEFT JOIN parts ON woparts.partnum = parts.id WHERE (((probs.wolink)<>0)) " + "UNION ALL (SELECT \"3\" AS ctype,\"na\" AS LABPN, \"na\" AS TRAVPN, probs.notes AS PROBNOTES, probs.brief AS PROBBRIEF, probs.id AS probnum, probs.wolink as wonum, \"Third party service: \" AS item, subrepair.charge AS linettotal, \"\" AS details, #03/12/1968# AS START, #03/12/1968# AS STOP, 0 AS REGHOURS, 0 AS TRAVHOURS, 0 as NCHOURS FROM probs INNER JOIN subrepair ON probs.id = subrepair.link WHERE (((probs.wolink)<>0) AND ((subrepair.charge)<>0))))]. AS wom LEFT JOIN wo ON wom.wonum = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN clients AS headoffices ON clients.headoffice = headoffices.id) ON probs.id = wom.probnum) ON units.id = probs.unit) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) LEFT JOIN projects ON wo.project = projects.id ) LEFT JOIN wotypes ON wo.type = wotypes.id " + "WHERE (((wo.created) Between #~STRT# And #~END_#) AND ((wo.client)~CUST) AND ((wo.project)~PROJ) AND ((wo.type)~CAT_)) " + "ORDER BY wo.id;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=31));",q2); + rs->Ex(q); + + + //=-=-=-=- PM by UNIT bug fix + q2="SELECT ~CRITERIA AS CRITERIA, pmhead.id, nonclients.company_person " +"AS MAKE, unitmodels.model, units.sn, " +"unitmodels.description AS UNITDESC, units.id1, " +"units.id2, units.id3, clients.company, nonclients.phone, " +"pmhead.description, pmhead.notes, Min(pmitems.schedate) " +"AS nextsrvdate, Min(pmitems.schedmeter) " +"AS nextsrvmeter, units.lastmeter, pmhead.woconvert, " +"pmhead.repeatevery AS rptmonths_count, pmhead.rptweeks, " +"pmhead.rptdays, units.purchasedate, pmhead.ageyears, " +"pmhead.agemonths, users.initials, users.first, " +"users.last, pmhead.isclient FROM pmitems " +"RIGHT JOIN (((pmhead LEFT JOIN ((units LEFT JOIN " +"unitmodels ON units.model = unitmodels.id) LEFT JOIN " +"nonclients ON unitmodels.manufacturer = nonclients.id) " +"ON pmhead.link = units.id) LEFT JOIN clients " +"ON units.client = clients.id) LEFT JOIN users " +"ON pmhead.tech = users.id) ON pmitems.pmschedlink " +"= pmhead.id GROUP BY ~CRITERIA , pmhead.id, nonclients.company_person, " +"unitmodels.model, units.sn, unitmodels.description, " +"units.id1, units.id2, units.id3, " +"clients.company, nonclients.phone, pmhead.description, " +"pmhead.notes, units.lastmeter, pmhead.woconvert, " +"pmhead.repeatevery, pmhead.rptweeks, pmhead.rptdays, " +"units.purchasedate, pmhead.ageyears, " +"pmhead.agemonths, users.initials, users.first, users.last, " +"pmhead.isclient, units.client, units.id, " +"units.model HAVING (((pmhead.isclient)=False) AND " +"((units.client)~CUST) AND ((units.id)~UNIT) AND ((units.model)~MODL)) " +"ORDER BY nonclients.company_person, " +"unitmodels.model, units.sn, clients.company;"; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=34));",q2); + rs->Ex(q); + //------------------------------------------------ + + //--------------------------------------- + //P.M. by client bug fix + + q2="SELECT ~CRITERIA AS CRITERIA, [clients].[company], " +"[pmhead].[description], [pmhead].[notes], Min([pmitems].[schedate]) " +"AS nextsrvdate, [pmhead].[link] " +"AS CLIENTID, [pmhead].[woconvert], [pmhead].[repeatevery] " +"AS rptmonths_count, [pmhead].[rptweeks], [pmhead].[rptdays], " +"[pmhead].[ageyears], [pmhead].[agemonths], " +"[users].[initials], [users].[first] AS " +"TECH_FIRST, [users].[last] AS TECH_LAST FROM pmitems " +"RIGHT JOIN (clients RIGHT JOIN (pmhead LEFT JOIN " +"users ON [pmhead].[tech]=[users].[id]) ON [clients].[id]=[pmhead].[link]) " +"ON [pmitems].[pmschedlink]=[pmhead].[id] " +"GROUP BY ~CRITERIA, [clients].[company], " +"[pmhead].[description], [pmhead].[notes], " +"[pmhead].[link], [pmhead].[woconvert], [pmhead].[repeatevery], " +"[pmhead].[rptweeks], [pmhead].[rptdays], " +"[pmhead].[ageyears], [pmhead].[agemonths], [users].[initials], " +"[users].[first], [users].[last], " +"[pmhead].[isclient] HAVING (((Min(pmitems.schedate)) " +"Between #~STRT# And #~END_#) AND ((pmhead.link)~CUST) " +"AND ((pmhead.isclient)=True)) ORDER BY [clients].[company]; "; + + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=35));",q2); + rs->Ex(q); + //------------------------------------------------ + + + + CString strID,strName,strRights,strHash; + long lData; + GZK k; + + + //Add new ARAS REQUEST right: + //loop through all the group records + rs->Query("SELECT groups.* FROM groups;"); + do{ + rs->FetchField("id",&lData); + rs->FetchField("a",&strName); + rs->FetchField("b",&strRights); + + //decrypt the original rights string + k.GZDecrypt(&strRights,false); + strRights=strRights+"1";//add on the extra right for schedule view + + //re-'crypt' + k.GZEncrypt(&strRights,false); + + //HASH + strHash.Format("%u%s%s",lData,strName,strRights); + k.GZHash(&strHash); + + //save the rights + rs->UpdateField("b",&strRights); + + //save the hash + rs->UpdateField("c",&strHash); + + //save the record + if(!rs->SaveRecord()) + AfxMessageBox("Error trying to save rights record"); + }while(rs->MoveForward()); + + + //Remove any bogus sub-repair records that were created by ARAS with a "where" set to zero + //change has already been made in ARAS 2.9.3 that will prevent them from being created in future + rs->Ex("DELETE subrepair.*, subrepair.where FROM subrepair WHERE (((subrepair.where)=0));"); + + //remove any blank customer service requests + rs->Ex("DELETE client_requests.workorderid, client_requests.request, " +"client_requests.probdetails, client_requests.refnum, " +"client_requests.requestor_id, client_requests.* " +"FROM client_requests WHERE (((client_requests.workorderid)=0) " +"AND ((client_requests.request) " +"Is Null) AND ((client_requests.probdetails) Is " +"Null) AND ((client_requests.refnum) Is Null)); "); + + + //Add the UNIT id to the ARAS requests table + //Add aras_client field to rptsmaster + rs->Ex("ALTER TABLE client_requests ADD COLUMN unitid INTEGER;"); + rs->Ex("ALTER TABLE client_requests ALTER unitid SET DEFAULT '0';"); + rs->Ex("UPDATE client_requests SET client_requests.unitid = 0;"); + + + //add a field to defaults to control what client sees in ARAS workorder screen + rs->Ex("ALTER TABLE defaults ADD COLUMN limit_client_aras YESNO;"); + rs->Ex("UPDATE defaults SET defaults.limit_client_aras = False;"); + + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"170\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.4.0\";"); + nVersion=170; + //buptodate=true;//<<==========CRITICAL!!!!!, should be at end of last case statement only + break; + + } + case 170: + { //v1.9.4.4 changes + + //Fix client address book report criteria fields + rs->Ex("UPDATE rptsmaster SET rptsmaster.criteriafields = 129 " + "WHERE (((rptsmaster.id)=41));"); + + //Fix technician billing summary report criteria fields + rs->Ex("UPDATE rptsmaster SET rptsmaster.criteriafields = 911 " + "WHERE (((rptsmaster.id)=17));"); + + rs->Ex("UPDATE wo SET wo.modified = [wo].[created], wo.modifier " + "= [wo].[creator] WHERE (((wo.modified) Is Null)); "); +/* + q2="SELECT clients.*, HEADS.* FROM clients LEFT JOIN clients " + "AS HEADS ON clients.headoffice = HEADS.id WHERE " + "(((clients.id)~CUST)) ORDER BY clients.company; "; + + q.Format("UPDATE rptsmaster SET rptsmaster.query = '%s' " + "WHERE (((rptsmaster.id)=41));",q2); + rs->Ex(q); + + + //Set STATUS column in statusviews to -1 if it was previously 1 as -1 + //now means any status where 1 used to mean any status + q.Format("UPDATE statusviews SET statusviews.status = -1 WHERE (((statusviews.status)=1));"); + rs->Ex(q); + + + //10/26/2002 + //set assigntech to correct value on old quick work orders + q="UPDATE labor RIGHT JOIN (probs RIGHT JOIN wo ON probs.wolink = wo.id) " + "ON labor.link = probs.id SET wo.assigntech = [labor].[tech] " + "WHERE (((wo.quick)=True) AND ((wo.assigntech)=-1));"; + rs->Ex(q); + + +*/ + + //fix the version number up + rs->Ex("UPDATE defaults SET defaults.versioninfo = \"171\";"); + rs->Ex("UPDATE defaults SET defaults.min_exe = \"1.9.4.0\";"); + nVersion=171; + buptodate=true;//<<==========CRITICAL!!!!!, should be at end of last case statement only + break; + + } + //<--------Insert new version before here -------------------- + + + default: + { + msg.Format( + "Your database version was not recognized and can not be updated automatically\r\n" + "Please email support@ayanova.com immediately with this version number: %i\r\n",nVersion); + AfxMessageBox(msg); + return; + } + break; + } + +}//while not buptodate +rs->Close(); +AfxMessageBox("You should close and re-start AyaNova now\r\n\r\n OR \r\n\r\n" + "follow any instructions given during the update\r\n" + "as directed before restarting"); +} + + + + + + + +//Used when checking PM items for conversion to workorder +//duplicate of item in pmcheckdlg + +void CDBUtils::MakeIntoWorkorder(CString strPMItem) +{ + + CString q,strDescription,strNotes; + long lHeaderID,lTech,lLink,lClient,lModifier,lCategory,lProject,lWOID,lProbID; + long lSchedMeter,lHighestPMID,lRepeat,lDays,lWeeks,lDOW; + bool bIsClient,bQuick,bOnsite,bAutorpt,bAutoWO, bHold; + int nDOW,d,nTemp; + COleDateTime dtScheduled,dtNow,dtDefault,dtStartTime,dtEndTime,dtSchedStart,dtSchedStop; + dtDefault.SetDate(1968,03,12); + + + + dtNow=COleDateTime::GetCurrentTime(); + //Get all the details from the detail record first + q.Format("SELECT * " + "FROM pmitems WHERE (((pmitems.id)=%s));",strPMItem); + rs2->QueryReadOnly(q); + if(rs2->IsEmpty()) + { + q.Format("Error converting PM Item %s to workorder",strPMItem); + AfxMessageBox(q); + rs2->Close(); + rs3->Close(); + return; + } + rs2->FetchField("pmschedlink",&lHeaderID); + rs2->FetchField("schedtech",&lTech); + rs2->FetchField("link",&lLink); + rs2->FetchField("isclient",&bIsClient); + rs2->FetchField("clientlink",&lClient); + rs2->FetchField("schedmeter",&lSchedMeter); + rs2->FetchField("schedate",&dtScheduled); + rs2->FetchField("autowo",&bAutoWO); + rs2->FetchField("hold",&bHold); + + /*PMDAYS*/ + //Get the rest of the info from the header record + q.Format("SELECT pmhead.description, pmhead.notes, pmhead.modifier, pmhead.autorpt, pmhead.dow, " + "pmhead.repeatevery,pmhead.rptdays, pmhead.rptweeks, pmhead.series, pmhead.wotype, pmhead.woquick, " + "pmhead.woproject, pmhead.woonsite, pmhead.starttime, pmhead.endtime " + "FROM pmhead WHERE (((pmhead.id)=%u));",lHeaderID); + rs2->QueryReadOnly(q); + if(rs2->IsEmpty()) + { + q.Format("Error converting PM head item %u to workorder",lHeaderID); + AfxMessageBox(q); + rs2->Close(); + rs3->Close(); + return; + } + + rs2->FetchField("description",&strDescription); + rs2->FetchField("notes",&strNotes); + rs2->FetchField("modifier",&lModifier); + rs2->FetchField("wotype",&lCategory); + rs2->FetchField("woquick",&bQuick); + rs2->FetchField("woproject",&lProject); + rs2->FetchField("woonsite",&bOnsite); + rs2->FetchField("autorpt",&bAutorpt); + rs2->FetchField("dow",&lDOW); + rs2->FetchField("repeatevery",&lRepeat); + rs2->FetchField("rptdays",&lDays); + rs2->FetchField("rptweeks",&lWeeks); + rs2->FetchField("starttime",&dtStartTime); + rs2->FetchField("endtime",&dtEndTime); + + //Move the date into the time fields + dtSchedStart.SetDateTime(dtScheduled.GetYear(),dtScheduled.GetMonth(),dtScheduled.GetDay(), + dtStartTime.GetHour(),dtStartTime.GetMinute(),dtStartTime.GetSecond()); + + // dtSchedStop + dtSchedStop.SetDateTime(dtScheduled.GetYear(),dtScheduled.GetMonth(),dtScheduled.GetDay(), + dtEndTime.GetHour(),dtEndTime.GetMinute(),dtEndTime.GetSecond()); + + + //FIXUP DATE + if(dtScheduled.GetYear()==1968) + dtScheduled=COleDateTime::GetCurrentTime(); + + + //PROCESS INTO A WORKORDER + //modified Feb 20 2001 to create as open, not closed + q.Format("INSERT INTO wo ( " + "project, client, type, closed, onsite, " + "anytime, assigntech, quick, creator, modifier, created, modified, " + "starttime, stoptime, notes, pmid ) " + "SELECT %u, %u, %u, #%s#, %s, %s, %u, %s, %u, %u, " + "#%s#, #%s#, #%s#, #%s#, \"%s\",%u;", + lProject, lClient, lCategory, bQuick ? dtScheduled.Format(_T("%m/%d/%Y %H:%M:%S")) : "03/12/1968", + bOnsite ? "True" : "False", "False", + lTech, bQuick ? "True" : "False", lModifier, lModifier, + dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), + /*starttime*/dtSchedStart.Format(_T("%m/%d/%Y %H:%M:%S")), + /*stoptime*/dtSchedStop.Format(_T("%m/%d/%Y %H:%M:%S")), + strDescription,lHeaderID); + + ///////m_pApp->ShowStuff(q); + + rs2->Ex(q,&lWOID);//modified Nov 5th [some year] + rs2->Close();//flush it..flush it.....flush it reeeal good + //Create a companion problem record + if(bQuick) + q.Format("INSERT INTO probs ( wolink, creator, created, pmscheduleid ) " + "SELECT %u, %u, #%s#, %u;", lWOID, lModifier, dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), lHeaderID); + else + q.Format("INSERT INTO probs ( " + "wolink, creator, created, brief, notes, pmscheduleid, unit ) " + "SELECT %u, %u, #%s#, \"%s\", \"%s\", %u, %u;", + lWOID, lModifier, dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), strDescription, + strNotes, lHeaderID, bIsClient ? 0 : lLink) ;//if client 0 else link=unit + + rs2->Ex(q,&lProbID); + rs2->Close(); + + //QUICK WORKORDER: CREATE A LABOUR RECORD + if(bQuick) + { + + //v1.9.4.4 get and set default client rates + //various changes in this block + long lDefRate=0; + long lDefTravelRate=0; + + q.Format("SELECT clients.defrate, clients.deftravelrate FROM " + "clients WHERE (((clients.id)=%u));",lClient); + rs3->QueryReadOnly(q); + if(!rs3->IsEmpty()) + { + rs3->FetchField("defrate",&lDefRate); + rs3->FetchField("deftravelrate",&lDefTravelRate); + + } + rs3->Close(); + + + q.Format("INSERT INTO labor ( link, tech, rate, travrate, start, stop, details ) " + "SELECT %u, %u,%u, %u, #%s#, #%s#, \"%s\";",lProbID,lTech,lDefRate,lDefTravelRate, + dtScheduled.Format(_T("%m/%d/%Y")),dtScheduled.Format(_T("%m/%d/%Y")), + strDescription + "\r\n" + strNotes+"\r\n----------\r\n"); + rs2->Ex(q); + rs2->Close(); + //v1.9.4.4 end of changes in this block + } + + //STANDARD WORKORDER: CHECK FOR PARTS AND CREATE WOPARTS RECORDS AS NECESSARY + if(!bQuick) + { + q.Format("SELECT pmparts.pmlink, pmparts.partnum, pmparts.quantity, parts.retail, parts.avgcost " + "FROM pmparts LEFT JOIN parts ON pmparts.partnum = parts.id " + "WHERE (((pmparts.pmlink)=%u));",lHeaderID); + + rs2->QueryReadOnly(q); + + if(!rs2->IsEmpty()) + { + COleCurrency crData; + COleCurrency crCost; + CgzCurrencyFormatter cfm; + long lPartID; + float fQuant; + //CREATE PARTS RECORDS UNTIL NO MORE + do { + rs2->FetchField("partnum",&lPartID); + rs2->FetchField("quantity",&fQuant); + rs2->FetchField("retail",&crData); + rs2->FetchField("avgcost",&crCost); + q.Format("INSERT INTO woparts ( " + "link, partnum, quantity, price, cost, usedby, misc ) " + "SELECT %u, %u, %f, '%s', '%s', %u, Null;",lProbID,lPartID,fQuant,cfm.Format(crData), + cfm.Format(crCost),lTech); + rs3->Ex(q); + rs3->Close(); + + + }while(rs2->MoveForward()); + + } + + + } + + + + + + + //RESCHEDULE TO REPLACE CONVERTED ITEM OR DELETE IF NOT RECURRING + if(!bAutorpt) + { + //Remove PM ITEM here if not recurring, else just change date/meter count: + q.Format("DELETE pmitems.* FROM pmitems WHERE pmitems.id=%s;",strPMItem); + rs2->Ex(q); + } + else + {//increment this record. + + //Find out which record is the highest + q.Format("SELECT TOP 1 pmitems.id " + "FROM pmitems " + "WHERE (((pmitems.pmschedlink)=%u) AND ((pmitems.link)=%u)) " + "ORDER BY pmitems.id DESC;",lHeaderID,lLink); + rs2->QueryReadOnly(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("Error: Can't locate the highest pmschedule for rescheduling.\r\n Contact tech support with the details."); + rs2->Close(); + rs3->Close(); + return; + } + rs2->FetchField("id",&lHighestPMID); + + + + //ASCERTAIN THE HIGHEST RECORD + if(lHighestPMID!=atol(strPMItem))//are were already at the highest to convert to workorder? + {//if no: load in the highest records meter and or date data for processing + q.Format("SELECT pmitems.schedate, pmitems.schedmeter FROM pmitems " + "WHERE (((pmitems.id)=%u));",lHighestPMID); + rs2->QueryReadOnly(q); + + if(rs2->IsEmpty()) + { + AfxMessageBox("Error: Can't open the highest pmschedule for rescheduling.\r\n Contact tech support with the details."); + rs2->Close(); + rs3->Close(); + return; + } + + rs2->FetchField("schedmeter",&lSchedMeter); + rs2->FetchField("schedate",&dtScheduled); + + + //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + //INCREMENT DATE OR METER DEPENDING + + if(dtScheduled.GetYear()==1968)//it's meter based + { + //Process as a meter based record + //this one's easy: + lSchedMeter+=lRepeat; + } + else //calculate next date based pmitem record + { + //prepare a simpledate class object + CSimpleDate sdTemp(dtScheduled.GetMonth(),dtScheduled.GetDay(),dtScheduled.GetYear()); + + + //Add the months, then increment to the right + //day of week if necessary. + sdTemp.AddDays(lDays); + sdTemp.AddDays(lWeeks*7); + sdTemp.AddMonths(lRepeat); + + //******************************************************************* + //ADD DAYS HERE + //******************************************************************* + + //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 + + nDOW=(int)lDOW; + 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(); + + + } + } + + + //set dtTemp back again. + + dtScheduled.SetDate(sdTemp.GetYear(),sdTemp.GetMonth(),sdTemp.GetDay()); + + } + + //<<<<<<<<<<<<<<<<<<<<< + //OK, at this point we have incremented either the date + //or the meter reading and can now insert the replacement record + //and then delete the old record + //done this way rather than updating existing record because were + //relying on a higher id value to indicate the farthest "flung" scheduled item + q.Format("INSERT INTO pmitems ( " + "pmschedlink, schedate, schedmeter, autowo, hold, schedtech, " + "link, isclient, clientlink) " + "SELECT %u, #%s#, %u, %s, %s, %u, %u, %s, %u;", + lHeaderID, dtScheduled.Format(_T("%m/%d/%Y")), lSchedMeter, bAutoWO ? "True" : "False", + bHold ? "True" : "False", lTech, lLink, bIsClient ? "True" : "False", + lClient); + rs2->Ex(q); + rs2->Close(); + + q.Format("DELETE pmitems.* FROM pmitems WHERE pmitems.id=%s;",strPMItem); + rs2->Ex(q); + rs2->Close(); + + + //ADDED 09/05/2001 to fix motorola "problem" + //update nextsrvdate to = next scheduled item + //first fetch the date / meter + q.Format("SELECT TOP 1 pmitems.id, pmitems.schedate, pmitems.schedmeter " + "FROM pmitems " + "WHERE (((pmitems.pmschedlink)=%u)) " + "ORDER BY pmitems.id;",lHeaderID); + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty()) + { + rs2->FetchField("schedate",&dtScheduled); + rs2->FetchField("schedmeter",&lSchedMeter); + rs2->Close(); + q.Format("UPDATE pmhead SET pmhead.nextsrvdate = #%s#, " + "pmhead.nextsrvmeter = %u WHERE (((pmhead.id)=%u));", + dtScheduled.Format(_T("%m/%d/%Y")), lSchedMeter,lHeaderID); + rs2->Ex(q); + + + + } + + } + } + rs2->Close(); + rs3->Close(); +} + + +//BootScan +//cool name eh? +//Check for any maintenance items that need to be done +void CDBUtils::BootScan() +{ +#ifdef _WTF_ + AfxMessageBox("Entering bootscan"); +#endif + + COleDateTime dtTemp,dtNow,dtMaint,dtDefault; + CString q,strMsg; + bool bFirstBoot; + long lPMItem; + CString strPMItem; + dtDefault.SetDate(1968,03,12); + m_bBootScanDone=true; + + + + //================================================== + //************************************************** + //Check to ensure that there is rates and one client + //warn user if not so that we avoid service call + //about error when creating workorder + + strMsg.Empty(); + + //SEE if any clients: + rs->QueryReadOnly("SELECT clients.id FROM clients;"); + if(rs->IsEmpty()) + strMsg+="CLIENTS\r\n(from main menu take Options->Edit->Clients).\r\n\r\n"; + + //SEE if any TECHS: + rs->QueryReadOnly("SELECT users.id, users.tech FROM users WHERE (((users.id)<>1) AND ((users.tech)=True));"); + if(rs->IsEmpty()) + strMsg+="TECHS\r\n(from main menu take Options->Edit->Users & Rights).\r\n\r\n"; + + //SEE if any ZONES: + rs->QueryReadOnly("SELECT * FROM zones;"); + if(rs->IsEmpty()) + strMsg+="ZONES (even if you don't plan to use them).\r\n(from main menu take Options->Edit->Zones).\r\n\r\n"; + + + //SEE if any regular rates + rs->QueryReadOnly("SELECT rates.id FROM rates WHERE (((rates.travelrate)=False));"); + if(rs->IsEmpty()) + strMsg+="SERVICE RATES\r\n(from main menu take Options->Edit->Rates).\r\n\r\n"; + + //SEE if any travel rates + rs->QueryReadOnly("SELECT rates.id FROM rates WHERE (((rates.travelrate)=True));"); + if(rs->IsEmpty()) + strMsg+="TRAVEL RATES (even if you don't plan to use them).\r\n" + "(from main menu take Options->Edit->Rates).\r\n\r\n"; + + + + + if(strMsg.GetLength() > 1) + { + strMsg="You must now enter at least one of each of the following...\r\n\r\n" + + strMsg + "\r\nYou should do this now before you enter any workorders\r\n" + "or serious errors and other problems could result."; + AfxMessageBox(strMsg); + } + //************************************************** + //================================================== + + + + //See if maint has been done already + dtNow=COleDateTime::GetCurrentTime(); + + rs->QueryReadOnly("SELECT defaults.lastmaintdate, defaults.firstboot FROM defaults;"); + rs->FetchField("firstboot",&bFirstBoot); + //moved below to avoid delay between check and snagging it + //rs->FetchField("lastmaintdate",&dtMaint); + + //SEE IF THIS IS A NEW EVAL VERSION + //IS registered? + if(m_pApp->m_uiFeatures&LICENSE_REGISTERED) + ;//Yes this is supposed to be here + else + { + //Is first boot? + if(bFirstBoot) + { + WelcomeToSC(); + rs->Close(); + return; + } + + } + +#ifdef AYQB//process no further if this is the QBI version + rs->Close(); + return; +#endif + //#ifndef _DEBUG + rs->FetchField("lastmaintdate",&dtMaint); + //Snag the maintenance job... + //done here regardless because it means less time between read and write + //and won't affect things anyway + q.Format("UPDATE defaults SET defaults.lastmaintdate = #%s#;",dtNow.Format(_T("%m/%d/%Y"))); + rs->Ex(q); + rs->Close(); + + if(dtMaint.GetDayOfYear()==dtNow.GetDayOfYear())//same day? + return; + + //#endif + + + + //CONVERT ALL THAT'S DUE FOR CONVERTIN' + + //DO DATE ITEMS FIRST + q.Format("SELECT pmitems.id " + "FROM pmitems INNER JOIN pmhead ON pmitems.pmschedlink = pmhead.id " + "WHERE (((pmitems.schedate)>#%s#) AND ((DateDiff(\"d\",Now(),[schedate]))<[woconvert]) AND ((pmitems.hold)=False));",dtDefault.Format(_T("%m/%d/%Y"))); + //=======-=-=-=-=-=-=-=-=-= +#ifdef _DEBUG + // m_pApp->ShowStuff(q); +#endif + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do { + rs->FetchField("id",&lPMItem); + strPMItem.Format("%u",lPMItem); + MakeIntoWorkorder(strPMItem); + + } while(rs->MoveForward()); + + } + + + //DO METRIC ITEMS + q.Format("SELECT pmitems.id " + "FROM (pmitems INNER JOIN pmhead ON pmitems.pmschedlink = pmhead.id) INNER JOIN units ON pmitems.link = units.id " + "WHERE (((pmitems.schedate)=#%s#) AND (([schedmeter]-[lastmeter])<=[woconvert]) AND ((pmitems.hold)=False));",dtDefault.Format(_T("%m/%d/%Y"))); +#ifdef _DEBUG + //m_pApp->ShowStuff(q); +#endif + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do { + rs->FetchField("id",&lPMItem); + strPMItem.Format("%u",lPMItem); + MakeIntoWorkorder(strPMItem); + + } while(rs->MoveForward()); + + } + + rs->Close(); + + //POISON PILL - November 21 2001 + //wipes the key for anyone on the list of non-paids + CString strREGKEY,strCOMPARE; + GZK k; + rs->QueryReadOnly("SELECT * FROM defaults;"); + rs->FetchField("key",&strREGKEY); + k.GZDecrypt(&strREGKEY,false); + CStringList sl; + + sl.AddTail("g070YEU+l209n+dfIg+zHStkGe4eZGKtDlwRDL2/C2s7ojhhssX08gYo2wglNo2v"/*"dupjPUa#3kLol#5wMOkc#9#5VwcXz#0#9ajqBqwaZ#5pMNuZuQ"*/);//LELIA PROCTOR + sl.AddTail("50x1+MYBBDbDL/JKwXMWc4v6S3XkSrhF4gUA3kCBwfvzYEd8/kaZN8orJ7IZiQfR"/*"#8#4QZ#0+ahDL#3YEM#6OMjJ#0FbZN#1LIJElkoXkMpYtF#2ynE"*/);//Signature Control Systems + sl.AddTail("n/Ad2lzsaObnea2VYCGk9wWpBXDuHa/D8tNxH681jJ6WuoAGo9tbybcGnenvM3zl"/*"#2+IHm#4UZipapRBcWJMZ/qTuJQvtGGwuuCD#2w+y#8Bb#4g"*/);//Hi-Tech + sl.AddTail("A9HMgGGz/TC2QwJvz3scy+R6mECDZ148xPjhn8nW72KMAanBhMSfZEzzE8rGCDC6"/*"YMWACcaYiMo#0lWpS#0rAy#2#6mmkjjQfRW#3cMDwY#8eN/kA"*/);//WDS victor garcia + sl.AddTail("sAKjGPxOtVpqaAdIv/UlreoxsuA8xynK4MdQkEoi/FxO7TgPhptFkJshx1qFVuTVWwe6SkiMBYSqH6N29S6kEg"/*"#2aPmF#4fEVMKzbu#1iq#5t+QXdf#5xH#7#8HEy#4pfWfcsDuIo"*/);//Bellwether solutions order 362 + sl.AddTail("ArLxjCbQe2oV8rmHQH6+5of5AEVBkVVmei5DthiLc0UZKg2j2r2vKW2uIYz0ZgF5VrWRQZfiGif2QDr5fiGkwg"/*"#7/b#1h#8mml#1fPQ#5UqRMAZB#9HF#8c#6#4zOkkFAEQzRNH#4oo"*/);//Bellwether solutions order 365 + sl.AddTail("IkS9UcBtwxXMbYMI0DdbvLfP3VMRtal0bmbLgpGM7lfa0vjtzaU8wt7/69y+scwiZfrj9EQgf/C2eGQUeFHTGQ"/*"#4Uo/ZS#5tAeFWwhlYtR#1#9#8/otVEamFGiNyeaFgwr#5p#9w"*/);//Vandy enterprises, changed company name to primetime - new key issued + sl.AddTail("y4LL98AnmEYHMMbQ8g3Ut9gxwJnez7o5vauxMPzs/NjxQmtIhX1nPmnC/HImI/TMwnMSBC1TPPXWCBGsiWBMJA"/*"W#2OP#4jDc+hrl#9#2bA+mKWo#6HtoBF#2#7Pvi#4cIIadFAM#0k"*/);//LEXCOM TELECOMMUNICATIONS CO "duplicate order" number 391 feb 20 2002 + + sl.AddTail("3kQQW48GO1nCKwx3tiwCpUKORay8fVKN1iN5E4Z5DMHOwBlKiQtSA2wKFLU/HGlc1Wh4PSva" + "BY48NBt/6OIC5Q");//"Fpbe#7uGcoOp#4fokdBLaFm#1#7JYywOAEeddQMXZkALK#1c"*/);//Mexico Express order#45 placed on Dec 21 2000, refunded on Dec 22, 2000 as duplicate order + + sl.AddTail("lPFqNkJlGrE0vKuChxmCPnZovtQtfYCDpUerSqjebVLWAaR9PPeZNoYenX8ghSFlP5Di3JEB" +"sffmcEGCobHiQw");//"#8s#0#5SlO#2uOnKPgLddGoNn#0og#7hj#5swPVDajUF#9uFqnA "*/);//E/C Vibration & Balancing Service Ltd order#177 placed on June 22 2001, refunded on July 3, 2001 + + + + + +sl.AddTail("JLwQ2p0KX8eRo6ZsJg0KU/NTq7ljyFXcS4dSL9ExsbLmCdkd/tPDFcJXC3OkK4Fj");//*"BXan#9obwoIalinGXF#0yYfsYR+gurwQDRnSyewpJlysM"*/);//Tom Rice order#577 placed on August 2, 2002, refunded October 14, 2002 + +sl.AddTail("7+IZBTNEbf/rNu9Al0Yyckb3FUoi35v1X5LnabFOLoLFFBVgHoRA8fAdPObZFIsNvBF9QRbt" +"AmbhvbRSWfKo6Q");//*"JGjzLMdnVS#0v#4m#7Xmhm#9tcBrOPtHo#7#1Bsmt/JDln#8gs"*/);//Computer Solutions Professionals order#602 placed on August 30, 2002 - purchase order not paid as of October 21 +// +// +// +// +//original keys that have now been replaced ( in legal agreement, they are not to use them) +// +sl.AddTail("3I1eTPbMRvXFUOdCOhAh1DaOf8x5rj3ChF0ygnjhLiAYB3HCXBo7pptxNFdU8ES6kPBUBl3v" +"6DQ8y7H8iYp97Q");//Registered to:[ZFC Consulting] Activation key:[R#9#3zApZIYrBnaUhXjz#3#5#6K+#7OSyBIXbLpUr#3C#3RX#9G#4] + +sl.AddTail("vfatmzeAAyMSfKjx6G17/E0ohDJNXUZt+0VvLL0loPGCT+CPxzES/wjp72veuf54Goxksc49" +"Wl0BuKlRGH/x5Q");//Registered to:[WS Electrical & A/C, Inc.] Activation key:[W#7oKFr#9FQhefdvfPQ#7IUm#3RkBjy#8Y+R#7B#8tafrlMUMA] + +sl.AddTail("8DQ9DHxoDAAhQdFNvhuQ4hcj5ZbYQIME1bIag3eWuytT0Rs3co8bspvHlL5R0eMYbNTFT4zw" +"D3UHx2/UbKswSQ");//WKT Communications [XGILF#0/kBnBx#3#9#1+OXUsy#7ttMkivQkqRaSZme#6Jqg#9E] + +sl.AddTail("/I90xJXJYEHbRHfZuVoLGndWMebuKfUzn2MnyuL1jqa+kWoA0S/k8oEK4a1JSIso");//Registered to:[Wizard Enterprises] Activation key:[WfPPvuL#3mohNMjk#8lGIcOG#3L#1piAqzcAvwvINL+ImOE] + +sl.AddTail("06tvS/2Cz8VMXugkkwtKtzwOPv94V+tShZAWx2BvUqoZ2WLOrehKtv91v+0s3QnTy+Gmd068" +"PFs6wcP3Dc9RSw");//Victor Computer Consultants [aT#0rRQO#0TTES#4AjHRSE#2B#3ASPf#7F#2z#8X#5cIFfgAOH#7c] +sl.AddTail("HYkPpRKvaxj21RZy5koeBsUWxzDlYMRh2Yplulo4Z0pXfcGMCEh+o3HzSjvID/ZzRCVAYOtd" +"UK+1SrlyMXX4WA");//Viablelinks LLC [#0q#2eI#1JumsNlUM#8R#0+qLPfqkvursSfnirRWbq#7HU#5lI] +sl.AddTail("CFXK7+KHUYXMB/WKIHBPnemqClqJCtkDFH7TIFNBKTm7d/nyYh1jRJwh16cBuRZVonGG8uJ+" +"EX2DdKSUvqrtOg");//Version 4 Holdings, LLC [Z#9RFRrbF#5RTz#1#5Oh#8/KKm#8aTjU#1yD#4CbdxHkCdo#0T+#8] + +sl.AddTail("GZzcI+UWVDl3JVvgjYGsd2B28IPNM3vBRDM1UBuTKa2w6H44l/9VRAww6pJEBN7B57sti96G" +"7dfRSMca65K7Ig");//The Digiticians [+cM#2vI#5QM#2DzCnfp+#2MKg+YDrkZHesWJEj#5f#7+TL#7nc] + +sl.AddTail("EIYACI5umM0ViM1lfs/b3ogdJUA1IpToYu8L3PYuggslPEeeYTjidW4YRLO3RRxukgEOJcN9" +"G8U4yTVJNwLH7w");//TekWorks [wqvxuW#7KuyFB#9aqILRWN#9#6KttOJnvecfIf#7b/PEnQss] + +sl.AddTail("8Pscwx1k27gYQpVMqIw24TUiXAON08ysxkKHi3ciRbSEgh3YWsr9YZVpvX959P4N3MFPCrKk" +"B98RarTpx+u68A");//Registered to:[Superior Service]Activation key:[dSXB#8UoZDMrbkN#9ScYcA#4zqvqieQsmyd#9qzR#7JSXBBM] + +sl.AddTail("IOCnO282pFJdawUGbsy8hU6IZh3dm5rn+Mlow8CbbVR7olZyUR8R4zc9WXnBJ7X5pwbn3CJT" +"C2b++EYRhAW3sg");//Superior Service [WHRJLmYGbW#5KeTrAcmSfXwW#9W#0Qa#1vez#3yIZysw/FNE] + +sl.AddTail("cvm73wa3KD7w0mwd/ZyJ0T3ArSnLy9wl/rMRycenNDNJrRx8xcYOxEdjXFlMNaXohDKLgiS0" +"Vjo2OTEMeSrasQ");//Speed Technology Development Limited [nVw#6Tw#6sgS#1WVgzKu#6mCnONJGQZA/MP#2cFVmjdMvWBA] + +sl.AddTail("gss9LXe8/dbpO0QuRhCFKF/fxGqUjyfEEbbFT15O5nIvKHZdnHj2VbcTd7O/D0Zafpp9UCJT" +"3imWER+dlm3YSA");//Speed Technology Development Ltd. [hNK+Lbz#5OYy#7DptsVS/#5N#8KbWzgLerLTtjol#2JztdPA] + +sl.AddTail("sptlwwWO3zVRo3Wzq1KM70P7psCaNrV4oDb7Bel6P7kufjd8tFssfCZiZxSJAjQXR582K660" +"71MmxkElwE9TYA");//Speed Technology Development Ltd. [#9xaSTyanBJLn#1#2kabGaVuO#3PU/XWyhnxOOaVXc#7JII#0] + +sl.AddTail("SiWfJ9qRKNdYgzPWKzjcACBt6ihxZSNWNL5vCOCjamw8xune28gFP8cggo6n8DGy");//Smith Cooper IT Solutions and Services Ltd [XDmAIK/brXnjrZtxWqv/Y#3Erey#4G#6mT#3jKYtpEtqkqQ] + +sl.AddTail("uKKfdtDmx3S+OLVb1Xjv7WaCfYTTjejhIA3yYkWIFPfZcn2sL7xMtAiEhO5Tx175Hg99gSdP" +"yAFD8VWBaXKpuQ");//Registered to:[CREATIVE SIGNWORKS]Activation key:[GlB#6xMSAvy#1Onq#5LfHFrq#3kQ#4a#0Puc#0g#8zmcyoMAQdk] + +sl.AddTail("LjbpdynWb3YEpDSOFXnIbk0zuTo8hEWO/pMssefOcGKoG2oO5MgLmNqODAmp/cI9");//Schwartz Ophthalmic Services, Inc [KPefutFRiRvjhLzpOkpueq//hgXaXIFmBDha+Ia#2FIM] + +sl.AddTail("Ml+x3XEpM6fYllgcRJsNLgmB7mRAYiUQF9zYYGl20t+iyrXGKEga+Bbvm+4Jt+MrWwW8uhHf" +"EI7iBvzRoS8pMQ");//Safe Data, Inc. [c#7RcyjcyKinY#9sEYO#5lSu#8ad/XS#4LtWwPiau#8L#3Kwls] + +sl.AddTail("pM9Zq6F8vA1k1d+JfsIQyFdBOuCbZ4FVmD5lcQ8xmy7lOeawqsVSJ1mdybehBsObZDvQI4wA" +"vPBdy27SZASetw");//Rinnier Development Company [Y#5C#0vquOld#4/pJvgPlKKS#9fkkXbfEsA#3d#0pVfNopskA] + +sl.AddTail("EtnX0Bi1YP97uRN488wRKfcytKV/XfWbgnlwN0x33ZG1NXJTJ/ghPoLSwzSL5Vx6VC+7U9Z4" +"YDXEAsyTainRUQ");//Q Enterprises, Inc. [FHcYu/CIH#2EP/I#6OumEskdTgpBst#2#8R1M+gtgsg#3Mz#0] + +sl.AddTail("xsnQoAXUUzO+f+nCth2xpQgCpVoqSRV8KC8RN+BKxN5xX+W7Lpky637wuYafGxukhZpRRQtH" +"6kGD+egLQ31fIw");//Press Automation, Inc. [#3ZbsmhbFM#9xwr#1F#9Zn#2ahEwkAByTY#5IgD#7#3szJrvM#2A] + +sl.AddTail("nBQAe1IJMO37isUIToWQSwWY84637e20Dr7iaL8e99l+7zFn3yZX4b1Zsk9EYq3gAkVf4E0w" +"pvPT705gNDfa3w");//Premier Beverages Limited [IvkJk#2vv/FzGJiK#4sleHO#2pivbnl/#4#3WS#8ntiVHphVU] + +sl.AddTail("t35LglDBnpOzPAsmaWFzugCxoY6TfP8UU5kWI6ojjbrsm9Olds6M5Ec5I3pdlg8hLbqdCQB6" +"tVMBX7QBuvko2A");//Planet Earth PC [MQgWRDTgxDqkonnyLvB#4BNa#5#0BChj#4p#3IdVWNPldprU] + +sl.AddTail("Cew3LDFVgpBoNmNXP1TiH5Qeg/iqQ93381FnIZjTx9JEHRGysWYihdbr3EfRwyOIMYRJAGfT" +"fddt7Eh7O051og");//Registered to:[Planet Earth PC]Activation key:[fBIdjQSztA#3JFygNYZqCBwNDG#6uV#9KpL#0#4IHrPlrYIM] + +sl.AddTail("9kyKK/apqZivA0KTuaIjEfJpvBzJJljQVUA9fdjoAwgdoBd/PE1oWyMs9yptd91Eh3BnOBSZ" +"gTHX5jHZxPY2ag");//OneUP Technology [mMUH#6#4Rgf+EN#8u+jMa#9XwsfNtK#4AQR#4eVl/teT#6/I#4A] + +sl.AddTail("cOZz00IQL/Df1TxVrfLzPzTJ4/FeU2rvh6vf20AKxp4EKfgJvdTM5Xaw06J5tjAWUMwiXd2o" +"5IcuNi7OQ/a9Tw");//Omni Management Group, Inc. [FaDNe#0NpxOA#3xagWHgKxihXntuGRrYVxZUNm#5#8B#9A#4o] + +sl.AddTail("5yIJhjQZ8mWTl1Lus7DhPmzaofdpThZhQabNTQdzuiJzA3NjpurWrLDCgso+lWD/aa5/LNzB" +"FsLEYWcBKRYLxg");//Ohmart/VEGA Corp. [#2gsZq#7i#4#6UnkxxO+SxjhRFmNUhpMFGU#7JRqLZLa#5Oc#4] + +sl.AddTail("+Uzglutbog1vXZV5lJaiQLCx+KFnZxBICZpe09ME3P4XWL5j77UV6xwdIFv3pdYk7gXsE4X+" +"67HJVwYu+pfERQ");//New Brookland Systems [lrVDCijjgXM#4#0#2Tdj/#4zbYXQ/PATaO#3#8PgqRHqm#6Mgs] + +sl.AddTail("/T7XoJK/GqBFFkl1+lsjuP6oP8cjtOckRZp8jZ3aWl2fhE0mZ+9lhz5D2mFZmc8JdsKNqHcA" +"7MUX8vyKKNnoNg");//Network Neighborhood, Inc. [bZsTU+yPCE#4ATTDqu#1SyyhguskgRv#4#7#0lSmKcqbO#9#3E] + +sl.AddTail("j+uV8J/l0BGO/DsvUtvHdh8mIRFnLcFLz7sezaVNlYZRsESAw9tT0AqtdgPtSdNpkNcJByri" +"8d9Z7gKW3zI0Tw");//Network Neighborhood, Inc. [npH#8czCVb#0pA#6AxU#2aAZ+pVuELGjwIAy#5#1#0/#6UmXIX#8] + +sl.AddTail("+o7xvoA3mBUOpaUOZgqmylo/kwPzFJJuBJfSRdjNR28aUx93sClL83BCJcZmMIC3");//Network Neighborhood, Inc. [Kn+VGQLL/G+U#7RGLbpwlKWvuKfEl#3IHTqSngPdnMQy#8] + +sl.AddTail("t9JCn4GDEFRE1RwKj/oD6wi+1IIGmoRjyM+GpWvJ6wIt+v5Y+kyLQX7TQ6NjAbDpBpTvZI1O" +"udScP2eDEF3w9g");//Network Computer Solutions, Inc. [nIyH#0VTjzkMjHMBe#5g#0qge#2s#7nQ#3uxhcz#4#9lJr+qFw#0] + +sl.AddTail("z/Z+wTDNroJQ0N2RbrtnL89L9gn/l0rVWlN7HHkn/aa9qXy9Ls/YtTyu2KVk7qsNpKAsDb4J" +"nDeGXLY2+C0HgQ");//Net/Complete, LLC [fGWdsT#6h#2F+m+ZseolBogClU#9XLW#0lOTh#7CuBQ/Tzw#8] + +sl.AddTail("fyb9R2PK56fctIICnfI2OJFksl9RgRbMhzK7Zv/8KhI+1Bdu9zZWAUW3J3hKOdZPJjo6OV1h" +"2cismhJ1+X50HA");//NET Xperts LLC [#7QJqIEsh#2jqYFkTrLeylaDi#5VBresfASt#9tgY#4/JRyU] + +sl.AddTail("1tTX/LSJYz96Duvzv/LonUa7j4k086gKaU9LZQYKGwxAgWs2widKU3XngroVEIGXqctPtOg2" +"+rEsBAW8AePZRg");//MIAD Systems Ltd. [W#2hIc/p#7eTuL#9eGlyf#7TO//YCasDJ#1oLq#7ZWw#1fj#1aY] + +sl.AddTail("3g/2JIoB6CkNuVSmrMMUTnJ1XoE/lYHXbYuZSM2og9qowgqTw5MXliU6ts3jTY6dMYThLlVB" +"U/162XL1vrGqBA");//Megabytes Computers & Networking, Inc. [#5VdKs#0M+GDN/RlvOlTP#5sPfl#5vf#5#7Hya#0QQSEJBZd#6#8] + +sl.AddTail("pqOIcaE2WBDF7Btvga+eVaHEP0S4xfoDdIP4W/10XZpL9NsHZ3+D202qj0QwpZxSXp1VbX2f" +"9KEfgK+65j5lEQ");//Mass Electronics [fM#2nF#7IIp#4Qvd#6kkgmSdXRPBxfsEJm#2QHaacDTAyxxI] + +sl.AddTail("12JbTFvRI+qnZDdVH+wg2XVeux9+CM4WhIZTm+HSubUlAOVjSJjnfZjPgb2WRExtnFdDQogb" +"KpR3l9QKQEXGRA");//Marcraft Marine [YWhoxUqi#2Q+itlqcbsdDMOiFMwzKNr#8kX#0C#8BXB#8fh#0] + +sl.AddTail("DyHliKgfl2DLsy/eZZW2DLv1JNR/5iOVnM7GMCkXMrmIepezRD6X5Y7rD9PmWYDC1P1N4PCy" +"fhdjmaEAEp0xGw");//Mag-Net Internet Inc. [#0WFbRcMNDm#9#8v+u#3QD/#7OTGbe#7WtTa#3IQA#7N#1oe#7dcY] + +sl.AddTail("i+U4JSj6UshJqblB40Y+BhWbs8qYm1zlAvGFqH7RGtPCnKmt5V7l2yXznrvisANxG/fwjeyu" +"oTsC0M9uRQppOg");//Mag-Net Internet Inc. [DxjFdd#6aKqVwh/#8#5#9zTOwTfMFbXYeQePg+rGfB#8#2gpo] + +sl.AddTail("MfjpEiO/lVgJXQvNhj7ACvir18+o5CUvFc8E1iIma9sISiO4K3QxWzJ8hiQ1d9s0");//Mag-Net Internet Inc. [ZRxZSUHxHLSku#4F#4yMyMK/BLcLJyL+YYejQkQpoZQAM] + +sl.AddTail("wRMtC9UKV8ZTsVOhE+3DdQKFhrLSRHFGxu5OTUHpAJaPBVKtRMFO5lcLXmKHMxP44eCsSysz" +"kopR0YQU+X4oVw");//KRK Associates, Inc. [vahQI#5wWWbq#7CWckTnwS+uWvxZEPe#9j#8#9V#6#9JKVzyko] + +sl.AddTail("M0MnVrVN8cVaHS9M3d4izMgZUPYcobl9h1AcIGFOiIq2G8iYq99nYawmiAkFDpqX4ClmCTjo" +"2VdbIm1WSuo9mA");//Kramer Computer Services [WDRFplcZa#4MbiFSm#0#1N#3ljYFLuN#3pb#0Nkvci#8EE/#8Lc] + +sl.AddTail("AyaKFn2otdlDel4fPQiCY5d6h2iKlY3EquLCswCb4/6ICazQAonMX9LwsaswHnfwbxfF8Urs" +"xz21nRrehCEDrg");//Kiel Bros. Oil Company, Inc. [fK#6NQ#2E#6GXZdc#4mq#1VsulEm#0C#6pakmWpoRVkNKTCqHM] + +sl.AddTail("0ikhTl3VPEOUYS2VvSxaUJ65bmgtMrkUdeGdR5DoBbVzUVt99ZjCq6MTUlrOrfZzZZY8cr1l" +"WSVTURqhmcaPyw");//InterMountain PC Support [#7C/pbaZnKLbuSruuLEbV/Ll#5B#8#2P#2knG#2PXjvafJcUI] + +sl.AddTail("4/3IXlWj4IF0t9SlKnrx2ZRCeoLHWWkSsbTCf+MxlnQGySK7AS7H7ra2zkZshlcbDSW5RcB3" +"5pTidJhdp3LMpQ");//Integrated Electronic Designs, Inc. [iC#7KwGpBtlwLYKQQofEnsN#1qvWTciWH#3qGlWJxPkx#1#8] + +sl.AddTail("7KnSFQnpnq5S5U5vbMLuZVRsPFPhMkJMxy1DFDnWwNd/mai/BPeCmGf2GBJiWcCL");//Integrated Electronic Designs, Inc. [/#4HxUkJ+wIkimfAAklFbODW#0#2GGIOnwtumhSIxQAoIo] + +sl.AddTail("v6knwr3KV2COMiRmlRvIRda/DSdM1y/WeN8ai2N2ZBq4/JP4IxeURphWz1kKpBWoXzzEjuch" +"U1FNSnP5knuDRQ");//Info-Tel USA [#6RnHgFrKRT#7KkwqjZ#7Z#1nxifqcetU#6b#0KfXccZtkC#2c] + +sl.AddTail("idDSrm9VRstW5RgeGyhTK1Bci0WYxKQ/O8xr/rrYaKJXFtgAcEvhVqlCRmtj+qFt1QtNT4e0" +"k9m55L4/on5OeQ");//Image Computer Services Inc. [Q#3oMVPoW#2NH#0#3zHUa+fWd#2lgkrQc#4+al#6qzLbCWhE#1M] + +sl.AddTail("22mROCOYwbnbsr1l+b7j3fnfByLfg9xWDqDUPf7lltzTKpaecyCrZPMB97q2NsnOPXfd7Qkm" +"RWF4rXSlalmblQ");//Image Computer Services Inc. [ySrz#9#0vbHPCwuD#4ypV#1asQEzpLKh/#8UEA#6JwZWeN#6dQ] + +sl.AddTail("WabCJmHgo/gTE31R7nSCGCls0agVfHxp7+BuRFPoM4qbX9V8pX9TqkevpApUc3bf");//Icon Data Systems [qrprTwN/hCttvPVl/FoPrupUKTVs#2e+ZSZzQNk+#5KYI] + +sl.AddTail("aGBWsEuuNxrn/bzXtzrb8hu2mlMg4kjFIkf+xN4RnQimgH7ssVCqF51dLH7jlDhOXLKWwTe4" +"iaRwQKdW0tK0rQ");//Icon Data Systems [kILku/igYLvrFrRYbvasw#5eTX#9YFglKLW#5#7+sFB#2IOo] + +sl.AddTail("BoMdp0xZLWHROPq6O4Go4q+Bcid3GIR7KtW2/76PXohXUX96HSdc8WoBvAY9lv0A1n4NU+mK" +"xBLYMeJyuaox4w");//Hot Fish Global [wp#3va#5zSSaI#1SvyC#6#1F#7bL#1#3+lhCmbwseTfmM+ptMCA] + +sl.AddTail("CDfz733WImNFlnLMd121mKQninVco9IWuXwLlpp52hnultXTbVgGmnLd0TE3V5AB1jLLDzMq" +"OPkU/cpAFaeWOA");//Hawkfire Technologies [mi#2XecQ#1QFryj#2fbp#8P#3RkJv#3u#9eXVUqA#4JrzBEm#2MM] + +sl.AddTail("34LrG5I0urlJ5rqqWmqzhjdO1EYNnMcUS1fnfek5I5j9z/JJmZAZi8MStQG1xSCiwHtj1Bl+" +"ZicG9T42g6eeNg");//Exclusive Traders, Inc. [iP#2W#6eoEe#1v#3qNA#6/zdPUvfGcD#7#9uGebqrJRtosTM#7w] + +sl.AddTail("AKbvpzuj4VTG7FpfK6RKGrbKbquDx8vNDxpxmHUN0cSZ0eSxXwsHlG2DF5dqplSRPHF9AC3L" +"DAGIK06NQPkIoA");//Epitec [jpNb+hzwOSv/t#7Y#0#7PpviJ#7VW+#9sR#3sjCuJ#8K#2fJCzs] + +sl.AddTail("CLmStcVq5JEbXg+VNrODAQIq4y/n2GiAIt3RzYRMfGlEPb6Mw6mtcS2u8G2HKYSj");//ENT Networks Inc. [JCXJjRrJSGnY#1O#7xGRoCNOCONmrIo#8omkITvAo#4oTpA] + +sl.AddTail("iuIcfg1cHi6JBU3+5Nql1xdnX8rKYoOV3/KL1AFQes+j1RTtMJd0zSw9xri6zngDJsasmcCE" +"e3uMFJbGnuTlOw");//Easton Electronics [k#6ZHW#0#6QJNuunIK#5zOUWftwpghuB#4#9#8A#5m#8lwThbf#7w] + +sl.AddTail("JCvmOzvNeUBJWeqzjZNzNwffI0CEKCEhUvmnD3IUcYdC+Z1ee7QpG3D+Wa85YdDdlqK1rasr" +"nJ/jRmIvYuIYRw");//Easton Electronics [liJBKiPqAyiE#2Zo#9Tockf#0M#5EjOz#4oGeEvsFo#1#5cSw#8] + +sl.AddTail("3kPlx2DTsn2UtNDh0gSZz3pSZY+BHOrzxtwLlXx+am/0g46m5IjA6v1P8qyhUCdHw1plZXnM" +"QCwGLlKTWnPrfQ");//Easton Electronics [Nqw#2+#7xT#9m#3sxpOwpGPby#1CDEp#4QtlBHyPifJtHsTh#0] + +sl.AddTail("9Re1S5bJ4d3fUdR9h9W1MKYJLV0Wyxd2oERg8+O8htFTn+Lnp9s1Sfd5193vGR6EOUu13He1" +"9pplu2m/PjfZIw");//Easton Electronics [gLfLoLkPA#4xKnKN#9lr#3K#6#9GiojixKgNjN#8DwyhZ#8#6go] + +sl.AddTail("tK6GY8PuVC3GuF2APpf1wTfhbeC9YZh4zdl1xAFnOHmaCmNBSIW2ACTzUMztbMvwD8twPpTS" +"DoLQNFLpXOikGA");//Dosatron International, Inc. (Test) [JFb#7cFyB#1in#5YVZMapg#7d#2DU#1+qtypM#5#8BPZdcp#6GUE] + +sl.AddTail("wUknLcCS9C6Iw8zHwzLSl4WHB9CFlcb5PhMe/1vq/Ocr0T2DsS6aHEeV65g2RVtW3zw10820" +"IXHob90wP6EdAg");//Dosatron International, Inc. (Test) [Vvoyw#0OkeJTMomE#6TBZVKSo#4Fyq#4L#8VZkEFp#8TxOp#3E] + +sl.AddTail("C3S6hU/PVBZK4mY2YD7qW7Q6kUonPh0bam3N5UbL3Ouvi47breSme56YXbV4+Pg8/l6IoIs7" +"AOaqPFrlpqPqqQ");//Dosatron International, Inc. (Test) [KgP#2b#3+oninlOcE#0cCJWyQtqEaBn#8AtQ#3#0FWhPwyxII] + +sl.AddTail("h417NLCvT/pOPIp1S8XjB3HrGaiGP9PiWiROVDCqXHg8QNR4hrZZijplo1nUbkxCRwMpXHDO" +"FRoaIR0MQoEqUQ");//Dosatron International, Inc. (Test) [ZEeR#2dYYy#5VHS#0Gl#4WbmaejOVbvBg#7hoH#8v#8FxVfIx#8] + +sl.AddTail("qmmZkhVKUVrN9tQKF/aGrGfZmZg0+D949/y8reeo2M4CnumPWRHCkacX7GJxhomVtk9H7rKV" +"7pdIxycIhK4ioA");//Digital Knowledge [qUHA#4sFEgUj#8#5vQD#2XrrPQNg#1gP#0wYz#6cCcDLzB+#8RI] + +sl.AddTail("HSmTfuBSecDIrKvRmc5y5/Vd2cZ57orkh33teO2U0BNw4PQtDfE47NvwNsFOlcnm");//Dattio Corp [UYFykl#2NzXKh#5vfut/MVVz#7GNPKpXfjjqPnHLoDpxLE] + +sl.AddTail("4m57MNqmRaeXt8Ul3jcbPBxmNqdzoOVsN48Ff5huHRYYjX0K7fPHxg/wCh0TEa9gGIAENcK4" +"YvLAedw5XYxpag");//Dattio Corp [JXtxk#5#6bdl+#6RU+uuOQlrpwl#8ohx#2jKMHe#5jywBEe#8g] + +sl.AddTail("E/eNrG/GxggnGCHb/bgbjTuIihnQlqseKSAUYeuRSqDIP2+ybFXfyQkoGa8oM9dS");//DATAKOM [ReaVLKnMRAfJHV#1vIBdCxSA#1nsEi#1SG#9bXDaFN/GmkQ] + +sl.AddTail("HfcoSW6PmTjUt18/dmZ1cVx7iAy8tfI/g/5taMsOCWjNldUESev5ZYfRd81ERpUYCGVdReMR" +"35xhC2Utx4y+pQ");//CTS Integration, Inc. [y#0OW#8yKslWcwnRWbfUA#2IAxOSNQF#4pyJT#4T#1GfkTFE#8] + +sl.AddTail("MQdERanxxGxdnhY4OG9lAFLv3ECz6d13PsC0F+/i4NezVIhue2MRcLInV+xudFFxEWL7zQhs" +"+DugpRVVFROsRw");//CTS Integration, Inc. [VV#6ohff#2pk#5TwclPLhO#9UNFOAgpdYdLQ#5#7#3jXoyC#1kQ] + +sl.AddTail("NdRtIE1qM0ulzwJIRHOhsBtk9mQu0ac6FnhcE6B3hswyfrn+hhehx3TJcs37Dy/VrSFwd22m" +"euJq0NuvTwEB7g");//Computer Werx, Inc. [Ew+gTFDw#7#3#6#1WUIvxqWIg#7UkMjgfHsuWikUT#4#5sb#6gs] + +sl.AddTail("SZRHJManmPC/GYfhfTkqvnF36AvkLRvHm8fYuFx6on1ktZ9o1y0ZGUC+JHLNEyQrLOuVe5wV" +"X9DHUKEQTZ5HqA");//Computer Service & Repair [sXmTbNP#9t#2hOLAfB+#0T+iMFSo#9Fi#8UQWbZCSQnHoHck] + +sl.AddTail("hxckfpuyVa6AYtinZiTWIdBvBEt7KiW82/MH15ZTswFwCudzsEjaThDXp0DYz+VHKCNNfYSH" +"ezzPHvy3orZyZQ");//Computer Service & Repair [Ham/Bp#9+F#7Y#4#9VZPUey#1/rZvS#2uj+SN#7psW/qe#3QS#2A] + +sl.AddTail("SwWgNfHf98LkHC+rn/AHbA76rq7XY7nkcXnLL+HFoeenusoKPQ58738M5Ag+dzG7DTLk4495" +"aXfYjZUjVQzTZw");//Computer Service & Repair [#7CXMW#6HVLZEo#8#9eD/LbefOBBQh+lAOKJ#4#8#5ClLQPmhk] + +sl.AddTail("uhMw/eAXeSPDUZEe5+vsLzKtJnErEtpDt+2NeoEpXXEfH+qTxru3u8EYR7UuFcw+KCyc9a2d" +"Wo1ZGTmAjlCVCw");//Computer Creations, Inc. [LIGLUe#5yN#3V#7ILIbN#3NeDiYA#8#1bZ#5veL#9iy#8ZgjPEDA] + +sl.AddTail("MZQgmoJmRC36f1ab2hh9GgFPp3BeYOgik0kDJyKfw1uvNW3YA+KrrCk+mPzYDERqV5Ojis8e" +"cvraii9ppHSfyg");//Computer Creations [QQUg/Pqa#3Ixq#8akrMV#1#4mJv#9#7ktyAMInZ#2mqWzf+JeM] + +sl.AddTail("n6iIHbDDCfN6dRtGl/+6iau5SJoJ0E8sabqpDohOpK++2i/iZMVkhZ9N3nm/9xlQH9hDYXL2" +"qxqwHia0aH1UyA");//Computer Creations [T#8k/K+Dec#8#0LgTi#8by#8tga+#9x#8BBsPPz#7i#1rLwjEjeM] + +sl.AddTail("+lZ7yRc+ArVoU32q/pKZ9V7+ytlH5lXzfoYP3imfaXJvPhW5AiBOBmNfAWFHq9OjyEdvqJRl" +"PWRswR1H/zRuDg");//Computer Corner Ltd [+#3#8oJ#6T#9QnWwuBCOxRbIK+/F#7VRXcSy#3#0L#3F#1TLXuhw] + +sl.AddTail("zQm03Ae2Rc50OXh9U0DTW+iZsh9ZT1QcQYcRv3z7wXyBrKY+XQ4bjB8p8em2gvyNUAIC3S3q" +"I8N9d599EVijmw");//Compnet Internet Service [ouBbzQ+Jxl#2KytNP#3mGinlbl#0B#2#8#3aNgn#2FWILeA/aU] + +sl.AddTail("is494/A6gZ12yZjKp4B3/3uYQZg4iL+87qYMwPyfsDZF2lgn6yXYE3D3hAODcWCWUmG2sXfu" +"Aissd/xq2GM90g");//Comfort Control Air Conditioning [FgvDzE#5X/TEzgL/#6Bk/v+pHRVhom#5baS#3Gf+#5TdVko#8] + +sl.AddTail("9xLRdF6rA/qjcbUZj9MVWKHPINdO1+VGZ7xqtK87C8nAPnpwFyUyp2LyyxWQFJjZe5uQtbq7" +"px6AF5V/qQT6cQ");//Castellini UK [kR#5ntEiD#1RxoaEZinm#4U+JHJmNbXizfWw#8SU#3Lx#8slQ] + +sl.AddTail("ifO2g1qQcUVLwKUgzUppqwKiY8p4lpJ2bO23Qzk7Z/fweJINHUI7SPWLpyXGvlW4");//Boat Medics, Inc. [#9Ipqiiix#1cTcTSgXInirWnjK#5RyckH+sBwxVmFTsWSU] + +sl.AddTail("RqEWLLXW8NCGZsrDWi1hVAI+3GvKEMosx93Kfat5SVGCy2/Wbhsb3f2zDYEI70MH+DVAXoT7" +"PT4woxvR66Pdeg");//Bits Technical Solutions [W/vnCI#2MGY#7yahCZZwXIdx/xtYV#9NA#6IillUPi#5#3ZGE] + +sl.AddTail("/CxjTvyFb83ebO3Rm9tP61+nVtWk2wUSKJy2cOwIE2BagtF9OkY+AWfdgDG9AbEY4iAF/7gQ" +"kgk/lbzZ3fYitQ");//American Eagle Federal Credit Union [KiK#8phGgxakUxmosz#4#8B#5UTX#0HmuUZ#0zBgb#8RE#8h#0Pg] + +sl.AddTail("//ujMI27oHp+YhvptGA3HMe10RN11s85O67QpGFuw6FuTUS1+qFZJlMR6HY/BZEf18th+a0E" +"CVGM9LioQwdK2w");//Altech Communications [N#4ZuO#2ZAScHXA#4BEuuKbG#6jA#2#5Pq#8#2djqkoVokF#6RF#8] + +sl.AddTail("QMhIauV71GaGch7UrOQKjXJFp/m0m4PaORI7M+7kD+dALNf3HdtSUZe1pQSVcOSC+zXXqxi3" +"ed93dhhfdZqHyA");//Altech Communications [Wl#9GETyOB#7qvtuB#1hldN#6nMtTl#1CXbqhCOW#4AXUouKw] + +sl.AddTail("ol45MVZqW7U7SdY4oJzvpwU9lSzI2uvzfbPBkcPibPQ+AZCqsU0OUnfLp0Ap/jzV");//Allstar Show Industries Inc [MXpMGGIlDPJU#4DNwaK#0FbUK/ky#6Rve#6AutGKqqX/tkI] + +sl.AddTail("v+DTZ7k0HCV/w+sLqdz9QfHa53Nq5vn844+uZFw04rfiGAZezOKJl/CvIo8Przq1T8HlBcgu" +"kbIsmwlnsMAM6A");//Allendale Machinery Systems [RG#3eLHFZ#7vw#5Afa#4B#1CADmKH#2ldBfF#6#4s#1+pFsqIfLQ] + +sl.AddTail("DRF4ee+jU1ol0UrrN0EnizaKSN0cydd9fGb0bjhRuTqT3Id8+lZmGtPSdfEYkQ0J");//allendale machinery systems [f/ZIhsds#3zAJoR#5hNZn/VvNhKZfhiYyu#3ormnrBjzNg] + +sl.AddTail("jPW4ZxDYSSJUn02G7kb8lVHpAAAL1dqMFS3stayCEGNydNqQdCEh+LAXX2bqXc3Uq48fNRms" +"3e+x75AR1IPDgg");//Advanced POS Solutions Inc. [aac#3xQWhVjB#7nIYjCCu#4PvEAn#9#6EkUITAcf+V#8u#8Jww] + +sl.AddTail("rG0bXEQAfCYFrP+4otWhniD6s4WtzTNMlYGpxzva1ZtzJEOt6B60N8+X7yx+myjKBZ+CB1Ao" +"Xw0jdTrmDBMjXQ");//ADVANCED DATA SYSTEMS [pnXTvxvSk#8NAilSyXv/Amw#0zN#4g/Z/Ex/HG#7U#3FfdEU] + +sl.AddTail("ZSEzD/RJHChakLX1Yl3U5/glU2/n/UoEO1zYGry/lvbvuBACu998eXRNeS7KtWYTHZ2vwclp" +"RSkyQbCN0RNM1g");//Adtech Systems Inc.[g#4dawDP#6DzEqkdwFAZcZsIazGcKgcR#2#7#7#5CA/Z#6CYu#4] + +sl.AddTail("jlRFxn8y6B3UtiOYlgWXpY2QuQmr578ADOEvZHCxffbfdBxihQPaljSdK9/8dIgCjOzMK1oG" +"feacP+8J32JwjA");//Aboriginal Technology Solutions [w/#5Kp#4Cm#8B#2#9nnranbsnds#0Y#4BYP#0CdR#5+FNmgctU#7Y] + +sl.AddTail("lVOAg0IIEZwsEhJlu/FJBq6ANoEeIKi7dL46C+CbAB1fI+kc18sqM98c3yPQVbWWYTKRS+AG" +"0dcON1v2/aoNaQ");//Aboriginal Technology Solutions [C#2atbxlT/#0#5LfweSTsDxkDX#3Arku#9wZYM#2UkcMZqRkQ] + +sl.AddTail("I5ESyUZVpN5hSKj0lCmiCnOu+XRN/ZV2ORyK0xVwejlIy1pSv5xjK735JUEHkiLslt1RYN59" +"6k9rlFzZhoktCw");//ABM [NCaP#6nGweTKuuXw#5KZfFQdEZkTnNr#3MX#5LYVX#7hiWR#4] + +//Bethany Lutheran Village Tower uJiq#5nWeSUbdCeqhcOnce#3PT#5YzGWI#9#3lw#3AFHKOCaI +sl.AddTail("bOW/KsYo5EaCha5SiSaJ3kLvQ7kcjsYpEgLuQABka4RMNrTUdgDuQEbcaETHigwBH4Pf6poq" +"dQ4QwikONb3B/Q"); + +////City of Quincy JTm#1l#1baVSUz#3CpCoLg#0#0hUudHDZSwawo#1E#0WUO#1Joo +//Update Dec 19 2002 - paid +//sl.AddTail("9eb4rPzI4WZdeiw1vcqjWm3Li66ryTrdmr8Az5RBA0do71/G5YeR2Dq7sIpGWjBgfU7+7tD+" +//"wYRwPeluoEx9lg"); + +//New Brookland Systems FTJqsgPHObedj#9#0#2GzndIIr#1#1nSlXk#5PWSkYmFbxbbc +sl.AddTail("2zDOeArppx2bhdhKjrVxwzxmSS602x2lfBZ3rvz1xgMkXnFLEHozDKCET0qFlXJc328yUndI" +"Ntxxjl816mOfog"); + +//United Business Communications WIxRPVFaLi#9IEuyR#5rp#6EpggL#9eJsy#4vSzRkG#9xC#7Lc +sl.AddTail("r+QiRHL0DVfocI4HrYKeRAQ8gCqcBQnbES8t1T8RRd3qiVHak+jFsZaXxQya5fQF8+2oLGdR" +"1VgUgkopH9wFAQ"); + +//Rice University #6#2MrAmx+dHUktLGqI/UMtALPtF#4FptyB#1dfFZiS#2#7#1E +sl.AddTail("F6xVySHC8avdZ7rrrmKp909zuAW78VzqSwMW0+XoOYs8A46uLrRyI413tl9ejLxrH7RKsiGJ" +"HwlZATqQWj3vUw"); + +//Cincinnati Test Systems, Inc. c#2#2#2+L#8#8gGKx#8#5NW#0iw#8tZS#8CIFJ#9ME#8G#9v#9wcMmWOs +sl.AddTail("2wHL43V2LwSFY+wtvL6ZNYA7G2X7CSUPlMNCdph74P7v1nZdiIUmeSzCEM+tyMt3vh8/PK7/" +"SiOkzoVJ6lOo3A"); + +//Ed's Locksmiths CYpTosuN#8v#1YlVveDhG/WuVG#3#0eosfnf#9Fux#1CGlXew +sl.AddTail("0hqWAK1Z8+mmlj3WEyyrspTy5AxylX3L2fkEG45RvAD2/2jk6KtqHk3erlglzLXE7K9DUbGz" +"XDIS8GL7jgWmOw"); + +//DATAKOM SIA gjog#8D#6nOZ#0#8I#6kjHMMx+lyGb#1Q#8F#5tYNBIl#6lIWZmM +sl.AddTail("JuYwXYnrU5HTXTsZ8T87zCV+LFsU/MKguuUxcmxxcpC7Mz/Qpoq+fBm/lgvtXJQxz0zpHrAm" +"/pgUbB/y0giB8g"); + +//Enviromech Inc iRCNssYZeUsN#0C#1LExAM#9rSzC#2HxCm#3mrYXFFTuO#5AY +sl.AddTail("rxZxyBqMVLzW+qtlHdedtZBUjydVfI8VJreD+nT5LYoUQUT2Fo6fQA7YWw6JSqqO8Ad8KMDH" +"ych5KDDScCAt6w"); + +//DIAL TrS#6NYZldOMS#1q#2EOC#9Ru#5d#9lOh#6QyFHUEd#3E#9BMIEk +sl.AddTail("1uJIx2PPy00lXX10sRaZiDqGo1DFtvT/OHdcWxT4RQWs4O3fqKNy6DIkueP8u6dVC+NyWunw" +"XD+HsdaTJb1dpg"); + +//OneUP Technology Nlno#4XWKhgGbM#4#7bbaninFq#7FRxu+OIMKeRNLk/#9Kqo +sl.AddTail("v0VAfSGEyxSGxKDqBxXot8OQdMEEiqjlncUei8Movt5NEg/2yUNPzNxKou4TId431In5eryn" +"huK6NSm6Hqq3Ow"); + +//*************ADDED DECEMBER 19th 2002 +//Ordered Oct 9 2002 - chargeback Dec 16 2002 (1 license) Graystone Properties [IJfwCJKVrH#1s+#7xDgxnk#1eFbVN#3GCTzGPP/nlOJe#3Ds] + +//Removed 02/27/2003 apparently we never actually got charged back for it +//at this point client has not responded to many emails etc. +//sl.AddTail("4mqLXbXbKzVN50stxjqqlicZf+P+solcUtcCsY81OihOCbiFGNFkkTnho/5WxrliN+whXTFJ" +//"2mBBrsLct5Aq3w"); + +//Registered to:[LEXCOM TELECOMMUNICATIONS CO] Activation key:[#4GCq++m#1CUUPjN#6jg#0#4#8/gYh#4pEbicXLFBm#7sSeFzZY]sent out license key for 33 when they only paid for 12 +sl.AddTail("REhqlKnu2fIudbkJ1ki1hkUBFfyS7rVT6UmwoyAWN/LwDTLgL3osjSTMjvqt7s1hqqEOirLS" +"X8MtGDDWitHjgw"); + +//OneUP Technology qXxTLyUSsN#6xrsedR#0+#2tYxgNfSjOvq#4bvnV#4/aBiQ#4 sent Feb 26 2002 incorrrectly for 2 users +sl.AddTail("io7hjeKtlMuaaYBVgv5VkltzWCMtBd/268wD2JqrgiNks4338aH2jTFPjc9fZ4km4oQghtgJ" +"U+fHwSOKpF/Wvg"); + +//Bethany Lutheran Village Tower Activation key:uJiq#5nWeSUbdCeqhcOnce#3PT#5YzGWI#9#3lw#3AFHKOCaI - incorrect reg name +sl.AddTail("bOW/KsYo5EaCha5SiSaJ3kLvQ7kcjsYpEgLuQABka4RMNrTUdgDuQEbcaETHigwBH4Pf6poq" +"dQ4QwikONb3B/Q"); + +//United Business Communications kWo#6#8zNfWHJ/#0SBST#4Emyz#6#4#1uEFjVzcCD#6GSXl#8#4xc replaced with order 747 +sl.AddTail("12iQDcyCIoMaaFQtlI/PuNN6QKcW6NhiTKNx7iwvPaYfD594H/afxtiMAwbIXRHzVJgrF/Wx" +"T5rdIUNxHi1c6A"); + +//United Business Communications WIxRPVFaLi#9IEuyR#5rp#6EpggL#9eJsy#4vSzRkG#9xC#7Lc replaced with order 701 +sl.AddTail("r+QiRHL0DVfocI4HrYKeRAQ8gCqcBQnbES8t1T8RRd3qiVHak+jFsZaXxQya5fQF8+2oLGdR" +"1VgUgkopH9wFAQ"); + +//Halski Systems, Inc. MnY#3#4LuvCOK#2iHnwctR/xpS#8VU+n#5qNjz#8xeT#3dWTbE replaced with order 746 +sl.AddTail("02IjQGIBv3+faD2/9ORxciJw5R/mGUCgMVY3RAjp1NYPK2fBbNiktL5nlDgR3h5mUNK4T6UA" +"3y4QxFp9f+aVyA"); + +//RODIN Computers kjJwtZXyxEA#4rEXDH#3H#2JlzIicG#3E#8Rl#0x#6e#5tF+#9d#8 replaced with order 740 +sl.AddTail("jslu0Zg5uOjFCy5Kqet5MnP5lF9q9FoXMN25IsO7OBfgz601jN6CYpoDkyPE4YNoYgBMJBAq" +"8hxPPKDG/BNg1w"); + +//CTT Enterprises LLC oDVXFM#2fcqQg#1#8+Mys#2ZvAZ#8e++nAi#9VOAc#3TwVOkkI replaced with order 730 +sl.AddTail("Hgw1sei92aULH24sBxHMbf04yWiovWK8vWyzKzdJ4/ppKfF0eFx+MoXgGhraucqBW7P+zMX7" +"ozGxum3fCcQB9Q"); + +//American Eagle Credit Union #5SvgFpgChPf#8SWXCwe#2awzZfnJPAJWX#2jz#3teI#2#5lLM replaced with order 726 +sl.AddTail("ZNrTf1wATOVfEFHepjDKxOLxSlOJSrLpSCwHI6KlXo2u7AMnMvBCKNRe7g+2ABXOLxI1vQuS" +"0luqMgU8ayrCIg"); + +//seamless solutions hjUlVbxLXWredZ#2kQ/eiqOZl/hOkCJ#0#0KYhp#2Gwy#0vs replaced with order 719 +sl.AddTail("3jU1NB3hYjTp68o4j1z2RiMfXzUI91tIsznolkmc9qXcoaL3yM6RsGlEw93SJeHH/K75jlVV" +"OxuN3M17gpCTVg"); + +//Cincinnati Test Systems, Inc. o#6oFWxBBYixbsEDN/svh#0U#1#3BREXvTxXJY#2A#2ZOcaLs replaced with order 718 +sl.AddTail("AeqZhYdgQXai1bqxVwJBKLSMJdOFtRFpQUe1dqI3nTgSz2jb1u82JeT5+eKATabRf0ekVgoH" +"kmyAz+AeblvnEw"); + +//Cincinnati Test Systems, Inc. c#2#2#2+L#8#8gGKx#8#5NW#0iw#8tZS#8CIFJ#9ME#8G#9v#9wcMmWOs replaced with order 692 +sl.AddTail("2wHL43V2LwSFY+wtvL6ZNYA7G2X7CSUPlMNCdph74P7v1nZdiIUmeSzCEM+tyMt3vh8/PK7/" +"SiOkzoVJ6lOo3A"); + +//Superior Service Y#0MHog#1jxf#8OrsWAswNUAuiBMvSDUPZ#0#3WxbglVb#2Hc replaced with order 711 +sl.AddTail("yZno722zIC/nvKiUshQNjhWIKoNH3OHDLBowZi/qBa3g0OKankK0CIHftKDrYLoiWqVB1eTr" +"h25qOrdEFNZ/fw"); + +//New Brookland Systems FTJqsgPHObedj#9#0#2GzndIIr#1#1nSlXk#5PWSkYmFbxbbc replaced with order 703 +sl.AddTail("2zDOeArppx2bhdhKjrVxwzxmSS602x2lfBZ3rvz1xgMkXnFLEHozDKCET0qFlXJc328yUndI" +"Ntxxjl816mOfog"); + +//Rice University #6#2MrAmx+dHUktLGqI/UMtALPtF#4FptyB#1dfFZiS#2#7#1E replaced with order 695 +sl.AddTail("F6xVySHC8avdZ7rrrmKp909zuAW78VzqSwMW0+XoOYs8A46uLrRyI413tl9ejLxrH7RKsiGJ" +"HwlZATqQWj3vUw"); + +//Ed's Locksmiths CYpTosuN#8v#1YlVveDhG/WuVG#3#0eosfnf#9Fux#1CGlXew replaced with order 691 +sl.AddTail("0hqWAK1Z8+mmlj3WEyyrspTy5AxylX3L2fkEG45RvAD2/2jk6KtqHk3erlglzLXE7K9DUbGz" +"XDIS8GL7jgWmOw"); + +//OneUP Technology Nlno#4XWKhgGbM#4#7bbaninFq#7FRxu+OIMKeRNLk/#9Kqo replaced with order 688 +sl.AddTail("v0VAfSGEyxSGxKDqBxXot8OQdMEEiqjlncUei8Movt5NEg/2yUNPzNxKou4TId431In5eryn" +"huK6NSm6Hqq3Ow"); + +//DATAKOM gjog#8D#6nOZ#0#8I#6kjHMMx+lyGb#1Q#8F#5tYNBIl#6lIWZmM replaced with order 684 +sl.AddTail("JuYwXYnrU5HTXTsZ8T87zCV+LFsU/MKguuUxcmxxcpC7Mz/Qpoq+fBm/lgvtXJQxz0zpHrAm" +"/pgUbB/y0giB8g"); + +//Enviromech Inc. iRCNssYZeUsN#0C#1LExAM#9rSzC#2HxCm#3mrYXFFTuO#5AY replaced with order 681 +sl.AddTail("rxZxyBqMVLzW+qtlHdedtZBUjydVfI8VJreD+nT5LYoUQUT2Fo6fQA7YWw6JSqqO8Ad8KMDH" +"ych5KDDScCAt6w"); + +//Lutheran Social Services H#7I#9CN#8c#2ZWYqXcBepKbLUcn/cq#1w#1OkRdQiRFcS#9#1s replaced with order 677 +sl.AddTail("f/W2bj/x6MTYPpoO5Uvp5dckVlez9j3wINFu+WFUGaercNQasjFyT3JNHiLUelVofW2JLGJd" +"cnPwAnd9VjOAJQ"); + +//DIAL TrS#6NYZldOMS#1q#2EOC#9Ru#5d#9lOh#6QyFHUEd#3E#9BMIEk replaced with order 678 +sl.AddTail("1uJIx2PPy00lXX10sRaZiDqGo1DFtvT/OHdcWxT4RQWs4O3fqKNy6DIkueP8u6dVC+NyWunw" +"XD+HsdaTJb1dpg"); + +//Kramer Computer Services [SCqPgo#8cedjtkNakhWh#8Nd#6#7#4Ar#3#1V#0nS#4Wkq#3kw#7#9Q replaced with order 673 +sl.AddTail("Bi3DkK7b/i6qeAGBzgucsI7R0D3wKFKBrLgCVqkNySTKKV6TO+mAsijYri5oEE908tuuFtST" +"kqxPdHA4+RYdfw"); + +//EcoLighting Systems Inc HBMP#9Enlbo#7qMOa#3aK#3f#0zI#1gyOU/+U+ZSDMvIV#1zP#0 replaced with order 667 +sl.AddTail("W6EBAl/ocpyromWkr+D5yGYH3xgIKxcjSlz7xWKmz04BLrMIgMmqbGMWgy6AVl9MY9g9LIJ7" +"vh0hhw919NN4tQ"); + + +//******************* Feb 24th 2003 ********************************************************* + +//Adtech Systems Inc. RP+djYyVZlPXJynqvwlMQsBcAB#6iWJiAcuf#0mJluo#4s - replaced with order 760 +sl.AddTail("B9pBHgg9PL6vJni4ScfA2YUD0ZM7HD2wvJy52V8a1nICzRWU6tsQtdtel7+HdEYZ"); + +//Wilson Memorial Hospital j#5vmyDmumc#9evF/MfMBUyKNQRpyC+KW#3dofQ#4#1DO#7dI replaced with order 775 +sl.AddTail("7atXZbYg727klvoBI0MsLl7h0MEwfO1+LOmim1W+OQ42y5Z098rSw+lZ7uGDaD882/HVYomq" +"9DPJ3cWzGLO4ng=="); + +//Total Technology Integrators LLC OfyOaZ+dvBWtbjgxnQysx#1#5rL#3AsOEbAwgd#8dSdh#1#9#8 replaced with order 777 +sl.AddTail("7/ZzsIbSpCOGjPyV4+dKQl4YEq2ORWFO31njaq8rpMrN0OgmScIag8iqM9l+zKlY5v1ktPtP" +"664/Tzd+O01DRQ=="); + +//Ed's Locksmiths #6Q#7#0#6ph#9#1S#9PodWp#3#8Pg/STKGlMtcO#4rGgn#5EyqoRA#4 replaced with order 779 +sl.AddTail("EctgtDWZBX1/cR5cRH8UkssbaBbuxv4BH+Yx1qpsD1X5Kn2GovwTFL373N9lBX2KA0ZjrIVj" +"CHWuG7YDAqbUZw=="); + +//Ohmart/VEGA Corp. dnqhYyR#7G#5Xy#8#3#5BqiWrVeT#1Kwm#3me#8PJ#5#8uAjE#4/#3Y replaced with order 780 +sl.AddTail("YbnUcS7LPd0wH6S2/dX2lzK9aGLidQyiIvCtvzoSAW4gcunHXl4vV7dN2j6S4qqwn/TF5Ej+" +"o+jAbIE4CnUZmQ=="); + +//Frank's True Value Hardware Co. hDB#0gpfCUZSPi/zCYc#6MUKQzld#3lxD#2/fYJ#9kqzMJwg requested refund on order 759 +sl.AddTail("hqvn36VX5SY+JqQsvXkd8bs9Lediy/ntYGMbz+LHiA7MOW2ypy0up1x39GYFDFCLtQBiWvOb" +"o1QiPbrKmII1pg=="); + +//previous order Certified Solutions #9NqyXCXVoEWFHbeZ#8TngSDDNibbL#9#4U+yCCdflzzF/g replaced with order 784 +sl.AddTail("1kM2fMP5bYwZxhpgsWRQgn68wTj+lJsu5tnvrCrGKg/EbrAgAZuKjuceOzt7SZQz"); + +//previous order Paul Labute, Inc. #7#0imEWy#5GkutkejuJS#1WoIx#4/#7qu#4#2aTsvHYPxCQYXs replaced with order 789 +sl.AddTail("eNaYFh5GbE97gtmjJWJ+weThrd9eqnb6JZ6+Xlp5CrJfmKkoeEK5R7b1fliWIhEcRs7agiRe" +"dWs+sQMSjjqIUQ=="); + +//previous order Comp-U-Help Computers, Inc HW#9+UlZzcM#7IXTa#6#2pa#5yslJ#6hf#2T#9Mz#9aq#4YLWoQjs replaced with order 802 +sl.AddTail("Z3XPSSOPET7hDCiu+906+8eVFRf+FW7VyQ+OLI5DL9IXhHdgIco8NAG+MtZnJiir6lQFouym" +"4TZlZYrJH1mG3g=="); + +//previous order ServiceCentret ApS CfEYp#5#9qcj#5mQqkCgcoD#2TOKFWumcA#3+cnTn#9eBqV/E replaced with order 818 +sl.AddTail("fhmjCgxIu22wVCp8j5X3jjJSb9bxAbXxshLTCPWWrtB4RV36bzK0WL4zpR8DEOXnJ8W8xU9/" +"aayNGXjYHZq1Fg=="); + +//combined orders Wizard Enterprises WfPPvuL#3mohNMjk#8lGIcOG#3L#1piAqzcAvwvINL+ImOE +sl.AddTail("/I90xJXJYEHbRHfZuVoLGndWMebuKfUzn2MnyuL1jqa+kWoA0S/k8oEK4a1JSIso"); + +//combined orders Wizard Enterprises G#0hDCyCMe/g#4#1gGwmnvP#1mrlsGmOGVa+d#1BsoemMYqw +sl.AddTail("TldyPAapGIUc+oRO3FvCZC7bl/STqdSq8exn/j0X1jToLPN2+rKRYdRhTumq1sQ5iI0YF8wW" +"MJyVP/VbJeBb6A=="); + +//previous order Symasys iRUW#8jElfWBwMemwdAcTPXGaDUeg#7S#0/NcNox#0#7oPdQ replaced with order 825 +//UPDATE June 24th 2003, they did not pay for the replacement key so re-instating the original paid for one +//and zapped the new one that replaced this, see below +//sl.AddTail("nJq4xbtRkW+bOhei5uZruuC735gHUyHoA7DoQE/6jOac73R7KUJu27kGaqSweTwUVAw4BUK1" +//"4bgbBeVyy+lW1w=="); + +//previous order Motorola Hong Kong #5#4MGTZZBdr#9eo#3mERZ+JG#7#0rnBZyaKVTzIBFvbu#7#3#4Q replaced with orders 845, 846, 847 combined +sl.AddTail("HKo6GZlogrrHy0ZdE9SR4QN/DQgWBz872Ae8AyD4WZU8JwsImCuLnjeHvKCNabKhjb0u837r" +"+CWP8kpeSdnbiw=="); + +//Certified Solutions #9NqyXCXVoEWFHbeZ#8TngSDDNibbL#9#4U+yCCdflzzF/g on Feb 26 2003 as they purchased and than decided afterwards it did not meet their needs +sl.AddTail("1kM2fMP5bYwZxhpgsWRQgn68wTj+lJsu5tnvrCrGKg/EbrAgAZuKjuceOzt7SZQz"); + +//replacement [Ace Hardware/The Tool Haus] Activation key: [] replaced with order 890 +sl.AddTail("PcMraG1a7nwVsRKqmVOy/SlY8RNcq9zEn/I3j3i1kWSVvQMf421Jaom4CVfzfTGk"); + +//replacement Registered to:[Motorola Hong Kong] Activation key:[Trt#2cpxTCYA#3xoYUfTKJQ+DjWID+pMlcbhOLZ#5h#2o#8E] replaced with order 896 +sl.AddTail("nnyRluZgMNwIxhLJdXzp9r5qRl2EVIVTcp8WdkdVHJ0DTgfvQcJHEyM+jNI/iEXT9QcrU9aU" +"K1SYvxs4i4gNyA=="); + +//replacment Innovative Systems of Virginia p/f#6d#5EPoBGzXv#7LP#6JK#1ETVyyYv+dPv#4Fw#9ExvKado with order 900 +sl.AddTail("3Z1/rGnazenqgXclNvstxMOkM4Z9/UrA03Es4dTDn2EU3R/VtbLAv62vYcmZP0rC1z1MWjJU" +"Sqc5XZrH7LWEoA=="); + +//replacment Registered to: [Motorola Hong Kong] Activation key: [tecludkt#2R#4JEY#1ec+qmGgq#4TYrlX#2NMytMT+Sbd#0b#4] with orders 899 & 898 +sl.AddTail("xhp20X6EzKTrOgeplGf+5OV1XFVjHvXhs9ECuAWa1THTq0iei5LCRjxiWkXd/Z4TFKRBWoES" +"zhX80GL9rgHbQQ=="); + +//replacement DATAKOM ReaVLKnMRAfJHV#1vIBdCxSA#1nsEi#1SG#9bXDaFN/GmkQ +sl.AddTail("E/eNrG/GxggnGCHb/bgbjTuIihnQlqseKSAUYeuRSqDIP2+ybFXfyQkoGa8oM9dS"); + +//replacment DATAKOM gjog#8D#6nOZ#0#8I#6kjHMMx+lyGb#1Q#8F#5tYNBIl#6lIWZmM +sl.AddTail("JuYwXYnrU5HTXTsZ8T87zCV+LFsU/MKguuUxcmxxcpC7Mz/Qpoq+fBm/lgvtXJQxz0zpHrAm" +"/pgUbB/y0giB8g"); + +//replacement DATAKOM SIA rg#9FNLJ+#9JbWEBWhfq#2r#2U#6#7qNxYOUFZhhhXtHJlTE#0 replaced with order 908 +sl.AddTail("Ceijwl4eFBACDKtBBGCtHDy6alWuXZL2lAwrjLnluqvJPyqmMIaFuav54kiN11Fr944tnJxl" +"xkQzVVc8esBCxA=="); + +//replacement [Motorola Hong Kong]Activation key:[ctSQ#9XaW#8laxqbySlnhd+pbbegsVmcfQqi#9qJLl#0I#7#4] +sl.AddTail("RsZ+vZS1y8VZ3u6hapEEmDGJmF7KoGHc9uVoAp1xWIxGXu9geVSE0Zb2j04Xx6SeWz4+zteG" +"P8W+A+WoggG3YA=="); + +//replacement Motorola Hong Kong [V#8AozQr#0W#8Gextv#6JQNF#9rZEE#7tUNkPVdOmFB#8hXK#6c] +sl.AddTail("qOkbROxBNl4JbHZ5Qx+GQveAThxf3soDxT5jkKDGqTbm3Nebe6OLzhJ7QCkaRSkImzz1YdLA" +"Tmb9gzKdOWQLpw=="); + +//wrong name [Adam Steele] Activation key:[G#0jrlyEkMW+lh#0AbMCcs#1+uw/XgyNBZBYM/n#4ixY#9z#0] +sl.AddTail("sYzwH4zkEKNCYhIFWh402gueIe0tCX7TuQhh7Uj/YPV2DqmTOshjc57Fq8KxnlQI9+ZBO3SK" +"ghAv2WJFOl1Tdw=="); + +//name change [Pete Miesen]Activation key:[p#2swAcPp#5+CE#8IesoE#4z#0Hquh+rlbEVDvjLQ#0k/RoAE] +sl.AddTail("e1wIqeKUoEvtL3+8HGZfGrmb3Am4yvJb7bOffMROR20tPxXM2ZlgijtD1kogpeHOsprPhAYU" +"V03M8cUhGji9Ig=="); + +//replacement Convergent Technology Services Activation key:[hgnBEy#8#0bXlAhT#8s#9SVqjpuPPG+txAcurEORTlRdUVg] +sl.AddTail("aj97r+b+09vZ7ut4aB9p26Dik3Y1HG0HCuAAEOl0S5UoWlAeCpegKl0kj8VUm3OU"); + +//replacement Pro Security Products [XtDkrmuEukVdqX+#3ESg#0STRCBBafQHKCCzPROEnICBA] +sl.AddTail("+Dp1CjCWQonsL2DRpNLq+OP0/DVFjW58Nxj0dyK7RyIKALb+SWMiUv3HyuCzDA9O"); + +//replacement Alpha Mechanical LLC [#5Brlkr#5lTjsybQMnCkouwPZjEX#8rEH#8/uNouDqq+J#9A] +sl.AddTail("l+l0sw2BUGdcdUufwQF4ffvAGjcDvnLHDhf8WzfbItNVhGFKMMr4CDhENtqch9nUy3yRTpx3" +"zIa9+ghGuik/0Q=="); + +//replacement [Alpha Mechanical LLC] Activation key: [#4dVHt#9Nhb#5Y#7L#5qVaVXBITbtbQxVK#1Z#5rqfMZcHjqkU] +sl.AddTail("PmcNVq9VkfSb0eVvA1HGIUVvpQ3sTImBA3ecVQCHBcXGVhxBVuPiqjQre263tQmuJEuSG8OT" +"Xk/n7ZR0W2kMUg=="); + +//name change Registered to:> [Apha Medical Equipment N.Y., Inc.]> Activation key:> [M+Z#9JODlk#6#7#0GpJE/HSGmdea#5p#7#9W#7aBd#3#0nZSbv#7#0I] +sl.AddTail("iHK/gMMg7qgsfD9XW8USBQS7a2b8ttIZXEcjj426yN5wGvGQgZMgmqW6OkeHvxZu9I4AZayl" +"8/EmCin/es9boA=="); + +//replacement [RODIN Computers]Activation key:[#9g#2VwZ#3fXoFPg#1z#1L#9Zp#6EQCWRHFxev#1yLiGC/W#6#1RE] +sl.AddTail("KVn7IKnLqlGwrOhRYiS3jnoewhD6GbELvTGncR3xf2xn122KTfE69NT/r+dA4jA7XAB11Ae9" +"8cEiX2Pd7VFdaA=="); + +//replacement WS Electrical & A/C, Inc. Activation key:[FrcBH#0yd#5yobFfj#6BdEnPerFCDoS#8TVR#1vNQLfM#1AFU] +sl.AddTail("IzyuQz79AbwLK8v2vxjKerhYaIdIdFhVYFEGOxiiugqGBVUNsrAFyrssMvZtCchua7WRhM+p" +"jqLUQYI6u/lneg=="); + +//replacement Computer Services Group #9FMSvqcal#8BSoP/m+W#7a#4qPlPflLbM#5#1gukjCeL#1jSM +sl.AddTail("1+ggd945GxRvx4TDtofocmVAwNuGOTYKhnXPg7S0hdubiIkbtwyPFfBsoq9Ghte3YyhcjRIe" +"BcRKTTuRoaAMFQ=="); + +//replacement CRS Technology #8CaGL#2bvRkOpy#0SWQDyiExcxz#2tsTwPv#2GGL#7Fet#0M#4 +sl.AddTail("VRWl9vGnX3cMCnvK8/EfcSkS3beQ+B0cciVAdseCVHOdRA4DbQZoDzvHu0w/G2N0oGxtmR4T" +"Z05qQUr30yxk+g=="); + +//replacement Nova Biomedical UK #7SE#8g#9xtNSzNPzTe#6zxmDi#0#4sHbV1CVtYqmuAkxVPd#8 +//sl.AddTail(); + +//replacement key [Beech Brook]Activation key:[HiWQ#6dFXvXyxzeIlB#0tYlHuEbCZB#5Js#9Yx/MD#8E#3m#4M] +sl.AddTail("ojWxebwZWlS+93Sp48BJdqZwsaIIdPlW4sr77odY4LI9vbMIkcsl5v5VNTtd9HNqKCsOgT7x" +"IkvToz9q2SEoKg=="); + +//replacement Beech Brook Activation key: [qYK#7pU/#8e#2VufpADaWy#1JpYCBXGCcMA#1EUyYDuAe#5kM] +sl.AddTail("GehU8q87DsEM/QjVtb8e0uzR4Uj646UuBtMisaWzY1HAGl5rAkH7Y98iIokQlA3p6JLZcleb" +"vCNfYdW9h2Vmgg=="); + +//replacement ASUC-auxiliary Activation key: [jzJkmdWx+wk#5#7#5gNz#9tw#0MZ#8q#9#0nYdke#6#2#4#6TpRV#4/Q] +sl.AddTail("YSuyIG6Tb/mepCrmqrwO0zAmGhDXq8OG8G+QeG2XgulWL6wvH5b8qsh5t5se2FeBEIj8uj41" +"3uiGMn1Cl7zrgw=="); + +//replacement Nova Biomedical UK #7SE#8g#9xtNSzNPzTe#6zxmDi#0#4sHbVlCVtYqmuAkxVPd#8 +sl.AddTail("rERvtVvDAL9eP9yRNnMDOXmIsBogHbV5/YSi9xhERbmgcJ7+ZOeZ3ZZGn5pPK21ofPw9DubS" +"oxKTSWuGahkhMA=="); + +//replacement Seamless Solutions Activation key:[oSX+Z#6ZvmNyhJXixFd#6KFHiwqbmvcSYxq#0Z#1b#5DGUe#4] +sl.AddTail("CGFuHyt0xD9natbL6ZGscrhWZJeJljJu/WAA6j76sp/VXJzpb0qZC3m/r018YtRvOQZ8e6jW" +"9S8qENzgb6Zzdg=="); + +//replacement key Midwest Networking, Inc. RaOYOKFCeyXqRWy#4aOlRgBuMYasOoq#5QOXCnLdhyXp#4 +sl.AddTail("drrNU/OwvW/wWR2KXDIMaHcNI3w3uiAsNDuGQWdKOa6UlRBHPLXIQM1ujOKD2jLA"); + +//replacement key Aspire Technical Solutions [L#1MR#6NqFg/hJVdPyzQyDlWuPqn#3vAh#5b#0P#8mibgPc/k] +sl.AddTail("DZByDVaQ2iHzuN/cK4xsMTov42+8+fEk5jx5s4IsJ6DZkOi4yz6Q1yGVMUoGM2pjnVTA7Ulr" +"hHP8boLzH0TVmQ=="); + +//replacement key Area251 Activation key: TGQBNPX#0mRIBJucdt#9#4+tKIS#2ZLNnW#8YbqEeQOdAZKs +sl.AddTail("3WTPUov4dWc88VBYemVYFO3eCEkJ7dDrCxe81OM3GpmvrIfeGHoBSrKLRF8yLR5kFEE53xFC" +"FynmAZhwkvBRMQ=="); + +//replacement key ViableLinks Inc. prr#3kzLKaEue#2aLJ#8KgsI#8PISfscxctrSgX#8#8r#3WAFg +sl.AddTail("oan9HUZJ+IpX2OZjVjsJalJMABwSMwfBcokbMUpUzEwbq0nYw5jeCC051PFJJbIUusB2W7d5" +"+O+3X87nvtDTKA=="); + +//replacement key OneUP Technology IS#0a#0#3gxZX#8w#6UAzqHZluLN#5E#3#2#0r#0Nr+wwFbS#7HLDU +sl.AddTail("6QuM3G7IVs6Sre6vk+XF41dJujdCUFu5SIq2F74tt3ra3qMk8XtjCK9BcnlpwOue1MYmUWgq" +"uOiO1B52l3jUtw=="); + +//replacement key Second City Computers [igN#8#6ugudYZ#8JHDmHzQZPWTLggYN#7iTu+#7MHpTuUz/s] +sl.AddTail("lBsZueX+tq9eCUj4nLr6BpYyjWLu5PN7iP214oUcOGenB8Tqmy1NlQC052ruBAY7aIrYzpVk" +"FHZjY57i32VcoA=="); + +//purchase order not paid for - Symasys WAaIXt#8pAVceRHPXeO+hLU/b#1Gj#6kkQuKTHpHhwBjc#4 total 6 licenses - 3 on this purchase order +//re-allow previous order Symasys iRUW#8jElfWBwMemwdAcTPXGaDUeg#7S#0/NcNox#0#7oPdQ which is for total 3 licenses only. +sl.AddTail("iudEoN0hzPbg/0Pnvu7JpkHSR3GYNVHUYW7LZCAjc/A0MWqGKiQMxC/imTLIcD+Q"); + +//purchase order not paid Furello Services Company Activation key:[zwq/YH#6cUmq#5siDLVH#3#2r#9RWheFM#1#8jCflvEgkUUe/E] +//ARAS purchase order not paid ARAS license = [O#7eep#9hATm#1x#9#9#0ApB#7CCPt#7BTJ+#7WpMDiYD#2K#3c#5HE] for Furello Services Company ShareIT ref#2774793 +sl.AddTail("ATbm/+utHUIAyaAEPlejOtRiNa+iIaHBT4L1CvXianLt0Ooc5f2HRkQsqKJpsYwH4OGFfXxS" +"dGs/TPaM4xcFYg=="); + +//purchase order not paid [Geek to the Rescue, L.L.C.] Activation key: [u#6oQ#9P#8jsiVkJx#0pHrQK#8UcZt#5w+ESHKHNqv#1kZvPMM] +sl.AddTail("3Qr4gGpHDpwAjgj5Xts9P6bIaAaw/KUunKamaEx6wd06ClWsPbTtCvOq8QIdRZF3q/TY4Sm0" +"Anw8TYT0P8zvKA=="); + + +//order cancelled [University of Rochester] Activation key:[QHeyyXlcjLOQtJDOO#1AETWx#1OT/NOc+CiLu#1f#0QxN#4k] (this was the screwup order +sl.AddTail("+qetf4mnkk1BN0/fA30EeepAoeWcEbv4SYPbSkLuAZo2GqLHcmBK1rFLW5roPVDSy3WtnGjr" +"UUwumsTWygqcSA=="); + +//replacement key sent for [University of Rochester Medical Center]Activation key:[+#5dMQC#7t#4DjVR#0VGzaaNmCcHEwvW#2mCqRz#3/xhzFr#3#4] +sl.AddTail("QE80GTWQ1bpVtgMDSM+7L83ufmjZIWtVZv4ylRayaP2lVCk6tSi1YMgw4OhfKCMCgD2EInSK" +"TCO2fesJQIs20g=="); + +//Zappage of original 5 user AyaNova trial key +//Evaluation 3aI45wVc+c90DYMyOlfxUeEAiqlpfa9Gw39cryvo3jY +sl.AddTail("QG8m8huOPZScC5ouosfpCZkiT6Pxk3prz2DVFfuP/uoLu0hIrXtTYbfS/t4k8MAf"); + +//Zappage of newer 15 user AyaNova trial key +//Evaluation IN3X6ZeCycn3lrsJgw4cTkNfjMSkKLwLEVj22VYwViE +sl.AddTail("WSc+ABFLu8aBdflkmwiFRmJDnT6XutUd+65IjqO7Q4zCzWsD7aJgkBE/OJdmFsOx" ); + +//replacement key [Motorola Electronics Pte Ltd (Singapore)] [VtCZbMxFNem#1rsN#3#7#1ugCPqpLLhdWi#8WJnJZRJQzQhI] +sl.AddTail("9I5p02wWofDdmsFvRYTg8jXlouRg+fWPUDgMbCXQ4GjNe8RH3sZiABG4GyChkiKS90wpT8f1Khl77WpNt4NzXg"); + +//replacement key Vicom Australia Pty Ltd Activation key: [xDpxXuws#9XYwxSOXKYIlq/IIUkNj#4iCUTxJ#7WxlLf#3Q] +sl.AddTail("5i6FaH5zA6bMLFFJKRy3W7s+GmNlnOKxlffC/HQnezlyyQ/y3KdCAdBAK8SXHXIu"); + +//replacement key Archer Integration L.L.C. #8cGX#0Mvv#2/fCfMekzxOIw/DKmD#5DeceD+#0hQEB#9hc#1#8 +sl.AddTail("/kEmZJPN1kZ9Q14KFXdODViAJF3SIEBoapoEFnFK1y+OjNX+68VKFUutbq+ghZZWsovQexWd" +"oy9Smcoi2sOsvQ=="); + +//replacement key Logical Solutions dOE#2XiAoANsRWwM#4HcdCWsgzdxM#9VxlW#9ZUoQRE#0yIY +sl.AddTail("Yx/p/e5I8ve0iTa4JnJYQNRHyuZiQKxh6VGTklcPc9cMMeqhjev7qNvfh3uKAcoCEldm19BL" +"hM+OTJbqJPimPw=="); + +//replacement key Bloodhound Solutions, Inc. [HvpmjQDA#8isghjDi#4AhYKZ#1vkqLRqqkz#0#9IUe#6#2mjXk] +sl.AddTail("j1p8r+BdzpVneRrioQzh+tH37MFyi0kQuZmENuY/r4U+MmaCxKMyS33Zd97kIWtkWmgXYWmy" +"ZMKMA9DsJ/ZGHQ=="); + +//replacment key Bloodhound Solutions, Inc. [OVgs#4jGRHAzshk/UmeYfca#4AaIIKroSNZmFuYXIdFQo] +sl.AddTail("oO0NrgLxyDNrww0phBE2kS4fjaGoZ9LJc1VQQ7fBFXMvg/oN/YH/j8x96bnWGd5+"); + +//replacement key Turner Technical Services, Inc. QM#1#9JLzN/YkrfQ#7Ihwte#5IxttkdcXc#5xZanUitEhX#8Y +sl.AddTail("eudgkwXJ8dC2AbxBhkZsuKgHnd20oUjfKsuKj3/9unxQV4ep7+zgMRY2r2CdDeQ8bjgwb/s1" +"F/AlRGX09X80/A=="); + +//replacement key Chicago Cash Register, Inc. [gmiFPAzpYtqhdo+I#5TdPBhgP#9Luki#9uuqspz/LkNI#1#8] +sl.AddTail("yyM9iY/jH8CZ27sqkVpnvF62wGNb/TlbavOJiMiz6tZef4/b44vuJXG8Q4uFqAvJmbIjEilc" +"tg3nVNfYfIEKZA=="); + +//replacement key I Fix Computers, Inc. #5neU+a#4EL#0HkYwEIk+L#0#4b#1#8dmmfLfSjBhQo#0AuBuAU +sl.AddTail("hLaRQQ6RgD1LSnnC7prfC350zcX1o6Wt58Yi+bn2DsAsbZPvXkzNOoBST5ellYgVdpBlHrBD" +"AWt7bR0/7i8XWw=="); + +//replacement key Lanier Health Services [ZgcuYr+qVktHx#4HE#4HfRdzoh#1PWzArKGoyfYl#0ZNp#5M] +sl.AddTail("4PehIUoYSkpHpPJb76PQKWOIwW4pXXbQevYsG5DW9YUFiuBe8jbdDfwW8xe839nAYRRl/aHT" +"ZFoiaMo5LDgKhA=="); + +//replacement key Spartan Oil Corporation [npUlQhAmeo#3T/wdfkWli#6x#6GrOeoUKOvd/CcQh#0OIUE] +sl.AddTail("jtIzza66+Lc43ABHBYcszr0JcVcIP+Y+F7EBwbt92OLOcVM+0cOiWIPxQfKEUJfV"); + +//replacement key [ESM, Inc.] [JuSl/oQLViBoP+#0bmyFrez#7lyI#6kyPUpsMOuRD#3hTto] +sl.AddTail("KgizuGQ/j8VNl4mJsXH7MdK9B7YQmRR09Ok+q46X6SX2llrAZJHrftJV/1KZtU7p"); + +//replacement key Kramer Computer Services fh#9#6F#1#4lpMt#7#9#7dS#7nyP#5rYmiedRgbjaFgZSXZuGPOU +sl.AddTail("bz5wqevmSk5XLO+7178Aey0kwrUJm+4nGeXZcDT1K3wf+G94bTBYronpgNOlAB7zJ2DrnER0" +"VVXqFVtUu+CjBg=="); + +//replacement key Gator Technologies h#9XJrzTZ/o#0AoYBtV#1dodZVsGADGnUpOkaqstO#5bs#1E +sl.AddTail("Qo/6lAhaES3f5B/Jx/2FLMFRrxslhMdBJeumMxCNgOq4vgrbTszT5VPIK3pidzdL/LKNPdV1" +"04hr5Gk7L1HRdA=="); + +//Gave away keycode on the internet Team ESD laq#2fD#5UIfyMpP#2FKqEZKToiJV#1ih#3Pk#4NSEgI+B/Ew +sl.AddTail("HrUoTrNTFq0S7QRjoVhc4cGUR4hznPSpkZdAnOEvK65dhiW8J9mPr8Sk3nCP7c0EHuXRQpTO" +"IyZyJ9vEfVbDqw=="); + +//refund because she's dumb - NETTEKny [#6#1EETlTrCvTYAFfRJFaq#6UKqeJKwiYUxZ#0+l#5hTaSwY] +sl.AddTail("6d8mg2tYLFOT187jmjyH/86+ZmP/z7kO3vkfESEc9XXpGF/g5S/dueVhvw1oWRWG3MyGmw0y" +"nlt/ed/we0vNqw=="); + +//replacement key CNK Computer Solutions, Inc. rhF#2#4jFh#0XlHshC#6IlmBvvqtFzKTaWCELd#1UHh#4HavE +sl.AddTail("JH7ZbYvXYaF/a/rGRdaWF7g2F5DABCU+lBPFjXnev49Ee/k+BVeHCUID+fn7EEpGRY0HEPP8" +"FyS3yDfUGCGPXA=="); + +//replacement key MIAD Systems Inc. gvmz#3ZxR#7VpS#7hlk#1ay#5r#8hmjok#2Z#4+z/TYmUy#7#2#5dE +sl.AddTail("umxnJQngWmNmUbhYGoQHv7F8EF8QAw5rPd422x0xCrsv5zpnh8RsMIy2JSenJnGh9ijWn1+X" +"nJV0AeFG0AmyKg=="); + +//replacement key Matt-A-Mar Marina QUrLX#1ImHCHQPMTuArsE#2fpgFe/jSpyabdEqBnim#6y#4 +sl.AddTail("NBPSA9jLY7DdCW+7hzGlTES7vXIY9N1RKJWkBGMVSzD0Tc/exv3l2SbHS9xGL6Bc"); + +//replacement key Absolute Sound /l#2/nzVro#3XgsKmz+ZfF/U#4+C#8B#5XWoyEclEvHaXuO#4 +sl.AddTail("BQ0zmVOt48hb06kBloPpYRd+T6c8lcievKSNSG/zITtZmkNfy0SOfBkvWGxOvy5qEem51/jt" +"Be6QgmUoJIR/dg=="); + +//replacement key Universal Tel Data Inc. maLfNc/#9#0AkK#3HDotfnVHa#2BozsweyNeiBVFIZEnISo +sl.AddTail("NwofMQ75rWYzDUjxnBFcwUWjrG0nxYg2vdfk8TjekDHkEDbKoweKlWRk7b3UfacT"); + +//replacement key Hans On Systems zG#6jM#4XeBWjPRAIxJL#6cjSn#4qtwoWtUwKj/nsGSc#0gk +sl.AddTail("1D3TMditPzxYRUj1FohuAk8hY2fiadQKrTjQzQTrdIQlY0ildko6nY4eGd1mkD8aInqMRrq2" +"vAPjebeZNzWkww=="); + +//replacement key allendale machinery systems [wDtimzl#6Tz#1MddyG#0H#5#4FctJkdvFFKEaPGPRKF#5#9jSo] +sl.AddTail("NYLqsafDvIFpXvaf+KxZFvLUr6sHGqzeexSZYIooGMYOPJu24VXPdwGLMZ2b2cCxRkSXrvUf" +"SwIu9dMPnfTBYw=="); + +//replacement key Voda Computer Systems fFlVCUNVJK/rBRt#1rvKSaEjecfLBgF#6zeQSn#5#9Z#8ang +sl.AddTail("Ix2R4nAb3xVRTi1CvyYhuhmSUKXcUoFgaWPykfRXapNVwv/BMu0hVxInZYfxLqPjktmYezr/" +"ZUGBvGjJKB3bRQ=="); + +//replacement key Aspire Technical Solutions Yy#5eT+z#8#8uze#0#0#8GCOsw#2mFpuR#0UZxemLphFABZf#6#3Y +sl.AddTail("L3dfN46qiJ1IVfBq7twoTPPIcJvPg1yMYJAD4ICDs915ILvw9qYGYItlCXPZ8clbNqP8Li9Q" +"8fVYiWKpGOKeGQ=="); + +//replacement key DATAKOM QS#6YzqZ+tQhos#3/Ji#6#6WDUPhjKYqHyQLlJoQxLbMVm#8 +sl.AddTail("MgX7n0fYEd0pwZA1BGdttWO2zbGhm98VAYibWtdtI+HR5Rrnu/djb88s+zxb/F0PSiibjbRO" +"Jb87fUmhnpiD/g=="); + +//replacement key McMinnville Access Company Z/#4#2ji+XoQQHp#9#3AL#9Mnak+hzU#1szXlGBw#3zXxSaEkI +sl.AddTail("mYewMcWBYYJapid09pxmCrohET/ZORI9MtCSYUeHOSucOYl9b2w+uD+OM7mi+/XlrI61A484" +"fY+amWlWRd4w1Q=="); + +//replacement key Motorola Australia HE#5zX#2PW#0tM#3z#6SANGwZrvxaqTFkMIzhnWeAW#3#7#8Z#9A +sl.AddTail("1fPn+N2EXjl9Y1kIdpZe3ML3cQizpxsMhrx8IwcEhUvHimuV3AjqSSDPnisTE+CE0C4nIa6r" +"WhNtJr+kaAkBUQ=="); + +//replacement key CRS Technology [cFHN#8sGppPWZ#5#5yfMck#4sabe+dBXiDeUMkc#4OEbA#2#6Y] +sl.AddTail("ROkvdyiFPsQQ0kciwF7v5W7tYLPkIpwsdoFH/WZuu1Qoe0cNMirR+l3EAy59fekrBqMxk3Ks" +"ZhzTEwcn5Y5ysw=="); + +//replacement key Computer Concepts of Louisiana, LLC [jiJf#5fiSya#6pH#6ChcVsVV#3es#5#6#0sD#6FY#1gROD#4pfJuI] +sl.AddTail("ETrw18NWgyQh4ZshbKFdgg0gRiXKYNqncUhbe5vm6N2bDIuYB9reCN7wOxsq4uwmVROarrTb" +"Wkglmw1t2GG9WQ=="); + +//replacement key [Tekworks] Activation key:[RNlhqq#6Y+CMVoNDkG#7#3#5JDRWQZWPH#5#1#4#7rZC#3iAfszI] +sl.AddTail("910g49XAPIy+fem3xHrUnshH4WkgYNp28QxdNEnxah4QijjPkBbj7QXE0Qc5zOOQnNOygRJf" +"3ycBZyDHA2j/LQ=="); + +//replacement key Absolute Sound TH#6hpDbNKQXZeYB#3ffSwUeiYBg#7ArTqY/ayf#6#6aR#9#3#4 +sl.AddTail("TkwkTEILY/Kx5+d4tY3ooaTfk74UrsIFo2cSTQMJXsvsqJ3AWb0mah2VzpbvaMkoSPfAnu5a" +"Httap5wIPuSrOQ=="); + +//you had sent this out a long time ago - TESTONLY Activation key:[jdnxoeVjN#2KZaf#6SHCSjkVBRc#9QllH#3UYITzvEukc#9E] +sl.AddTail("KxjH+4aPqZNpqFuE/12gC3Im4f1WH8qMVlQKM+lgsCUpFHbVKyqvHAUXuPcNC7i4BMQ/DW0U" +"LLs3UFru19DVvA=="); + +//replacement key Vicom Australia Pty Ltd ePB#5XPvlHPfRsui#6#1w#8IqM+Nnt#6zb#4#9Kv#9BtaPqk#7#6A +sl.AddTail("fPWWNsq0UYDJSG0jPFjC12rBB12t03VjnzFO5qSolpsUunNGRcGv3UeKX0mzU3WEKvl93qBl" +"qW8dbggEVsqtcw=="); + +//replacement key Microland Computer Center b#0HXVeQSy#9ETRTy#2ZqZB+dukB#4Kn#6#6nL#2maiUgc#1#6rQ +sl.AddTail("thabxTFNSCststK9I87C0OSMQSXW+rIE25sZFrWdqQHS+58pDoZ9NY7l5Mqyys+cRcF/7vH9" +"Vc9EnRCr+e9tww=="); + +//replacement key ITnorth.ca [S#7evuYSwQLIDlgpyZVwx#9/JxZVYfiqq#3qS#6yccPTuJQ] +sl.AddTail("6kWgduLhdD0qIP5jD1DngMJ7+SLnjFIew6kdveRzKHRlB/HJ5Ovo8UQGWEI5K3IM"); + +//replacement key ViableLinks Inc. LJtj#6#3m#8bknXITle#3#3xSlH#2lFYOUGz#3hJGAUqxjkLAQ +sl.AddTail("27JekL2YpkitiPCbf0Q+0y3iczjfDEqUvzGHZOXj+wLebskOjYFTaMeb97OCHAlmwvcQdJ9r" +"0qH5D15X6tXbeQ=="); + +//replacement key Nicholson Manufacturing [#1shNELGaSU#0qljnrh#7#4/xYSgFQQF+JwmZAmuLV#5#1tz#0] +sl.AddTail("k4lLy7xZCG1ybhgADXmtQfR6o+ZKJ4hR/0MfoicQLORTu6VygJlfjDrurJ+XJyZeHDY5yXQY" +"Vf6lot/q2emRfQ=="); + +//replacement key Halant Group T/A Whyalla Computer Centre [wo#7tbpf#7V+X#8yadvqXeGxPTVVr+E#8NfKNfeVlxii+DE] +sl.AddTail("CAD2fksIXNnw1YvfNJyXiofSxLts62kqRnu6OVBeFx3Df46sHOKyS6rXLMGEZ5sh"); + +//replacement key Int. Food Services Corp. [Fk#0MDUhKv+HrYrYLX#5q#7#9GM#9bof#9#3Rh/F+DvTvf#9PAQ] +sl.AddTail("CDB+JXTSbOayx0ynmZa7n05llHP4/RWALyXM2DJLQcdusDPj7o7aHi0qhzc6DNLosHC45tUS" +"Zl2S6XDvhFoArA=="); + +//replacement key United Business Communications jMgWTMDDuPX#9OVRrlN#3MfUHsZQ#0nRfStezrrmvvHtGA +sl.AddTail("tzIvEGIA/opMOdfbCxvcoVAu5RjCVxWdcWayh+ZY9e8aqsFmex6nnXusCjrpDuvk"); + +//replacement key Mechanix Wear #7LyZBTJMNY#5theb+MtglplA#6HRj#6#5FbffShYuCWNl/w +sl.AddTail("zyLsARf1wFnkmAawXRUIf6r0LcG/iAruJ7hQNYNMLtsqmGuawQEmBDGvPkeRI/RIAPX12W5D" +"oxGUcHajAvgA4w=="); + +//replacement key Speltec RmSlkJaQDRqDzHy#8#2SXngPxN#9u#2#6oWFnLJGrHt#1l#4CU +sl.AddTail("Tvm7fG+GpFgTCrYu54xevUmYlQQU+1f4UHT8Fw1qWIUVRJZ9n5pOVq7zjXXNySWJnowrXBRW" +"v58kXezAdNxwFg=="); + +//replacement key PMES, Inc. xFvN#6z#0FNZNNFAp#3L+#7#0OKhR#3#2Wbx#3xS#1D#4ZN#7#7su#1w +sl.AddTail("hts4TbGx65bsFsKNGcbfgg8BsvUNjqw4x7HsuhgJ7BxoB86ls9+dSs3RtIQgTAtUoNZbI5Yi" +"/qFno8de8XMZ4Q=="); + +//replacement key PMES, Inc. PKuwcarP#8/#5HOS#9#1ejVsbwg#7KSt+#7Imk#6L#5BAW#4RUkE +sl.AddTail("pew3Pk74wXfHJzsGf+QSD1SwscSK0HtOSvivoc1KqqO9vZsZB3UH8TXVYrujM987v/NIJ4dn" +"oTZWUflyZDua3Q=="); + +//replacement key Aspire Technical Solutions lYItLugO#0hASCElUlOO#9DVN/nsitQClDGR#8r#3#5QndKg +sl.AddTail("2bH8FuBkTzWLvURCTz8uNQ4ox3W+NSLowz5EeM6Y2NBv7gPEW0AQR9WaPAer+WJtksW8ZhFO" +"5NUSiQFBx3oXHw=="); + +//replacement key Hiller Systems, Inc. opZn#4dRwkZXz+Irc#2ShYi+gaGepGnica#8#5hRQbIxM#8M +sl.AddTail("iJslXpoUZbZwcMZmoJZntbyZ91pgrP6BpOQxEvB1oBuOqhuYt3nXIIFq4TQiOdjLBT8ESArP" +"JO7tD3hP30x8kQ=="); + +//replacement key Ideal Stainless, Inc STMH#0#8#8sItxtoh#2fe#5v#3LE#1/#1BtNDCAAGapMWBH#6xFs +sl.AddTail("fejWGOQ01+u0SqNN0c6ZFruqyV77Q2eoipCL6tj5DUH/sITNoWzw2MvD8JrBfcGqFKBuJ3UO" +"JjY0Piy/drIr6Q=="); + +//replacement key Kubota Manufacturing of America zeKTwSXfZWllqttObLWGPaW#0#3FP#7Oj#0lGUr+CCZbef#8 +sl.AddTail("oG+3tqIn4IEOZyCGoCD105La4kCGrwGBwEL9ga8KkX8ymCiFRx+v8zveQ9xiCNM+hf06O4G3" +"UchFnzfA32cUcg=="); + +//replacement key New Age Electronics +SfTAnM//eXLGvrWBATmBn#4e#1j#4c+XPHOnB+dhwqw#0Q +sl.AddTail("aHppxVFA/wcQ5O/BX+VHtYAXLasc/l3FEc5/z5SDvXRXZgrWvY8RMuYzP8zDOQ3t"); + +//replacement key Odyssey Networking, Inc. qoX#2DFo#2D+#6ojRDpo+gcMdGRNwEw#1L/PP#5#1fHEb#2#3#9I +sl.AddTail("LA3i3tosR4unRM57ozSu7rG9f02Je4Q6CuPPhzk8Q6JrfeTUXoo0aw+l5pVNwtgmPGXWbzjW" +"eyM8r+Z5mQZygw=="); + +//replacement key OneUP Technology n#1f#2ArSvFFVF#7#3asdUNKC#3vZL#5EGoj#4Lk/n#8Mo#2q#9Sk +sl.AddTail("pUoFGWnbVVQ0B/H8NPJe1/Gmqs/lVvTqOPf30WOLkscGQlG7eVtSRUFEig4oLbZxyGDLTcfh" +"6/9ArNrY/DPVnw=="); + +//replacement key Cartel f#8kf+QEbzlLpRe#9XvaD#2Dyylb#3CF#0+BTM#8MKNCww#7#0M +sl.AddTail("/zDy8639PSoifsjWi9KYZ7GnEZ9VhIzlfIOaWnmTaSRV9HVQ2Gf5YM17UyZuzhZOso99CiAC" +"783avc3k3cC4Yw=="); + + +//replacement key Certified Printer Repair, inc. #0T#2DVN#9#8#4O/Nm#3+Oet#2#8#0JBCuo#6x#7mT#6KmI+Vr#9fwnc +sl.AddTail("t3xyZAk+EtivQRwN95HQGWzR5wN2bugvhtqfQhsiBj8SgymKUMQH+jLaSPBCuCvBRsEZDauH" +"sZQup5zah7uavw=="); + +//Joyce entered the following August 9th 2004 + +//replacement key ITnorth.ca Network & Consulting Service LTD. Rhru#0+XR#1hoNLT#3+xPwO#7RwdQXlRdfXhY#5#7QP#5gsYvw +sl.AddTail("XUpHHEf5/xYcst/L/ckgJcbUyGJuDANoNWeEf2EuEihWCRUChFWlzSxjHZQ7Y/170/IU4bGO" +"bTU4QY3TbCXg/A=="); + +//replacement of key Interactive E-Solutions LLC F#1TTVNb#6AhfxkMsFqxUy#9v#8QeThuFQ/ORxBoHBIX+AU +sl.AddTail("dwT2tBpzRdp6gkojRFhm7qO5qEZE6fun43hxqDn8Y6RihsnNZPswIB+DzcoV5bgZ"); + +//replacement key Net/Complete, LLC h#8RsjqG/UTniy#7c#0IpX+#2#6rUhGskpYpjY#9DsXaEAspo +sl.AddTail("pUnSBoDAUsoVl11A9GGkSVyz4b+KIP3IlaRcBeCr40HTspE1tQDoisObqacDNb2U+IU5mL3X" +"FCMaoVfyTQopuw=="); + +//replacement key Seamless Solutions #0Cws#4l#2yUnhkEdX+lGqJCtnMtStFO#8zaWuvVQO#6v+O#4 +sl.AddTail("9VZ8ssOtRa1Rc4tftgwx8SzzkHduyL8rrXzK+dU3ynyPZaP9hddc4IwpQGSxMWbHjQTartet" +"zQ4iscUdINGNxw=="); + + +//replacement key ITnorth.ca Network & Consulting Service LTD. V#6s#8#1/eBZFI#5oI#7+C#4CZxI#4Tzk/pxvIoyICY#7Tj#5#3aY +sl.AddTail("KEVYVeZum5HDi2BGdKBjJTGZ7otVMDASDjRvVfRntAnupqJ9lsasSeDTr0McLi3EfQXVWHx0" +"6xXLxA76DzDXzA=="); + + +//replacement key Security Watch Inc. lgQUFQYzJHHXS#8ye#6U+bhstHqllWBQurIY#3A#0#5fbY/#4 +sl.AddTail("dGVIUQH/Wx6NTaHM9/j7u+793iFTuuxBGGB3oHM3szZutpu+XPCH7efhmvJZyaitrFqJ58i2" +"FO+5JJItn+zirQ=="); + +//replacement key Smart Home Wiring Y#1#7AJD#2XryWPm#0kLSBgE+so#4Ivt#0s#9V#4cIG#8#4MUdjPg +sl.AddTail("WZuN+ntBt2eIsB3z90xM1ESYjtnibUnNXe757KJMy78KbsoB89uK8PC7LsSxouTgSNRwiVhx" +"l9tof+Zp9L1e4w=="); + +//replacement key Lutheran Social Services of Mid-America +QTBQLA+WkgihxvSx#3DM#5AMULXu#6sJhj#8hll#1pFnYm#8 +sl.AddTail("bbnQZ1dd/qk8t/dVDkzTtprpcr4XnmL2yIZADDLsVRsRn2zEJ0ehLq/tRHyG0slGsRc+3z6N" +"GwGpIS76yPperA=="); + +//replacement key VPRO, inc. a#2FK+VzBYv#1RIiuKV#9CBw#8a#5yEIoaFenX#0vaQvNfDq#8 +sl.AddTail("JGpAXrON83gaEIbYcOdfBakEglmG26pC15REiqx5KWDkrUqkh6R4m0hLgUurlXpB3L0mET9C" +"LxMELsmENN4oqQ=="); + +//replacment key Northeastern Security fLvWghG#6CEgRZ#3t#3W#7bhes+#4yNGAcRRThdSUTWhb#8Z#8 +sl.AddTail("Gw68n78UDEMtvOvf23nUeP8WKYMGsVNeKbXz+lgqU/Hd9QncYcT+kbI3slqyCUICQa1Sg5XT" +"v8ipc3ZUypXPKQ=="); + +//replacement key Halski Systems, Inc. MnY#3#4LuvCOK#2iHnwctR/xpS#8VU+n#5qNjz#8xeT#3dWTbE +sl.AddTail("02IjQGIBv3+faD2/9ORxciJw5R/mGUCgMVY3RAjp1NYPK2fBbNiktL5nlDgR3h5mUNK4T6UA" +"3y4QxFp9f+aVyA=="); + + +//replacement key Lanier Health Services ErkZ#7S#3ZmKYQTM#5NHYe#7#2#8tFg#1llam#4c#7#3hk+g#5#0SXw +sl.AddTail("X9ZvIzVoVf/Qx9yMLE03/ig/19v5frt/ttZFf8vxEoHvm8P6v+kR7wYHA1s79y1YmhMhrPQy" +"VEyd2nMe3vL25w=="); + +//replacement key Decypher Technologies TaI#9wJCmH#4#4m/MRqSY#8rPEkRVKRGPdX#8#4#1UELhVKR#4M +sl.AddTail("t6wVtysZRFz+aJ1AEzCxVYJzzinpyZJQFvq5VkaqAAjhRkqVKy+Ur5g+r2eH6QPHY/Qv/L/Z" +"hLgMw/MGgsOOdw=="); + +//replacement key Turner Technical Services, Inc. MDO#2BivlsP#3zKWoHi/kHdSt#1qD#6EK#0XXJMnQLE#3S#7qg +sl.AddTail("K9HQpOO/18FWXTzc0KtQsC27hbmw77h8EjpaZYvT+Lcd7SOM9DHl+5vSNihkf8gTptTa8A7Y" +"/72UBHzjhFGO8Q=="); + +//transfer of ownership Cardinal Communications Corp. #0bUJcIDqU#3lnayxCXTCdwm#3Zhc#3Y#7IfUh#8/zeioEbLM +sl.AddTail("UxacJ4PoJ+rh8ywYiA2JGsDXAL76GFuB3qJbcPa0Fvi//GcafghyUsSPhlhCyewb07PbgOyK" +"07KC7jrJJFI3OQ=="); + +//replacement key TS TECH Enterprises, Inc O#1ieUhhCNMWJZUpzjiooWmBjZiIDvrzlHyF+RSeZVw#8 +sl.AddTail("xFCPydsJkcnWfG8PEzgN0L1LSd/rAkY/V+4E4Ft5MHusa0B5cNc4ik9o/Ix8dhhx"); + +//replacement key RODIN Computers NYIHF#7DTQqXFgxbEujY#5PvGdEQK#9OiN+NALIeWvbEa#8 +sl.AddTail("0vk0vgGx7vpejdh9O4fG0O1JeLzZMnSkHN5pr8POK1Kq7QixRVVgrVAzAkVhchsh"); + +//replacement key Wired Up Cafe /GtLK#6yflA#9//#3PKUK/goKyWGduRPgb/nBBk#7nIBjS#8 +sl.AddTail("T+QnoItTvIcbQfzThqefubh3opyEtUvN1tloGSfKIZu2JU2tv2jHBp6dRZ7dpa8WJvFNdVHL" +"FX3vGVWYtjJARw=="); + +//replacement key cmx computer services hy#0HXbk+#1V+lgV+petVMAN#1Elx#5jRSIySE#2#8KH#5uW#0Y +sl.AddTail("w2wuYBkoK5Mp+Ke30QLvN/Qk+wZRQJV+1ZU+/vWFsrYTb9GqCI4BSmgozPiA7IcF/Rfht6vR" +"edjmFiRz8mWnCA=="); + +//replacement key Omnor Technology Solutions #4rzWZHLZLpt#3hJdDY#2Dw#7kPrVEDm#5lwQre#3ONc#8DWIg +sl.AddTail("TjmIrX/a0NDDtplwt1XJ5nBj0YqXGGKwyyuvwsvzNhkrAUB7yDzrtBg0QmTykQOyqbNUlN92" +"YcWYPa9bvAf2CQ=="); + +//replacement key Voda Computer Systems NMaaMXRnuHECunBDam#2#7QXYn#5KArLlEUKXcV#1uqh#7TA +sl.AddTail("t4nYCwOwUQBmeFJcsJPEnJMyu6ZmiugEYMay1oISm0s2iL2dyBpIaOHmpun32NLU97TsaqKd" +"WmJdXrLpskQ9XQ=="); + +//replacement key Symasys iRUW#8jElfWBwMemwdAcTPXGaDUeg#7S#0/NcNox#0#7oPdQ +sl.AddTail("nJq4xbtRkW+bOhei5uZruuC735gHUyHoA7DoQE/6jOac73R7KUJu27kGaqSweTwUVAw4BUK1" +"4bgbBeVyy+lW1w=="); + +//replacement key TS TECH Enterprises, Inc #2aQLjdeyyTZIZXNs#4YsExew+#8FVJIOPIDBtCv#3#8oFB#4 +sl.AddTail("u0/I/+2RTPJKsN1UILB9dZl01TPsJAGirzT2dEVS4Mk/vS4rorUX+32MXqto73jWUXEJVqAw" +"/avzj4cKc9E5hg=="); + +//replacement key ITnorth.ca Network & Consulting Service LTD. lpCDp+#7Fl#5xU/baqDLqMaIQ#3uVfzYUN#9NVXMuic#5#5#3A +sl.AddTail("H/AHtO7Xdd4Ua9EIM1DAVJzZV/ZEd735Cp1eRNbFqRZrnZCF5aNQR9JpL7cYAY6OcyANMQyw" +"SBF4Xf8pudRAQw=="); + +//replacement key Decypher Technologies BdGIxj#2fGmmQSQbcA#9SgtFK#8#1bg+LGlYK#6#3MnlCSJaY +sl.AddTail("4iAn//k7mKljnc5pS0Y2AhO9VJdhKOUJ5mAYQmZroxEIV0M3wpkwDXxfdNcF5A7Cr9H6huDe" +"0ZH6gz8mFXeZ6w=="); + +//replacement key Ansutek Commercial Ltd Btsd+QvbLJdw#4VmhqLz#9lgdY#9TVerEdfZGMMLM#2eELQ +sl.AddTail("/drXnuMtBGmxEKltbTV19buOXl61/P3cP+K2uV+c4O4agyKaeb0Oz/Q14ObOEL6q"); + +//replacement key Interactive E-Solutions LLC Wam#3TfsqhIuJRviE#3H#9#0MjoHPoDqagCjPkgnIVbvgzk +sl.AddTail("iMJXjp4Pa+vD2VebhJC32QTcQff5CJwMjSvmZClnusSU57M1hlnkabJl9qTgZ0zL"); + +//replacement key RADCOMP Computers A#0SmbWnX#9#9Fpdy#3OonjOcpQC+/nqQn#9HWywJvDRafrk +sl.AddTail("LOanLUNCDpqp9RXlc271gsCxEb47z2byrJnXbMKnIK7CTCjUqv1kQvwrhwKHfLnuf1/ZThux" +"85j0dhiG9c0iEA=="); + +//replacement key The Computer Hut, LLC AugZy#8YA#9#9Nudi+w#9XgokVONZVTiMZllWrY#2aloNBKs +sl.AddTail("FdmSAzwgWYjUE994zxYlTY7yML08SJIoQHOr5iU0fJ9p8ZzMJ6Iyeogn8B3iwJof96b8fOS7" +"URVkB0keikXQmA=="); + +//replacement key Steel Systems & Design YJFoERRwNxkwf#2sbZjTJh#1#1DsDZwce+VmVSBVZgeDFo +sl.AddTail("vyxMCPuBcmwViK1lTK1Iv5Trp0ZaUaK7S1DFYMAK44C+yVX5bAJAc2ZmLGY+NQAJ"); + +//replacement key Catek #0RyQb#9#3S#1QetxCCezY#8YKK#1#3JMjfy#2FWIFLK/Q#4J#9Mc +sl.AddTail("+1EcyrH5f6ubd6QV8+hDW3t2DpPtR/ip9pzaW9A0kEuxRie1OBWsY6UfNBhgPLJxxabO8T0z" +"A97HaB4s3CG5Rg=="); + +//replacement key Gator Technologies GcD#3Yzq#6uYytCkJqRUxxfCuijHEtoxNnbvPaZOo#3MU#4 +sl.AddTail("/veXxWrHuYOhzyY8GRp/Kl8fZ78A2CJ5tRVkHzL19Xn66abgqyuvtwru3M9yjt9x"); + +//replacement key cmx computer services fYBiwzVyLGxBAMm+#2y#4Xo#1txo#0ZaGGTgYRt+k#5#7#9ORo +sl.AddTail("3ppFp1cwFdc649hVKxRsn22Cz9GHBS50GLM+POIi9T4DR4vyQqXSz/ciJ+MKBwjsgqNuBalO" +"9TDARfELv7UaCQ=="); + + +//replacement key Halski Systems, Inc. aiHfM#1#7#7NSkjmWsCCOn#8PlOYY#3XPdn#5ufAUwrziZGOc +sl.AddTail("PfFGN1uyVXX0cYZHoOlY5j3Ikl4qO/W1e8a/m0UI9rovbsSC/TgMDjMlc3D2zWFZuCkKzHsp" +"BH5BP51I1kcKCA=="); + +//replacement key Innovative Computer Concepts #4IsWKo#4VYfAWfWIc#0CsM#0W#0KNVqKlPr#9FDrmMm#7iu#9c +sl.AddTail("B5+8SjioML+SFMYs2PA6pyHAeZ9pH5I4LlPkwoHJDaJbVWiBxC7OrMZsyYuaV0bhjuVdwztQ" +"sZiBxltfv55/+A=="); + +//replacement key romteck grid UeEQwF#7qmI#3#0kLro#0JbHzexBiLWDVGfEXPv#0f#3#4GZX#8 +sl.AddTail("6Am3Uz7ZF1IOnhN/o4XmCgiljKzy3yJZvYQIO9u9Zd1LziwW7iWajedzUyL7Oox8T9rjuHiP" +"LKhqNdiyk/y3vw=="); + +//replacement key Total Technology Integrators LLC vZ/f/dmlt#0fGVLOfjGxI#2L/+eDQTRiYqjbb#9#8g#3HjUE +sl.AddTail("knnL6UU/MEZhffYOACZ6qYp0+mmWVEqUicuuJyK2f9ZNjqhkwcS5r2899nYGlAA8l9SN035/" +"9oIlP0edxuCG+Q=="); + +//replacement key West Coast Network Servics cC+uyzhj#2#9bxDYLDS#7NHQqfYm+x#2yu#1mppk#5ZMH#3EWA - note the spelling of Servics for this key is supposed to be like that for that key +sl.AddTail("dXSVFFjf715XpJXCBnIeJ22hvFT1WA1f9JxMc4/iOmB6y5y21gfplHabf7iL7rvWoxePbql7" +"IXTLuvnxmxPRrg=="); + +//replacement key Golden State Networks, LLC KY#4Ky#8XSOiGPFhPIf#9RzoVhSrNo+rbq/Ho#7#4zIGqUpk +sl.AddTail("gqTH5qJidxNthuXoYGk366ZjEn6KiUUGiqQAJE3sfJsFt4CDQ5Nx/HJA31NKAUjnPtS21UGu" +"/fAmbUnwnQw+cQ=="); + +//replacement key Entry Guard Systems V#0S#8liJlE#0PFJ/flycVYW#7sdqdSrlpDvlOLFqtz#3eEc +sl.AddTail("KnDC6mJ76PVAaZ4o5YhjmRIzoipeCCSpm5cjNGy5INp2cFE+ydnZzOvyK9I5VkTJ4gE7PXoT" +"xndU7ERvBJ0x1g=="); + +//replacement key The GroundsKeeper, Inc. y#7dqENDcemILx#0m#0PgYTaCeGD#1#0qN#5lZE#6+IReSx#5WM +sl.AddTail("cew3tEi1gZhie/FfAuynzzQYa9laCAQp4ALcu6icaXHnXxLQ1uS9lo6TxF45WHwBDGeON0/0" +"17/eWr1eYmWe1A=="); + +//replacement key Blessey Marine Company DQH#2OZntNhH#1CrXPzFcZgbtfwYeWS#9lxgL/#4#4QeVc#5s +sl.AddTail("Z5mRMZ8nlb2G04t+0i6cpmoHJmOH1dzZa5gNVNWlszUFKb/0zf8Tt1p66YV5nnKpmfXov4UT" +"/G2E1a+0tct5xw=="); + +//replacement key Decypher Technologies t#5C#8iqOIuV#9#1gtWBHMBGJP#6PzBKuNQNjfDjdsfi#0zgw +sl.AddTail("TdDXHeDTX0SSyg93NI2M21Y0d863WGdjyt33OiKYeLkSdQII5lkMWkM7Zr9BxVwbX5CY10J5" +"5VugzcggKNv6UA=="); + + +//replacement key Mori Seiki Mid-American Sales, Inc. XlSH#3tnYpaDzQe/fnCqwPtjv#9fJu#6k#9B#3WGcxbc#2c#6o +sl.AddTail("HJ0aVSgtpEPp/HX8LJOlXnDdQU1ywSBT5umwbhRhUclWlJZEzzDg9nB+Bw0n7IemB7dapQT9" +"Nv0ZUzu+nesdjg=="); + +//replacement key Footsteps Computer Services, LLC dBfeLJ/+d#2P#1zEe#0Yed#7tnY#6Lmvat/f+YZdmXwurXxI +sl.AddTail("x2118RnpAoh3iwTQo5Q86EBcHUqjNOwSjvGLipwt9hBOSqR2F0zOQs52ICFucHM1GX5kEnit" +"Vi4hKaCcAKEGqQ=="); + +//replacement key Computer Fellows Inc zG#7GAFrJuv#8cRedkzIVH#4j#1#0xWJfjEi#1BPP#6YSaOF#0E +sl.AddTail("zYa089tAMoZWI0mscVCoarLg4VRan23Vi+DtSIVVHF22UKm+uw+RJszKovYfpaK5g+3m/JLe" +"1WfWo7XQggPk9w=="); + +//replacement key iTek Connect, Inc. #0zzSBzOWJxIggKh#3fXC#2eiqL/xbRHt#9FpGXt#2#3/CDYM +sl.AddTail("oLocvrmD1hRki5517KxIj1H3n/tABFtsFCYULKGLuRD6TCKUHvvCZhA9j690JUHnL8ooRVjF" +"Y1jqdVdIwsamOw=="); + + +//wrong order Eldorado Chemical #4#0f#6#5#2Jraj#3K#9F#2#2bftZxvtzNLkKs#5/oDUrGHMMrPhs +sl.AddTail("w3+yLKZSc/3k3C709YT1fMgTjNeWY2ES88LjM1aPyjzHYD1Mo+3wBTGoVqGgfF6QF/SKm97I" +"IDln5QGtGdoZ7Q=="); + +//replacement key Filterworks USA FUcGal#3mrdaMHwpAScoYTdRMUHJkibwNIl#2XOkWfcNg +sl.AddTail("EBJ7wG+79Z6sRIoj+liCHuU+uT2Qdy2ITv1nXAAcsLDyc49Z9emqeflqLVH2nE8Q"); + + +//replacement key Enable Technology NPHX#7cosbFEMmOXEycvRw+G#8vf#7cMp/#9oGVnU#7#7VK#5s +sl.AddTail("5P5euheqFscHKxCojhxnIMwYO8jY10rv/+x65eZEttqwrxmHSn+bT+7twj5+tCNvrc9RbmXS" +"weVqE6a9j8RqeA=="); + +//replacement key Networking Technologies VFQgtSMhPDNTc/ybyQxWCsFez#2bXgrZpGtnFztTBNMY +sl.AddTail("5BQESiuKoPg5RmWMhuZncyYRWIF7Y05H2+gLJY48OVlbzzhd7s/b79LECfhbfNWq"); + +//Joyce entered the above August 9th 2004 + + + +//replacement key Interactive E-Solutions LLC #9bPUClw#3#2xVw#9#8ev+x#6c#0vQ#7hRWuDEgZ#6kT#0#1F#9#3CDc +sl.AddTail("k3JAr2ceI9N7lvrkRtXk6pXo+vUPRhNDP4gC4bQ3LYPt5+1buU2pRgPnxsoJ/YEsj/3IZ+CU" +"ReBteFyD1meVpQ=="); + +//replacement key INFOSYSTEMS On Demand Activation key: #4OfqMVGXsBbGAXy#0+F#3#0#7d#9s#4xiqjW#2w#7sCQ+gjxB#7s +sl.AddTail("0G/Lsj1eVU4C1tqCTqCI/PzYk+RcGKie0qJaaXQbix/WaG7lHigD+IXT26cKBRJlDuOlCZT6" +"19a0M9ZCA/0RZQ=="); + +//replacement key Earls Saw Shop Activation key: CrqH#2ka#8MbyBq#0UQ#0GXbDXJvrgnqjMwl#8FuaExEaeC#0 +sl.AddTail("q1T3EH2hluBoKHEKpNCwRBoKkTk9S8ABQcqYf73s9/Z55idAxdOhcTx8z1r+n7Ap+C02wTT7" +"zxXfI3qmG3zMfg=="); + +//replacement key Mason Technologies Inc. TJODRHX+OSaamis+#0CTUKJuo#2zvUELJ#9OWk#9MWyWe#0U +sl.AddTail("pXMI+Zr+exSO58zuYKNy+OmSXtJ1z+951dJOuOQ0/0ds8WX/sFUPSjOgTzzNBabRbsoAcBR1" +"D9oLQ7vMD6dJmA=="); + +//replacement key HardSoft Systems Ltd yQGzYwIOMTg#4#8MYdc#2Al/R#3RGoSwVs#5kUDpQszYfn#1M +sl.AddTail("tvpslE5L9zzNmVYA2W8MeNuWVCoKiP2kU7WE2zdZARd5rsR9r/pJPC5GvdnW2E3kPnbylqst" +"78UXCRR6T3HV/g=="); + +//replacement key NetSolutions fSFARrfYc#4e#6awrjPA#1/Q#7n#5uAGykXeC#9biSzlSqdhA +sl.AddTail("nBiNiUF4jvIpVHx9M7v3R/ehpkQRCENYycdM0nlNY/3+/ApVbWjrA8BHVI7tw1DiEvEZn7hZ" +"YNuBYt09V4WGoA=="); + +//replacement key Voda Computer Systems e+TYLPebMD#0lMNexUGlvzBoDTgmCH#5ncgX/GZcAKcZI +sl.AddTail("SZZclhzUCadCviRXDbKHiVHgjs4UHCD0Lmgdgk8wCEgpt2ZXo8W9FqiTatsMDQkW"); + +//replacement key Computer Maintenance Alternatives #6aPbmBA#7xCqG/uWq#8vhkma#7OuQy#3AgArzZc+Czw/ZN#0 +sl.AddTail("3J5kkbHRmGLJlHPGXvFnIDLuSVlvaKC6+uh6eb6cHfw7L87Rj3ZXNMEIClK1uRV4y5J+wmH0" +"VoA3P2tkZo+TwA=="); + +//replacement key NII, Inc. #2nV#7zII#8#1//#7KVO+#9mWwF#1MdjGSHvGcA+k#0mkiHW#5jo +sl.AddTail("fpIaFGHjAvlHKZadoOFXrJPUuiEYwxYeCWEE4qO4B15mrAB7DgQMvhQoMxjBaRHRXuqOG8Ju" +"A4gUgh1Dql6wbw=="); + +//replacement key Johnson Communications, Inc. FjmCvkOth/YMqAgDOR#2CUOWn+IQOmAXXo#4#6zHXUOZN#8 +sl.AddTail("9DbKgx49k/Rfqeud/aL+MXkBhDSVlDT1aWDn1Ed5r/pibzL6D6TxPWSiYxNVTlxr"); + +//replacement key Tech360 DN#1pO#2f#8X/lxsGCkkoq#1eyTA#5r#0oYrlh#2#4hM#9z#0Ng#5Y +sl.AddTail("8LJi5e8LFIg18O9ybC9oyVz4n7+IX3owHskUjiGx67etafBPl9qJhce5Lmomv9h2rQTohjV/" +"DvmC5daY9T3+hQ=="); + +//name change ISYS Canada Inc. - Calgary eoLNFxuJZrTvrplXU#3Ez#5yoqIf#1hVSorH+#5KE#3dU+dY +sl.AddTail("UMID4zY3J+dWUVUOPmeGhpo5ZMB4L0nSXJ081rvfaWQpQir7PsZ741naVvj8OPmwsbu+U46I" +"fUgpQuzyRFc05g=="); + +//replacement key Komsaff Ltd uZ#8GzLCN#7#8#9G#1+dK#7PgDbPn#0a+IHk+e#0kxuHaqRVMcY +sl.AddTail("WcMbn4Y252+i94MP+dbBwVf3T1DXKgMVD5psnymiJ0w/s+ErocoMD4lL998TlAQj3dbxpAgO" +"IyLW9azIuYBIrQ=="); + +//replacment key Motorola Australia Pty Ltd oRtjqsxNk#2OqO#0#0u#3roRBtRiOuQoUA#9AA#3Q#5I#0jfiZs +sl.AddTail("oLLfRv9vTRNwEUY6EGgfJw8OpOEwW4mzbDPtUE1Z6Hmf2zR5pqApqFljzR9AY3cprvHeV5oC" +"syCePb58Z/ffGQ=="); + +//replacment key Motorola Australia Pty Ltd #8wyshdN#7#8#3bU#3FZDDOWUD#1G#2#8#0mSKVMmBEewDTkZexE +sl.AddTail("cUe0S+XmgObQJu+jQZ2PpCWuo5YYGWh0R+BlbB1hp3Jd57yoq6mK2qPuQJ7pCoiepsU9ADHM" +"KBQNw/LFJTc4/Q=="); + +//replacement key Motorola Australia Pty Ltd D#1ed#4SQ#8MpIlWI/Q/OUmvasT#4F/s#1awkq#9#1+olmTiNE +sl.AddTail("ACMeL6hLH9etMm0Mo26l1xHpYTSp3R2J5dd98XXVuafMMrFL2mMCEFZd410bwVTR4N6qcRy0" +"XzSCzncW7obEBQ=="); + +//replacement key Motorola Australia Pty Ltd NoAcKmActl+peSmt#4BGqF#1#2xaoRATO#6lobi#2JJOgS#6A +sl.AddTail("kpToOUSOzMmT9LJUiiCmbm0rnrSU8/IVvYxk94iY8lJYsVTFLwUtpUyitxvapBEJ86YvAdZ8" +"84QjYTunrMp29w=="); + +//replacement key Motorola Australia ZiwBf#5wy#2m+D#1YPZ#1HEYEUZGLy#9C+fgVGFm#0J#3C#6Zto +sl.AddTail("xtzdvJh/EiWV9+VPqajCTxSqiM/gauYhfP1lVvotVT9PNjs4uZ0w6W7aHRSgzwCV/F6s41Eo" +"//7vuGcPUoMzog=="); + +//replacement key Motorola Australia rDHba#9+OLqx#5XzkvQi#9fS#1WNCEo#0+uFcnNmjMjka#0b#0 +sl.AddTail("HSS0AD6OSvowjdqaGlOGomtwuuJfOS3vSf626NOE8EDpp3piH4xQegbW6Gd+PtPQnN+n0qm2" +"zkzfxSWzw6FpjQ=="); + +//wrong name Computer Troubleshooters - West Ryde sFR#7#6+#9Fdjtmy#0TOv#7Sd#1wQzXqjCGDpBAW+XC+KiJiI +sl.AddTail("Ez0jvs0WtrfmRGU3Tc/cleYskxDUZyvcic/awiv6RoRT8gwheplQYcGHWpMPTjw5giay88QW" +"20KbuIyhx6Nbmg=="); + +//replacement key John D. Marcella Appliances #7EAbnISuj+M#1ggGvLRbsB#1luwKhSXtRArp#8MnkWC#3gs +sl.AddTail("8zacBl5Q6UY8dVfzr2HRlwv1u8uJNiSUYfUuaIFOxYgM1SrzPlNuPBxurUV5phutlTZqy+bk" +"WQOc2R97wR48NA=="); + +//replacement key WaveOne Technologies Yo#6mfjnJho#0#2w#2T+NqoVrtrW#5HnQXoDTocpQ#7FYX#1#0#8 +sl.AddTail("TFN+wUk3xizg1G4nGE6oB4ijRXd+un1OraozKhyaVoO3cNu/AB1eFO2+f0OILMaqU28i3env" +"3nyFxF4ALSJTUQ=="); + +//replacment key ITnorth.ca Network & Consulting Service LTD. cHQCxdlUJf#1WA#6CUXWt#2AEjLA#0mbRuBXtH#1yqTNJMdg +sl.AddTail("k0pAUailJ2QoDUFkK4Z0B7MFvgmjI9MnOLrQS7AmxTMI0QQwiDz8TIaOOSfAoKlGr/NCap7I" +"SO1Rdyd6r311ew=="); + +//replacement key Motorola Australia eMW#7/T#3ZU#9gFFso#3IWAc#4s#3DdWMCITHxtaDDGv+d#6Kk +sl.AddTail("yGd2M/TVXg59F149h7EugyE6wvsDyMIfDAijubpbElXh8QWhwGXRr7asAzXHSUGeYwVYLVBD" +"Gsp5NucDvazPeQ=="); + +//replacement key Computer Troubleshooters - Ryde uFTagUIldfk+yz#0#1o//umdDQGkYcWD#7vpGDsJWg#6pfA +sl.AddTail("gp97zdDIc96XV5+YatQcVbnmQn0Bmr9F4ePHMNFIHw5TtT28q6Cj5vNoM3OBLhbF"); + +//replacement key Outback Electronic Services Ns#4vEIUNpVELNWv#4TpEOEY#2OfphnTRE#0KEnPuhRR#6ag +sl.AddTail("yVegbuVT5Xqd8J0dsUrzTofDjPL1z0jgZ+FYDSvsVXuq6U+SWuHzY4TPY408+uoGkrrR57vL" +"ht2XM1CYy4ZZMw=="); + +//replacement key ITnorth.ca Network & Consulting Service LTD. LXbiCtrPTNQY/ugajzSYmVYIruedsFjZkdPCGUnk#5tY +sl.AddTail("oX8arqCe1C97UigLz5wkjrpJynYDIFEk8dKeWtAcLgPmQJTpRzu8mLGmDxYtYCyN"); + +//replacement key Sage Technical Services eVt+#6fod#7M#7#3z#5ozoImHrVAZjFNjWGKugeJYFvD#0FvY +sl.AddTail("93AaCmwZTNQXmsqP9oLv9IXEQO3R+s6iNk02ejHZbOBSqR1+TDaz+k1NnaV8A95bY+6Iafi1" +"SnPJqV9BGKbG5g=="); + +//replacement key ThinkTankIT LLC /A#7WbecEjpGiiweNSuMlgjabW#4A#3Lv#2/McOkIrPbL#3I +sl.AddTail("kqS0uDuK8hcyrSQYBklzDw7vwlJQbasF6u6mJa4iXu82FD0C1ea483dsnTjR/hR40Su96rIm" +"9Om/r0TaAep2HQ=="); + +//replacememt key Norlan Integrated Systems yl#5IEBqsYUyFVrI#4OZQxp#6iKnUoUlTb#1T//#9VnZeNY#4 +sl.AddTail("GtYcN8Lao6qQVV3YVMf8ImuroEqwhv4qWRMCJ7LXm2bNCVzOkWcQyYfP+6n2bxUdgHj+8Yz+" +"VFcpPC9hb3UNnw=="); + +//replacement key MIDWEST BIOMEDICAL SERVICES hPK#6#8HPoSWbrpCvtC/AtiackgUlLr#7ruyWN#4#8+elBX#8 +sl.AddTail("RKgc6vPsgqqEBk5rzE7/Mk3y52uaEi+omVkzLQkrPouRTBt4ltKc3TiW8AIs4JCsye8kQFt2" +"BkwASEXzKe5Bag=="); + +//replacement key Motorola Australia V/glr#6AoV#8Oxnv#6Xacz#0p#6x/ITzMbxQlKIHClIHj/Bg +sl.AddTail("QLK/BNAsl5s+WruHiQzSIWzt2mHHK2SU0ZsN4XjMFaqamT7noiMH/mxZrJcvYnMTUxPkKQdM" +"rrzSqZES/xqzOg=="); + +//replacement key CNK Computer Solutions, Inc. TCkqrbKQdBnXmYECBkIeXpSDv#5g#7#8KJjdxXDm#1zB#9YM +sl.AddTail("J8NJS+aaoZuanEmH/yjWbZOkXACKy/nNsoL3SgLbUix0rx91fWpM1tgi57v9ievZiTbMCFFh" +"rJC88cnCWgPKVw=="); + +//replacement key Lexsys qU#3mxJI+G#6TVkKEqjtyLKci/sQr#1#9/bOcWyQ+JZPc+Y +sl.AddTail("QTGksFcBCbnrEpXM3ArlftYaRE0lrE+ZXhAzFtBH27RunJb2oNHgQ79N/scH1SFw"); + +//replacement key midwest networking BxcFIlytY#8oi#9gJ#3RNvZ+#3HyUyqs#8jKo#3cMf#1B#2HleA +sl.AddTail("22iAhv1IQAdfLN3iCckrznU+Ju6Hx8OsXbo5t+1khipIRaI1lbSuq5i99Hf7JZ375tFkVa4N" +"l86dPKaDOMYNNQ=="); + +//replacement key Halski Systems, Inc. #1PY#2Bvw#9AsFYr#3zF#4Id+#6cmlMaomEZF#2#2v#4YysPwU#0o +sl.AddTail("5XB4vmUWe+oCSCEgz4B7dsZveT8ExtxSTLMY6hIf8UGoIVXrJ1AFNw0sVee++9uRg450iglW" +"RCKC+56oPYJAmQ=="); + +//replacement key allendale machinery systems +fJQ#4sX#9TP#3nsg/KmDtSy#7QGRlLcAAOqtL#2nh#2kFWHs +sl.AddTail("SZYkwWJnlDuEcXqkmhl+eeOyEeV/LSgayjMpVFCKN/r1vSnR+kr4rU/7ncmbV+656cnShBDS" +"xVsioVM3ErQDog=="); + +//replacement key TS TECH Enterprises, Inc SVLkziQt#6ursRbucn#7k#5YcOVUgpdlwEWgqTMynBkYjw +sl.AddTail("2tBucL6H6oPRquyVk8FxSq30Xdgtsf1MquDrzrQBk7TApS8rYmsdux6icGgv2ndG"); + +//replacement key PC Universe #2ZWAbGPg#2KBZeR#5pBxdVO#2E#0lZdGDvEQ#1#3mfyG#3XQHE +sl.AddTail("jHdih4P7irQFtCblMh92EF7/rjoqM+LJMb2pEr4jxGk4R/aejuTSyGYi+LFQ7uF8ng+W5wYi" +"XnguPoCuVp7g5w=="); + +//replacement key Southern Tier Graphics wdMDriPatgu+VACN#6#4WdXvJ/OqF#8tBSfqcuFsmQTrN#4 +sl.AddTail("7Toh2DjgbYDhHJ73vqrVl3ZBcfuqntBlRhv2uggBn/a/GcFrseCV4gojK29dkojG"); + +//replacement key East End Computers LLC RZPfUkj#4I#7lC#9nseLWW/CO#0#7CNo#4Z/mrloc#6OyDRxik +sl.AddTail("K/SWtYK4XhaJkp1fEjmvQiI7Ry37DximAK3IkJn1Cp3w+s+eA096/iThxQ5IH10K2fp485t7" +"dXSP6iWX4ponIw=="); + +//replacement key E.B. NetworX Inc q#9htW#7#2D#5bz#6dAZI#7PH#5tqJjxmzc#6/YQBYVpN#7cN#6GY +sl.AddTail("tsiVwZmJLEzj2rL4qZ8mFHt/89ZgXqMcAb7j/sKtfwUIn929v6t4tNlNVB4CfP2zDpF4ZaOo" +"d/yWhLZbr+8l6w=="); + +//replacement key N.W. Air Solutions, Inc. t#3h#8fGtPaKmEKrAd/IK#6Sm#8#9F#4ej#6#0Z/bgBqaRhMsWc +sl.AddTail("7pdebGAK9bfrnnZ0/lYGNefMyiCKk86vh8liwFwzEgjFKxs8A7l2OlWVVOwPb8qPLI0pjSDA" +"QLaSGgNmel7LHg=="); + +//replacement key Ansutek Commercial Ltd sD#7QssY#1h#5bMJFl#0cBYp#8uMP#7RPf#6#0I#2cZf#7#2tT#2#7SY +sl.AddTail("7efizFXjDsciJB0aq9xSZgLh5rxDSMs/34lU4L+TBC9RWm9G27PBS6C6XZ3aCSvpYAY0TP+/" +"1u/etzfiKeJIQQ=="); + +//replacement key Ohmart/VEGA Corp. #4UfNLljOvBrp#7BzrPiH#1vGWKfdEFIOFhR#9eQNznQOZU +sl.AddTail("qqZwReBFv5pSHbZTp3Wile+SygaAwAbXmzDgSt1FURVMrCuptz+Ma81uVNz0hvYb"); + +//transfer of ownership Kubota Manufacturing of America VK#1P#3usuOjgPlfZKzTBR#6OeTdwwMAIXClYktRoEjW#7Y +sl.AddTail("qNxIK1pR7yYK95MXn5pU4QET3cpwt1UDcp915AxcYuDRf5AafTBuTYrLqcsQZQUo"); + +//replacement key (add kubota's keys to) Halski Systems, Inc. A#1aR#1yFZhMu#3pfeJMr#9DKJ#3s+rYRAP#5ezjw#1D#3VVV#1w +sl.AddTail("KzKbOTDDzyPnHysccUJ+X1Ol2MkambX5M9+5QL4OmPSmUBRAC7IGc7Pj1wuFDZWlBdCGzqef" +"j7CHMthuVwULWg=="); + +//replacement key Braintek, LLC lKuu#7h//qSHEHi#6h#6ULddYokvgHt#2#0LwblQOtOaZp#0g +sl.AddTail("5w8eRzbpx0Sl3VaZy3xelXxjGX70lxdM2d0OZLtz+cxkZ0LoCIdW0irv04DiAqAkmAJ4QMPE" +"XxHPvmk1PyMGQg=="); + +//replacement key US Biometrics xGKLp#3X#2JWdHsh#3DCEHpwrcoEjMlHq/chn#9YvVlWTy#4 +sl.AddTail("Sy0GNltCT9YMLFV0fK+X7RGHH+9b1353EqbwUQhwrxLGNMFfwp8q0s80HShWiP8JIwb7Itkq" +"WU/rt9dE1BdQXw=="); + +//replacement key Visy Technology Systems gbEUjIJ#3JX#3YKRF#2#6w#9#3BMYBvaIDv#5yrT#8cKf#2cLSMY +sl.AddTail("pny9XeRJoSlNknyetGrPCRajiW7GhjHH35ILX6Yn1YdLZZJszo2OfCRou1sqfQWcqIVQEAHF" +"VNgN5wLPWoijOw=="); + +//replacement key Odyssey Networking, Inc. d#9dQX#8lSFsW#0#9gch+bC#0lyl#5wU#3+Ad#1nHn#7wH#5wXsfU +sl.AddTail("Oth5Y30AFzbwdqVHCaj1O8o7ejtlclqXxVGVIljQy+lr9LayLK9C87MNGExVlnFPHcAPT/50" +"NRjirLGB3oytVw=="); + +//replacement key ESM, Inc. aMC#0wfTIVuVam#7nKHyZgEAv#9Dxg#2FWwtLLCrmIx#5t#5s +sl.AddTail("DK/7NCnLg5uTmnTEyHNLLwTkpXMc6rWs7X7VriMVqHhwATdHoR7i7IU/8+GMvSl5UYAeT3DG" +"CgFm18TZ2KzQHQ=="); + +//replacement key C S Tech xhWBBSOGtOpsi#1OY/JJCLe#0rcJ#4jaJ/ghsBzA#6Mg#4#0w +sl.AddTail("cqj9pBh4o/pTXBgbZDdaUm+nlOe1FAskZ5mYibf/re3aDEPedwwikWtWuFg8eDAyo7UjZPRN" +"hwzjRxoIG02Ihw=="); + +//Joyce entered above Dec 16 2004 + +//keycode being used by non-licensed users info@securitygate.com - Universal Heat and Air TkWQWgYLyWsnMaJgJXnivCW#3Go#6LmXb/#4oqASBw#9iRg +sl.AddTail("lPLdPBzwLjjLrUlghfpYa4MCxq9+cY/NHOMyH1fuBnEsEzf95EPd4Xg9OvdlKJlU"); + + +//replacement key C S Tech QQ+Y#2#3E#3f/BhFxYtR#6aNmQ+#0n#8xW+Qr#8PWzhUMVO#3Hw +sl.AddTail("IlPbYKaGMSdnYeOP2V7KM7KvxeSbP94YPfivbqdpXUGdJAITMyJa+vPjYJqR0oMRzQzvqcUL" +"BvBU4tQTIbvjGQ=="); + + +//replacement key Combined Communications Inc. RIsn#2oDr#5z#4XPr#6ulBVh#3d#7WpGWJtT#7#7mMUZiAyRCAQ +sl.AddTail("bzey5Zyv1c7/YIuEFd6F7e6goZvW716Ky9JWlLA5D04M/BSDtKGGUablcQ4o/AJ0yDatsOWy" +"cRZhKO93fsinZg=="); + + +//replacement key Chiron American Inc ZlCnTuf+axnJCItrC#8sUmGrpHo#8dZzDD#3NUZh#1Erk#0g +sl.AddTail("+dcat9R4A7ziUPvi05QEzjKTlZbtr/RLaWPNttBfcNKeWoG+Y70ejgANG33PXGUxbmFXvMV3" +"b2rQRjeqpyP2JQ=="); + + +//replacement key AGJ Systems & Networks Inc. bHlYgQxhyUWGVJUTXx/#9iQptGEzvhRBXxUjvGw#6v#7#1M +sl.AddTail("wPSVLzf1X2Idove64i9dVY5ifWN8G5mgHbWDacqib1FSk1a2RO9Z97y+aCAybwMg"); + + +//replacement key Cirritech Corporation gDdNvpydeqdvk#8SvIQmYf+#8#8kCsfvKHHUogJLoP#2#1#3o +sl.AddTail("h3+aeDETfStioiWHAXjBqaJrsW0boFBoCZEfgWRc/yrCFV9JzeFmWFqeh+KMF+2hPnu6lT8X" +"6IZybtftlDqkOQ=="); + + +//replacememnt key Laser Systems iKfp#1/#0qpjh#5ToLXUSnmvsSqUkiOt#6#3CyFRBsMkw#8mk +sl.AddTail("Bqs+m9XhRf47OXrfP03BBWy7qroP+R05ptICn6Hg8FTVdjIoyqOkCAwLFPIEi7+qojOx3sIS" +"i1HFlHoVWQWjyA=="); + + +//replacement key Nordson Canada WPicleEd#0Yh#1CTW#4VwNatnoJyzsH#7JTOCqosoc#0/HIw +sl.AddTail("on7oDh8kAgo2mq7Dl8NnBbSjL9JUykhMTUHxX0NDmBF0rhWfhg0g78YTffhNTNGEnu120Plp" +"plOUhCq0TDMWjw=="); + + +//illegal use of refunded ARAS - Sheridan Property Management #1e+QAOEiH#8s#1JHJieox#3rWEgdrNonzddx#8EIHy#6#0PDo +sl.AddTail("QJj7wyjIbOrOXZJ3t3U0c6TLu+yVE23MAFApyF+A1RN/d+lGw+f2YFbnY9bP9/DPbCItD7h/" +"vLeegB3QGkThCg=="); + + +//replacement key [Golden State Networks, LLC] Activation key: yIsfkBm#9cfYY+IVYhKe#8R/#9lr#7izfjz+jecDm#7CPFiU +sl.AddTail("/lPZ6GnQFn57ehUpwj+/IeMNTYLvtqr304C0LFGebPftQF1n5U07OHVd9ZCU3vy74HY1NfKW" +"VdypH5zQyV4G9Q=="); + + +//replacement key [Southern Tier Graphics] Activation key: x+ybolDWEylIvVxp/wFRulHy#7EkWIfdbCOJ#6agNTiyw +sl.AddTail("a1Rtwy7P/LZrTABpVWj9KqQFRY1HsuWu91f9dgMJJwMoYizqe89CZNzIk3zzpJFU"); + + +//replacement key Diversified Communications Inc., DBA DI-COMM] Activation key: #1#1H#6jIzn#8#3mQ#5W#2HYlQ+NDB#9#3mPyXfyv#4YwfPgo#2zMg +sl.AddTail("sCM5hltcH8WRiBI6XfZTZSa3GLUMGGiZP/yGJrR/LpKrj98raAyMkReTSjNXBMvb9ObNGwa3" +"+Jdl//4VC4fM+Q=="); + + +//replacement key State of Nevada Legislative Counsel Bureau Activation key: #9k#5b#0xD#3Rn#1#2xd#0JMO#0#3x#8wRkGXRxt#6#2#4#5RcwLjp#7#9A +sl.AddTail("hSw7wHj0lZrunEbhQplIMwrkR7oVLEAv6X+8hr+znM6wSWx2gz8zgcbd4ssrpXpWH8Y+MhCZ" +"nL3w7zmf/m/luA=="); + + +//replacement key [AGJ Systems & Networks Inc.] Activation key: idvHalhbmqDI#2jYHq#6woW#8OLvnwAws#5wLvEyMaZdtt#4 +sl.AddTail("vRW9EQz3jyTaCvQx0kSzTGtzldlmwmXmc6PHzglTmH5WIK67nMfGdjtOAVjbVbZvx3DkZYfJ" +"mW6xrLIygfP+6g=="); + + +//replacement key Crossland Equipment of Houston EXpNDUf/tX+Rbi#2ga#3ENO#5NyALcx#6S+EWGaxAB#7#4#7IY +sl.AddTail("24IiBgY9EhyGa7XPB0Eux9EQyehrrMa7ResQgato+6+cnrAc2WWFttgBukhV7LvlaN8l+Kt3" +"eQlkC/fLGb5Qgw=="); + + +//replacement key Access Washington HoFSdHJOgYrh#0v#4w#9P#5XQKGT#6uOcPzcBr#5#1RWxHfRTY +sl.AddTail("zAFG5ItzGyO5nTNqzoChlAeC6+7NZnYzd07b7JDWQbOqUI+mpmw84lDzF8v6PpM3llHQPFbR" +"nPCfRVKxChN46Q=="); + + +//replacement key [Pace Technical Services] /zD#8#3L/v#5b#0pQIzdp#4WAKxcaT#5AhrrBuM#8cjPj#5y#9AQ +sl.AddTail("9mJg+uK+ZXCoF/IPkg0DpGo0fe0QTsIfcEzfNcfTTwJ/t+f3Twebg6TOVYLxr0WccRrtN4ke" +"vge1N9s0Z9ws6A=="); + + +//replacement key [Sage Technical Services] mcvr#0+YFr#1#3ALX#2afnRu#8XTacB#8Rxkh#2LtsqdKd#5Apk +sl.AddTail("SzY7fzixJVx4JuA5zc7uBYuuD/AhfLzGhhyCz4lb7D8503ggeJXFgWG+Rx8k88Qi+Lr/x2Dm" +"GYveaqKR2ESk6g=="); + + +//replacement key ITnorth.ca Network & Consulting Service LTD. os#9a#4okZQJRWLMzOus#3#1kKFCE/K#2BVm#3VZfLIbjvRmU +sl.AddTail("pC1c1dZM6tTpY3DDMmw5D0nJYxGXBXhWm8ha8phfkfXwrLVeFGWyt+FtXfZCaNkrnEG+5ffc" +"iQ2VGz27JL2liA=="); + + +//replacement key Alphacomm Sales & Service lnjYUlN#6kiDZ+NMOFw#8zS#7#0LZ#8#3U#0McLssDwK#4p#8hZw +sl.AddTail("kqXmGflNXajH6bP3FsFSW0+b24Agog0J8pQh1F71REFkq+kBMK2WkA2CqBVp6aqQtlyDBmnG" +"jiFo5mNONJDkVg=="); + + +//replacement key [TS TECH Enterprises, Inc] /nrHSsGyZkjdgijnFtPKzPbMasmuYls#5CFZ#1d#7Ir#1#7M +sl.AddTail("RlZ9Z70PL1c9C2ctd+PfeFhYhJqWjowg8Wtwnv4odUnaV/IeQUoNJjJXVGQ2HZEoLGS7b3tE" +"sEMacQYYabIiaw=="); + + +//replacement key [Sage Technical Services] hCMW#4HHeeD#7gKRraIfjGm#8BbmXJT#2GMXwoSj+vPNmGw +sl.AddTail("9/DfikoAyvZuCYvtzTnpeGCI8f/454fafdCDkr+N5C67uXFx3tv/XYHaqlvkWNAh"); + +//Joyce entered the above March 18 2005 + +/* +// +sl.AddTail(); + +*/ +/* +// +sl.AddTail(); + + +*/ + for(int x=0;xEx(k.InLineDecrypt("gR3jWcuUWuSOJYVmhT88M/7v+kys87i4FDB/fSlJv1DMuiccVg6QQPOPbIxgWVpqIU2e1eUD" +"4DS2HUVF+xOC/w==")); + //display warning + AfxMessageBox(k.InLineDecrypt( + "nQtTQpiy/QvLCShodMi0c75R6oUJQyOQPRuoWekODUK9mEw/MI9qTGQQ1FZMSJERkhSAewtN" +"kpusV75GCY8epEhqw00WHE6BS4Vt5SWNvvEf0fND7s15BwS3kiuNe4o3VYmwvyGiQyUd2agE" +"WNOJrY8k1iU1l847vlK7lsUHm0P/3KuLmAWoEe5ET1QLWFyOF/S/AxaV9tfon019/TCvJIcr" +"5eAwXrZNQminwG23bLJJZri9F0LoTRbly7HRHX6F4OOP0kiC3n2/D9REoFGFCG835x2A9O0k" +"JKe5aiJWiPEUch9JTyZ+EXAsfzOAGT4Evxw+HOpGob4bMTxGuO0sA8q14nao+Uz4rZ3Fv05p" +"m/zjNREEyV89xdo3xv26OrmksZEqxNA7HD09I2I3GKuW4Emette8/H4J7TrhWPpa438T8ski" +"x1VZM8xkFUx3joqdBs04Phhghk+5ciOh0hN90OpzVbx4BCJ32fGJ/X/w++MNx8m59QAh+PVh" +"xpqVyZya7rVmRUsTzWlDX62amQRMj0u5l4/7z2cKvpFqZf4DV/q0qaWh7FnR4kE59wri03J7" +"TvdU0KbO+2kPIKizPFoBcSAEnmVywAaYO5UdT1FxfPhoccpJ2ggIw+dJGSOXjtVNorvLa/VT" +"R2KpocPuhnZrwcJW5TRBo4e4UUDH7tBRElObGuarmaf7S/H3Kn6ICRpf" + )); + //exit program + ::PostQuitMessage(0); + } + + + + } + + + + + + +} + + +//WELCOME TO SC +void CDBUtils::WelcomeToSC() +{ + AfxMessageBox("Welcome to AyaNova!\r\n" + "A complete owners manual is available on our web site\r\n" + "Select the Help -> Manual menu items to get the manual.\r\n" + "Or visit www.ayanova.com\r\n\r\n" + + "You can also access context sensitive help for any screen\r\n" + "by pressing the F1 key from that screen.\r\n\r\n" + + "In addition to the online help and manual, \r\n" + "we provide full no-charge technical \r\n" + "support to trial version users such as yourself.\r\n\r\n" + + "We encourage you to take advantage of this and email us\r\n" + "at any time if you should have any questions at all about this program\r\n" + "Send your questions to support@ayanova.com\r\n" + "Our response will be swift and thorough.\r\n\r\n"); + + EvaluationDatesAdvance(); + + + +} + + +//used to move all dates in evaluation data +//ahead relative to the reference date and current date +void CDBUtils::EvaluationDatesAdvance() +{ + + COleDateTime dtNow,dtRef,dtData,dtDefault; + COleDateTimeSpan dtSpan; + long lDays; + CString q,strDefDate;; + + dtDefault.SetDate(1968,03,12); + strDefDate=dtDefault.Format(_T("%m/%d/%Y")); + + + + rs->QueryReadOnly("SELECT refdate FROM defaults;"); + rs->FetchField("refdate",&dtRef); + + //get the difference + dtNow=COleDateTime::GetCurrentTime(); + dtSpan=dtNow-dtRef; + lDays=dtSpan.GetDays(); + + //buzz through all the tables fixing up the dates + + //PROBLEMS TABLE + q.Format("UPDATE probs SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE probs SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //LABOUR TABLE + q.Format("UPDATE labor SET start = DateAdd(\"d\",%d,[start]) " + "WHERE (((start)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE labor SET stop = DateAdd(\"d\",%d,[stop]) " + "WHERE (((stop)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //MAIL TABLE + q.Format("UPDATE mail SET deliverydate = DateAdd(\"d\",%d,[deliverydate]) " + "WHERE (((deliverydate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE mail SET mail.date = DateAdd(\"d\",%d,[date]) " + "WHERE (((mail.date)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //NONCLIENTS TABLE + q.Format("UPDATE nonclients SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE nonclients SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //PARTS TABLE + q.Format("UPDATE parts SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE parts SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //PMHEAD TABLE + q.Format("UPDATE pmhead SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE pmhead SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE pmhead SET nextsrvdate = DateAdd(\"d\",%d,[nextsrvdate]) " + "WHERE (((nextsrvdate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //PMITEMS TABLE + q.Format("UPDATE pmitems SET schedate = DateAdd(\"d\",%d,[schedate]) " + "WHERE (((schedate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //PROBS TABLE + q.Format("UPDATE probs SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE probs SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //PROJECTS TABLE + q.Format("UPDATE projects SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE projects SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //RATES TABLE + q.Format("UPDATE rates SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE rates SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE rates SET expires = DateAdd(\"d\",%d,[expires]) " + "WHERE (((expires)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //RENTALS TABLE + q.Format("UPDATE rentals SET dateout = DateAdd(\"d\",%d,[dateout]) " + "WHERE (((dateout)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE rentals SET datedue = DateAdd(\"d\",%d,[datedue]) " + "WHERE (((datedue)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE rentals SET datereturn = DateAdd(\"d\",%d,[datereturn]) " + "WHERE (((datereturn)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //SRCHKEY TABLE + q.Format("UPDATE srchkey SET srchkey.date = DateAdd(\"d\",%d,[date]) " + "WHERE (((srchkey.date)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //STATUSVIEWS TABLE + q.Format("UPDATE statusviews SET woentrydate = DateAdd(\"d\",%d,[woentrydate]) " + "WHERE (((woentrydate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //SUBREPAIRS TABLE + q.Format("UPDATE subrepair SET sent = DateAdd(\"d\",%d,[sent]) " + "WHERE (((sent)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE subrepair SET eta = DateAdd(\"d\",%d,[eta]) " + "WHERE (((eta)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE subrepair SET received = DateAdd(\"d\",%d,[received]) " + "WHERE (((received)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE subrepair SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE subrepair SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + + //UNITMODELS TABLE + q.Format("UPDATE unitmodels SET discodate = DateAdd(\"d\",%d,[discodate]) " + "WHERE (((discodate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE unitmodels SET introduced = DateAdd(\"d\",%d,[introduced]) " + "WHERE (((introduced)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE unitmodels SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE unitmodels SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //UNITS TABLE + q.Format("UPDATE units SET purchasedate = DateAdd(\"d\",%d,[purchasedate]) " + "WHERE (((purchasedate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE units SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE units SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //WO TABLE + q.Format("UPDATE wo SET closed = DateAdd(\"d\",%d,[closed]) " + "WHERE (((closed)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE wo SET starttime = DateAdd(\"d\",%d,[starttime]) " + "WHERE (((starttime)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE wo SET stoptime = DateAdd(\"d\",%d,[stoptime]) " + "WHERE (((stoptime)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE wo SET created = DateAdd(\"d\",%d,[created]) " + "WHERE (((created)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE wo SET modified = DateAdd(\"d\",%d,[modified]) " + "WHERE (((modified)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //SCHEDULE MARKERS - Added 09/18/2001 (last item for 1.7.2.0) + q.Format("UPDATE schedmarkers SET startdate = DateAdd(\"d\",%d,[startdate]) " + "WHERE (((startdate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + q.Format("UPDATE schedmarkers SET enddate = DateAdd(\"d\",%d,[enddate]) " + "WHERE (((enddate)<>#%s#));",lDays,strDefDate); + rs->Ex(q); + + + //TURN OFF FIRSTBOOT FLAG + rs->Ex("UPDATE defaults SET firstboot = False;"); + + //cleanup + rs->Close(); + +} + + + + + + +void CDBUtils::OnBtntest() +{ + CString q; + int x; + for(x=1;x<12001;x++) + { + //insert 12000 clients + q.Format("INSERT INTO clients ( company ) SELECT \"%i\";",x); + rs->Ex(q); + + } + AfxMessageBox("Done clients"); + //insert 1200 parts + for(x=1;x<1201;x++) + { + //insert 12000 clients + q.Format("INSERT INTO parts ( partnumber ) SELECT \"%i\";",x); + rs->Ex(q); + + } + + AfxMessageBox("Done parts"); +} + + + +void CDBUtils::OnBtnexport() +{ + CXferDlg d; + //TO DO: close tables here? + d.m_bExportMode=true; + d.DoModal(); +} + +void CDBUtils::OnBtnimport() +{ + CXferDlg d; + //TO DO: close tables here? + d.m_bExportMode=false; + d.DoModal(); +} + +BOOL CDBUtils::OnHelpInfo(HELPINFO* pHelpInfo) +{ +WinHelp (0x00020000 + IDD_DBUTILS_FORM,HELP_CONTEXT); + return TRUE; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.h new file mode 100644 index 0000000..d4824d3 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DBUtils.h @@ -0,0 +1,143 @@ +#if !defined(AFX_DBUTILS_H__F544FA42_4065_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_DBUTILS_H__F544FA42_4065_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DBUtils.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDBUtils form view + +#ifndef __AFXEXT_H__ +#include +#endif + +#include "spdoc.h" +#include "gzrset.h" +#include "gzk.h" + +class CDBUtils : public CFormView +{ +public: + CDBUtils(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(CDBUtils) + CSpApp* m_pApp; + GZRset* rs2; + GZRset* rs3; + GZRset* rs; + + CProgressCtrl* ppg[11]; + bool Execute(CString strQuery); + +// Form Data +public: + //{{AFX_DATA(CDBUtils) + enum { IDD = IDD_DBUTILS_FORM }; + CStatic m_st11; + CProgressCtrl m_pg11; + CButton m_btnTest; + CStatic m_st9; + CStatic m_st8; + CStatic m_st7; + CStatic m_st6; + CStatic m_st10; + CProgressCtrl m_pg9; + CProgressCtrl m_pg8; + CProgressCtrl m_pg7; + CProgressCtrl m_pg6; + CProgressCtrl m_pg10; + CButton m_btnDelAll; + CButton m_btnQuickIndex; + CButton m_btnIndexAll; + CButton m_btnDefaults; + CButton m_btnCompact; + CButton m_btnCM3; + CStatic m_lblWordCount; + CStatic m_lblPartialInfo; + CStatic m_lblFullInfo; + CStatic m_st5; + CStatic m_st4; + CStatic m_st3; + CStatic m_st2; + CStatic m_st1; + CProgressCtrl m_pg5; + CProgressCtrl m_pg4; + CProgressCtrl m_pg3; + CProgressCtrl m_pg2; + CProgressCtrl m_pg1; + //}}AFX_DATA + +// Attributes +public: + +// Operations +public: + + void EvaluationDatesAdvance(); + void WelcomeToSC(); + bool m_bBootScanDone; + void BootScan(); + void MakeIntoWorkorder(CString strPMItem); + void UpdateDatabaseSchema(); + void EraseAll(); + void SetRights(); + CString m_strErrorLog; + void LogError(CString strError); + void zTrace(CString msg, bool bShow); + void ShowMe(CString txt); + long FindMaxChar(); + void ShowIndexInfo(); + bool SuckWords(int nTable); + + BOOL PeekAndPump(); + void ShowProgressControls(bool bShow); + void Index(bool bFullIndex); + bool ExclusiveAccess(); + void DeActivate(); + void Activate(); +CSpDoc* GetDocument(); +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDBUtils) + public: + virtual void OnInitialUpdate(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~CDBUtils(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(CDBUtils) + afx_msg void OnBtncompact(); + afx_msg void OnBtndefaults(); + afx_msg void OnBtnindexall(); + afx_msg void OnBtnquickindex(); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnBtncm3(); + afx_msg void OnBtndeleteall(); + afx_msg void OnBtntest(); + afx_msg void OnBtnexport(); + afx_msg void OnBtnimport(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: +// _ConnectionPtr pConnection; +public: + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DBUTILS_H__F544FA42_4065_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.cpp new file mode 100644 index 0000000..32ce455 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.cpp @@ -0,0 +1,1666 @@ +// CDIBSectionLite.cpp : implementation file +// +// General purpose DIBsection wrapper class for Win9x, NT 4.0 and WinCE. +// +// Author : Chris Maunder (cmaunder@dundas.com) +// Date : 17 May 1999 +// +// Copyright © Dundas Software Ltd. 1999, All Rights Reserved +// +// This code may be used in compiled form in any way you desire. This +// file may be redistributed unmodified by any means PROVIDING it is +// not sold for profit without the authors written consent, and +// providing that this notice and the authors name is included. If +// the source code in this file is used in any commercial application +// then a simple email would be nice. +// +// This file is provided "as is" with no expressed or implied warranty. +// The author accepts no liability for any damage, in any form, caused +// by this code. Use it at your own risk and as with all code expect bugs! +// It's been tested but I'm not perfect. +// +// Please use and enjoy. Please let me know of any bugs/mods/improvements +// that you have found/implemented and I will fix/incorporate them into this +// file. +// +// History : 25 May 1999 - First release +// 4 Jun 1999 - Fixed SetBitmap bug +// 4 May 2000 - 16 or 32 bit compression bug fix (Jim Miller ) + +#include "stdafx.h" +#include "DIBSectionLite.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Use C++ exception handling instead of structured on non-CE platforms. +#ifndef _WIN32_WCE +#undef TRY +#undef CATCH +#undef END_CATCH +#define TRY try +#define CATCH(ex_class, ex_object) catch(ex_class* ex_object) +#define END_CATCH +#endif // _WIN32_WCE + +// Spit out some messages as a sanity check for programmers +#ifdef DIBSECTION_NO_DITHER +#pragma message(" - CDIBSectionLite: No dithering") +#endif +#ifdef DIBSECTION_NO_MEMDC_REUSE +#pragma message(" - CDIBSectionLite: No memory DC reuse") +#endif +#ifdef DIBSECTION_NO_PALETTE +#pragma message(" - CDIBSectionLite: No palette support") +#endif + +// Standard colors +RGBQUAD CDIBSectionLite::ms_StdColors[] = { + { 0x00, 0x00, 0x00, 0 }, // System palette - first 10 colors + { 0x80, 0x00, 0x00, 0 }, + { 0x00, 0x80, 0x00, 0 }, + { 0x80, 0x80, 0x00, 0 }, + { 0x00, 0x00, 0x80, 0 }, + { 0x80, 0x00, 0x80, 0 }, + { 0x00, 0x80, 0x80, 0 }, + { 0xC0, 0xC0, 0xC0, 0 }, + { 0xC0, 0xDC, 0xC0, 0 }, + { 0xA6, 0xCA, 0xF0, 0 }, + + { 0x2C, 0x00, 0x00, 0 }, + { 0x56, 0x00, 0x00, 0 }, + { 0x87, 0x00, 0x00, 0 }, + { 0xC0, 0x00, 0x00, 0 }, + { 0xFF, 0x00, 0x00, 0 }, + { 0x00, 0x2C, 0x00, 0 }, + { 0x2C, 0x2C, 0x00, 0 }, + { 0x56, 0x2C, 0x00, 0 }, + { 0x87, 0x2C, 0x00, 0 }, + { 0xC0, 0x2C, 0x00, 0 }, + { 0xFF, 0x2C, 0x00, 0 }, + { 0x00, 0x56, 0x00, 0 }, + { 0x2C, 0x56, 0x00, 0 }, + { 0x56, 0x56, 0x00, 0 }, + { 0x87, 0x56, 0x00, 0 }, + { 0xC0, 0x56, 0x00, 0 }, + { 0xFF, 0x56, 0x00, 0 }, + { 0x00, 0x87, 0x00, 0 }, + { 0x2C, 0x87, 0x00, 0 }, + { 0x56, 0x87, 0x00, 0 }, + { 0x87, 0x87, 0x00, 0 }, + { 0xC0, 0x87, 0x00, 0 }, + { 0xFF, 0x87, 0x00, 0 }, + { 0x00, 0xC0, 0x00, 0 }, + { 0x2C, 0xC0, 0x00, 0 }, + { 0x56, 0xC0, 0x00, 0 }, + { 0x87, 0xC0, 0x00, 0 }, + { 0xC0, 0xC0, 0x00, 0 }, + { 0xFF, 0xC0, 0x00, 0 }, + { 0x00, 0xFF, 0x00, 0 }, + { 0x2C, 0xFF, 0x00, 0 }, + { 0x56, 0xFF, 0x00, 0 }, + { 0x87, 0xFF, 0x00, 0 }, + { 0xC0, 0xFF, 0x00, 0 }, + { 0xFF, 0xFF, 0x00, 0 }, + { 0x00, 0x00, 0x2C, 0 }, + { 0x2C, 0x00, 0x2C, 0 }, + { 0x56, 0x00, 0x2C, 0 }, + { 0x87, 0x00, 0x2C, 0 }, + { 0xC0, 0x00, 0x2C, 0 }, + { 0xFF, 0x00, 0x2C, 0 }, + { 0x00, 0x2C, 0x2C, 0 }, + { 0x2C, 0x2C, 0x2C, 0 }, + { 0x56, 0x2C, 0x2C, 0 }, + { 0x87, 0x2C, 0x2C, 0 }, + { 0xC0, 0x2C, 0x2C, 0 }, + { 0xFF, 0x2C, 0x2C, 0 }, + { 0x00, 0x56, 0x2C, 0 }, + { 0x2C, 0x56, 0x2C, 0 }, + { 0x56, 0x56, 0x2C, 0 }, + { 0x87, 0x56, 0x2C, 0 }, + { 0xC0, 0x56, 0x2C, 0 }, + { 0xFF, 0x56, 0x2C, 0 }, + { 0x00, 0x87, 0x2C, 0 }, + { 0x2C, 0x87, 0x2C, 0 }, + { 0x56, 0x87, 0x2C, 0 }, + { 0x87, 0x87, 0x2C, 0 }, + { 0xC0, 0x87, 0x2C, 0 }, + { 0xFF, 0x87, 0x2C, 0 }, + { 0x00, 0xC0, 0x2C, 0 }, + { 0x2C, 0xC0, 0x2C, 0 }, + { 0x56, 0xC0, 0x2C, 0 }, + { 0x87, 0xC0, 0x2C, 0 }, + { 0xC0, 0xC0, 0x2C, 0 }, + { 0xFF, 0xC0, 0x2C, 0 }, + { 0x00, 0xFF, 0x2C, 0 }, + { 0x2C, 0xFF, 0x2C, 0 }, + { 0x56, 0xFF, 0x2C, 0 }, + { 0x87, 0xFF, 0x2C, 0 }, + { 0xC0, 0xFF, 0x2C, 0 }, + { 0xFF, 0xFF, 0x2C, 0 }, + { 0x00, 0x00, 0x56, 0 }, + { 0x2C, 0x00, 0x56, 0 }, + { 0x56, 0x00, 0x56, 0 }, + { 0x87, 0x00, 0x56, 0 }, + { 0xC0, 0x00, 0x56, 0 }, + { 0xFF, 0x00, 0x56, 0 }, + { 0x00, 0x2C, 0x56, 0 }, + { 0x2C, 0x2C, 0x56, 0 }, + { 0x56, 0x2C, 0x56, 0 }, + { 0x87, 0x2C, 0x56, 0 }, + { 0xC0, 0x2C, 0x56, 0 }, + { 0xFF, 0x2C, 0x56, 0 }, + { 0x00, 0x56, 0x56, 0 }, + { 0x2C, 0x56, 0x56, 0 }, + { 0x56, 0x56, 0x56, 0 }, + { 0x87, 0x56, 0x56, 0 }, + { 0xC0, 0x56, 0x56, 0 }, + { 0xFF, 0x56, 0x56, 0 }, + { 0x00, 0x87, 0x56, 0 }, + { 0x2C, 0x87, 0x56, 0 }, + { 0x56, 0x87, 0x56, 0 }, + { 0x87, 0x87, 0x56, 0 }, + { 0xC0, 0x87, 0x56, 0 }, + { 0xFF, 0x87, 0x56, 0 }, + { 0x00, 0xC0, 0x56, 0 }, + { 0x2C, 0xC0, 0x56, 0 }, + { 0x56, 0xC0, 0x56, 0 }, + { 0x87, 0xC0, 0x56, 0 }, + { 0xC0, 0xC0, 0x56, 0 }, + { 0xFF, 0xC0, 0x56, 0 }, + { 0x00, 0xFF, 0x56, 0 }, + { 0x2C, 0xFF, 0x56, 0 }, + { 0x56, 0xFF, 0x56, 0 }, + { 0x87, 0xFF, 0x56, 0 }, + { 0xC0, 0xFF, 0x56, 0 }, + { 0xFF, 0xFF, 0x56, 0 }, + { 0x00, 0x00, 0x87, 0 }, + { 0x2C, 0x00, 0x87, 0 }, + { 0x56, 0x00, 0x87, 0 }, + { 0x87, 0x00, 0x87, 0 }, + { 0xC0, 0x00, 0x87, 0 }, + { 0xFF, 0x00, 0x87, 0 }, + { 0x00, 0x2C, 0x87, 0 }, + { 0x2C, 0x2C, 0x87, 0 }, + { 0x56, 0x2C, 0x87, 0 }, + { 0x87, 0x2C, 0x87, 0 }, + { 0xC0, 0x2C, 0x87, 0 }, + { 0xFF, 0x2C, 0x87, 0 }, + { 0x00, 0x56, 0x87, 0 }, + { 0x2C, 0x56, 0x87, 0 }, + { 0x56, 0x56, 0x87, 0 }, + { 0x87, 0x56, 0x87, 0 }, + { 0xC0, 0x56, 0x87, 0 }, + { 0xFF, 0x56, 0x87, 0 }, + { 0x00, 0x87, 0x87, 0 }, + { 0x2C, 0x87, 0x87, 0 }, + { 0x56, 0x87, 0x87, 0 }, + { 0x87, 0x87, 0x87, 0 }, + { 0xC0, 0x87, 0x87, 0 }, + { 0xFF, 0x87, 0x87, 0 }, + { 0x00, 0xC0, 0x87, 0 }, + { 0x2C, 0xC0, 0x87, 0 }, + { 0x56, 0xC0, 0x87, 0 }, + { 0x87, 0xC0, 0x87, 0 }, + { 0xC0, 0xC0, 0x87, 0 }, + { 0xFF, 0xC0, 0x87, 0 }, + { 0x00, 0xFF, 0x87, 0 }, + { 0x2C, 0xFF, 0x87, 0 }, + { 0x56, 0xFF, 0x87, 0 }, + { 0x87, 0xFF, 0x87, 0 }, + { 0xC0, 0xFF, 0x87, 0 }, + { 0xFF, 0xFF, 0x87, 0 }, + { 0x00, 0x00, 0xC0, 0 }, + { 0x2C, 0x00, 0xC0, 0 }, + { 0x56, 0x00, 0xC0, 0 }, + { 0x87, 0x00, 0xC0, 0 }, + { 0xC0, 0x00, 0xC0, 0 }, + { 0xFF, 0x00, 0xC0, 0 }, + { 0x00, 0x2C, 0xC0, 0 }, + { 0x2C, 0x2C, 0xC0, 0 }, + { 0x56, 0x2C, 0xC0, 0 }, + { 0x87, 0x2C, 0xC0, 0 }, + { 0xC0, 0x2C, 0xC0, 0 }, + { 0xFF, 0x2C, 0xC0, 0 }, + { 0x00, 0x56, 0xC0, 0 }, + { 0x2C, 0x56, 0xC0, 0 }, + { 0x56, 0x56, 0xC0, 0 }, + { 0x87, 0x56, 0xC0, 0 }, + { 0xC0, 0x56, 0xC0, 0 }, + { 0xFF, 0x56, 0xC0, 0 }, + { 0x00, 0x87, 0xC0, 0 }, + { 0x2C, 0x87, 0xC0, 0 }, + { 0x56, 0x87, 0xC0, 0 }, + { 0x87, 0x87, 0xC0, 0 }, + { 0xC0, 0x87, 0xC0, 0 }, + { 0xFF, 0x87, 0xC0, 0 }, + { 0x00, 0xC0, 0xC0, 0 }, + { 0x2C, 0xC0, 0xC0, 0 }, + { 0x56, 0xC0, 0xC0, 0 }, + { 0x87, 0xC0, 0xC0, 0 }, + { 0xFF, 0xC0, 0xC0, 0 }, + { 0x00, 0xFF, 0xC0, 0 }, + { 0x2C, 0xFF, 0xC0, 0 }, + { 0x56, 0xFF, 0xC0, 0 }, + { 0x87, 0xFF, 0xC0, 0 }, + { 0xC0, 0xFF, 0xC0, 0 }, + { 0xFF, 0xFF, 0xC0, 0 }, + { 0x00, 0x00, 0xFF, 0 }, + { 0x2C, 0x00, 0xFF, 0 }, + { 0x56, 0x00, 0xFF, 0 }, + { 0x87, 0x00, 0xFF, 0 }, + { 0xC0, 0x00, 0xFF, 0 }, + { 0xFF, 0x00, 0xFF, 0 }, + { 0x00, 0x2C, 0xFF, 0 }, + { 0x2C, 0x2C, 0xFF, 0 }, + { 0x56, 0x2C, 0xFF, 0 }, + { 0x87, 0x2C, 0xFF, 0 }, + { 0xC0, 0x2C, 0xFF, 0 }, + { 0xFF, 0x2C, 0xFF, 0 }, + { 0x00, 0x56, 0xFF, 0 }, + { 0x2C, 0x56, 0xFF, 0 }, + { 0x56, 0x56, 0xFF, 0 }, + { 0x87, 0x56, 0xFF, 0 }, + { 0xC0, 0x56, 0xFF, 0 }, + { 0xFF, 0x56, 0xFF, 0 }, + { 0x00, 0x87, 0xFF, 0 }, + { 0x2C, 0x87, 0xFF, 0 }, + { 0x56, 0x87, 0xFF, 0 }, + { 0x87, 0x87, 0xFF, 0 }, + { 0xC0, 0x87, 0xFF, 0 }, + { 0xFF, 0x87, 0xFF, 0 }, + { 0x00, 0xC0, 0xFF, 0 }, + { 0x2C, 0xC0, 0xFF, 0 }, + { 0x56, 0xC0, 0xFF, 0 }, + { 0x87, 0xC0, 0xFF, 0 }, + { 0xC0, 0xC0, 0xFF, 0 }, + { 0xFF, 0xC0, 0xFF, 0 }, + { 0x2C, 0xFF, 0xFF, 0 }, + { 0x56, 0xFF, 0xFF, 0 }, + { 0x87, 0xFF, 0xFF, 0 }, + { 0xC0, 0xFF, 0xFF, 0 }, + { 0xFF, 0xFF, 0xFF, 0 }, + { 0x11, 0x11, 0x11, 0 }, + { 0x18, 0x18, 0x18, 0 }, + { 0x1E, 0x1E, 0x1E, 0 }, + { 0x25, 0x25, 0x25, 0 }, + { 0x2C, 0x2C, 0x2C, 0 }, + { 0x34, 0x34, 0x34, 0 }, + { 0x3C, 0x3C, 0x3C, 0 }, + { 0x44, 0x44, 0x44, 0 }, + { 0x4D, 0x4D, 0x4D, 0 }, + { 0x56, 0x56, 0x56, 0 }, + { 0x5F, 0x5F, 0x5F, 0 }, + { 0x69, 0x69, 0x69, 0 }, + { 0x72, 0x72, 0x72, 0 }, + { 0x7D, 0x7D, 0x7D, 0 }, + { 0x92, 0x92, 0x92, 0 }, + { 0x9D, 0x9D, 0x9D, 0 }, + { 0xA8, 0xA8, 0xA8, 0 }, + { 0xB4, 0xB4, 0xB4, 0 }, + { 0xCC, 0xCC, 0xCC, 0 }, + { 0xD8, 0xD8, 0xD8, 0 }, + { 0xE5, 0xE5, 0xE5, 0 }, + { 0xF2, 0xF2, 0xF2, 0 }, + { 0xFF, 0xFF, 0xFF, 0 }, + + { 0xFF, 0xFB, 0xF0, 0 }, // System palette - last 10 colors + { 0xA0, 0xA0, 0xA4, 0 }, + { 0x80, 0x80, 0x80, 0 }, + { 0xFF, 0x00, 0x00, 0 }, + { 0x00, 0xFF, 0x00, 0 }, + { 0xFF, 0xFF, 0x00, 0 }, + { 0x00, 0x00, 0xFF, 0 }, + { 0xFF, 0x00, 0xFF, 0 }, + { 0x00, 0xFF, 0xFF, 0 }, + { 0xFF, 0xFF, 0xFF, 0 }, +}; +///////////////////////////////////////////////////////////////////////////// +// CE DIBSection global functions + +#ifdef _WIN32_WCE +UINT CEGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, RGBQUAD *pColors); +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDIBSectionLite static functions + +// +// --- In  : nBitsPerPixel - bits per pixel +// nCompression - type of compression +// --- Out : +// --- Returns :The number of colors for this color depth +// --- Effect : Returns the number of color table entries given the number +// of bits per pixel of a bitmap +/*static*/ int CDIBSectionLite::NumColorEntries(int nBitsPerPixel, int nCompression) +{ + int nColors = 0; + + switch (nBitsPerPixel) + { + case 1: + nColors = 2; + break; +#ifdef _WIN32_WCE + case 2: + nColors = 4; + break; // winCE only +#endif + case 4: + nColors = 16; + break; + case 8: + nColors = 256; + break; + case 24: + nColors = 0; + case 16: + case 32: + if (nCompression == BI_BITFIELDS) + nColors = 3; // 16 or 32 bpp have 3 colors(masks) in the color table if bitfield compression + else + nColors = 0; // 16 or 32 bpp have no color table if no bitfield compression + break; + + default: + ASSERT(FALSE); + } + + return nColors; +} + +// +// --- In  : nWidth - image width in pixels +// nBitsPerPixel - bits per pixel +// --- Out : +// --- Returns : Returns the number of storage bytes needed for each scanline +// in the bitmap +// --- Effect : +/*static*/ int CDIBSectionLite::BytesPerLine(int nWidth, int nBitsPerPixel) +{ + return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8; +} + +#ifndef DIBSECTION_NO_PALETTE + +// --- In  : palette - reference to a palette object which will be filled +// nNumColors - number of color entries to fill +// --- Out : +// --- Returns : TRUE on success, false otherwise +// --- Effect : Creates a halftone color palette independant of screen color depth. +// palette will be filled with the colors, and nNumColors is the No. +// of colors to file. If nNumColorsis 0 or > 256, then 256 colors are used. +/*static*/ BOOL CDIBSectionLite::CreateHalftonePalette(CPalette& palette, int nNumColors) +{ + palette.DeleteObject(); + + // Sanity check on requested number of colours. + if (nNumColors <= 0 || nNumColors > 256) + nNumColors = 256; + else if (nNumColors <= 2) + nNumColors = 2; + else if (nNumColors <= 16) + nNumColors = 16; + else if (nNumColors <= 256) + nNumColors = 256; + + PALETTEINFO pi; + pi.palNumEntries = (WORD) nNumColors; + + if (nNumColors == 2) + { + // According to the MS article "The Palette Manager: How and Why" + // monochrome palettes not really needed (will use B&W) + pi.palPalEntry[0].peRed = ms_StdColors[0].rgbRed; + pi.palPalEntry[0].peGreen = ms_StdColors[0].rgbGreen; + pi.palPalEntry[0].peBlue = ms_StdColors[0].rgbBlue; + pi.palPalEntry[0].peFlags = 0; + pi.palPalEntry[1].peRed = ms_StdColors[255].rgbRed; + pi.palPalEntry[1].peGreen = ms_StdColors[255].rgbGreen; + pi.palPalEntry[1].peBlue = ms_StdColors[255].rgbBlue; + pi.palPalEntry[1].peFlags = 0; + } + else if (nNumColors == 16) + { + // According to the MS article "The Palette Manager: How and Why" + // 4-bit palettes not really needed (will use VGA palette) + for (int i = 0; i < 8; i++) + { + pi.palPalEntry[i].peRed = ms_StdColors[i].rgbRed; + pi.palPalEntry[i].peGreen = ms_StdColors[i].rgbGreen; + pi.palPalEntry[i].peBlue = ms_StdColors[i].rgbBlue; + pi.palPalEntry[i].peFlags = 0; + } + for (i = 8; i < 16; i++) + { + pi.palPalEntry[i].peRed = ms_StdColors[248+i].rgbRed; + pi.palPalEntry[i].peGreen = ms_StdColors[248+i].rgbGreen; + pi.palPalEntry[i].peBlue = ms_StdColors[248+i].rgbBlue; + pi.palPalEntry[i].peFlags = 0; + } + } + else // if (nNumColors == 256) + { + // Fill palette with full halftone palette + for (int i = 0; i < 256; i++) + { + pi.palPalEntry[i].peRed = ms_StdColors[i].rgbRed; + pi.palPalEntry[i].peGreen = ms_StdColors[i].rgbGreen; + pi.palPalEntry[i].peBlue = ms_StdColors[i].rgbBlue; + pi.palPalEntry[i].peFlags = 0; + } + } + + return palette.CreatePalette((LPLOGPALETTE) pi); +} +#endif // DIBSECTION_NO_PALETTE + + +///////////////////////////////////////////////////////////////////////////// +// CDIBSectionLite + +CDIBSectionLite::CDIBSectionLite() +{ + // Just in case... + ASSERT(sizeof(ms_StdColors) / sizeof(ms_StdColors[0]) == 256); + + m_hBitmap = NULL; + m_hOldBitmap = NULL; + +#ifndef DIBSECTION_NO_MEMDC_REUSE + m_bReuseMemDC = FALSE; +#endif + +#ifndef DIBSECTION_NO_PALETTE + m_pOldPalette = NULL; +#endif + +#ifndef DIBSECTION_NO_DITHER + m_bDither = FALSE; + m_hDrawDib = NULL; +#endif + + DeleteObject(); // This will initialise to a known state - ie. empty +} + +CDIBSectionLite::~CDIBSectionLite() +{ + DeleteObject(); +} + +// --- In  : +// --- Out : +// --- Returns : +// --- Effect : Resets the object to an empty state, and frees all memory used. +void CDIBSectionLite::DeleteObject() +{ + // Unselect the bitmap out of the memory DC before deleting bitmap + ReleaseMemoryDC(TRUE); + + if (m_hBitmap) + ::DeleteObject(m_hBitmap); + m_hBitmap = NULL; + m_ppvBits = NULL; + +#ifndef DIBSECTION_NO_PALETTE + m_Palette.DeleteObject(); +#endif + + memset(&m_DIBinfo, 0, sizeof(m_DIBinfo)); + +#ifndef DIBSECTION_NO_DITHER + if (m_hDrawDib) + DrawDibClose(m_hDrawDib); + m_hDrawDib = NULL; +#endif + + m_iColorDataType = DIB_RGB_COLORS; + m_iColorTableSize = 0; +} + +///////////////////////////////////////////////////////////////////////////// +// CDIBSectionLite diagnostics + +#ifdef _DEBUG +void CDIBSectionLite::AssertValid() const +{ + ASSERT(m_hBitmap); + + DIBSECTION ds; + DWORD dwSize = GetObject( m_hBitmap, sizeof(DIBSECTION), &ds ); + ASSERT(dwSize == sizeof(DIBSECTION)); + + ASSERT(0 <= m_iColorTableSize && m_iColorTableSize <= 256); + + CObject::AssertValid(); +} + +void CDIBSectionLite::Dump(CDumpContext& dc) const +{ + CObject::Dump(dc); +} + +#endif //_DEBUG + + +///////////////////////////////////////////////////////////////////////////// +// CDIBSectionLite operations + +#ifndef DIBSECTION_NO_DITHER +// --- In  : bDither - whether or not dithering should be enabled +// --- Out : +// --- Returns : TRUE on success +// --- Effect : Turns dithering on by using the DrawDib functions instead of +// the GDI functions +BOOL CDIBSectionLite::SetDither(BOOL bDither) +{ + if ( (m_bDither == bDither) && + ((m_hDrawDib && m_bDither) || (!m_hDrawDib && !m_bDither)) ) + return TRUE; + + if (!bDither && m_hDrawDib != NULL) + { + DrawDibClose(m_hDrawDib); + m_hDrawDib = NULL; + } + + m_bDither = bDither; + + return TRUE; +} + +// --- In  : +// --- Out : +// --- Returns : TRUE if dithering is used +// --- Effect : Returns whether or not the DrawDib functions (and hence dithering) +// is being used. +BOOL CDIBSectionLite::GetDither() +{ + return (m_bDither && GetBitCount() > 8); +} + +// --- In  : +// --- Out : +// --- Returns : A DrawDib context if dithering is supported, else NULL +// --- Effect : Returns a drawdib context for use with DrawDib routines +HDRAWDIB CDIBSectionLite::GetDrawDibContext() +{ + if (!GetDither()) + return NULL; + + if (m_hDrawDib) + return m_hDrawDib; + + m_hDrawDib = DrawDibOpen(); + + return m_hDrawDib; +} + + +#endif + +// --- In  : pDC - Pointer to a device context +// ptDest - point at which the topleft corner of the image is drawn +// --- Out : +// --- Returns : TRUE on success +// --- Effect : Draws the image 1:1 on the device context +BOOL CDIBSectionLite::Draw(CDC* pDC, CPoint ptDest, BOOL bForceBackground /*=FALSE*/) +{ + if (!m_hBitmap) + return FALSE; + + CSize size = GetSize(); + CPoint ptOrigin = CPoint(0,0); + + BOOL bResult = FALSE; + +#ifndef DIBSECTION_NO_DITHER + // We will only be able to get a HDRAWDIB if dithering is enabled + HDRAWDIB hDrawDib = GetDrawDibContext(); + if (hDrawDib) + { +#ifndef DIBSECTION_NO_PALETTE + DrawDibSetPalette( hDrawDib, (HPALETTE)m_Palette); + DrawDibRealize( hDrawDib, pDC->GetSafeHdc(), FALSE); +#endif // DIBSECTION_NO_PALETTE + bResult = DrawDibDraw(hDrawDib, pDC->GetSafeHdc(), + ptDest.x, ptDest.y, size.cx, size.cy, + GetBitmapInfoHeader(), GetDIBits(), + ptOrigin.x, ptOrigin.y, size.cx, size.cy, + 0/*DDF_HALFTONE*/); + } + else + { +#endif + // Create a memory DC compatible with the destination DC + CDC* pMemDC = GetMemoryDC(pDC, FALSE); + if (!pMemDC) + return FALSE; + +#ifndef DIBSECTION_NO_PALETTE + // Select and realize the palette + CPalette* pOldPalette = NULL; + if (m_Palette.m_hObject && UsesPalette(pDC)) + { + pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground); + pDC->RealizePalette(); + } +#endif // DIBSECTION_NO_PALETTE + + bResult = pDC->BitBlt(ptDest.x, ptDest.y, size.cx, size.cy, pMemDC, + ptOrigin.x, ptOrigin.y, SRCCOPY); + +#ifndef DIBSECTION_NO_PALETTE + if (pOldPalette) + pDC->SelectPalette(pOldPalette, FALSE); +#endif // DIBSECTION_NO_PALETTE + + ReleaseMemoryDC(); +#ifndef DIBSECTION_NO_DITHER + } +#endif // DIBSECTION_NO_DITHER + + return bResult; +} + +// --- In  : pDC - Pointer to a device context +// ptDest - point at which the topleft corner of the image is drawn +// size - size to stretch the image +// --- Out : +// --- Returns : TRUE on success +// --- Effect : Stretch draws the image to the desired size on the device context +BOOL CDIBSectionLite::Stretch(CDC* pDC, CPoint ptDest, CSize size, + BOOL bForceBackground /*=FALSE*/) +{ + if (!m_hBitmap) + return FALSE; + + CPoint ptOrigin = CPoint(0,0); + CSize imagesize = GetSize(); + + BOOL bResult = FALSE; + +#ifndef _WIN32_WCE + pDC->SetStretchBltMode(COLORONCOLOR); +#endif + +#ifndef DIBSECTION_NO_DITHER + // We will only be able to get a HDRAWDIB if dithering is enabled + HDRAWDIB hDrawDib = GetDrawDibContext(); + if (hDrawDib) + { +#ifndef DIBSECTION_NO_PALETTE + DrawDibSetPalette( hDrawDib, (HPALETTE)m_Palette); + DrawDibRealize( hDrawDib, pDC->GetSafeHdc(), FALSE); +#endif // DIBSECTION_NO_PALETTE + + bResult = DrawDibDraw(hDrawDib, pDC->GetSafeHdc(), + ptDest.x, ptDest.y, size.cx, size.cy, + GetBitmapInfoHeader(), GetDIBits(), + 0,0, GetWidth(), GetHeight(), + 0/*DDF_HALFTONE*/); + } + else + { +#endif // DIBSECTION_NO_DITHER + // Create a memory DC compatible with the destination DC + CDC* pMemDC = GetMemoryDC(pDC, FALSE); + if (!pMemDC) + return FALSE; + +#ifndef DIBSECTION_NO_PALETTE + // Select and realize the palette + CPalette* pOldPalette = NULL; + if (m_Palette.m_hObject && UsesPalette(pDC)) + { + pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground); + pDC->RealizePalette(); + } +#endif // DIBSECTION_NO_PALETTE + +#ifndef _WIN32_WCE + pDC->SetStretchBltMode(COLORONCOLOR); +#endif // _WIN32_WCE + + bResult = pDC->StretchBlt(ptDest.x, ptDest.y, size.cx, size.cy, + pMemDC, + ptOrigin.x, ptOrigin.y, imagesize.cx, imagesize.cy, + SRCCOPY); + +#ifndef DIBSECTION_NO_PALETTE + if (pOldPalette) + pDC->SelectPalette(pOldPalette, FALSE); +#endif // DIBSECTION_NO_PALETTE + + ReleaseMemoryDC(); +#ifndef DIBSECTION_NO_DITHER + } +#endif // DIBSECTION_NO_DITHER + + return bResult; +} + +////////////////////////////////////////////////////////////////////////////// +// Setting the bitmap... + +// --- In  : nIDResource - resource ID +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Initialises the bitmap from a resource. If failure, then object is +// initialised back to an empty bitmap. +BOOL CDIBSectionLite::SetBitmap(UINT nIDResource) +{ + return SetBitmap(MAKEINTRESOURCE(nIDResource)); +} + +// --- In  : lpszResourceName - resource name +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Initialises the bitmap from a resource. If failure, then object is +// initialised back to an empty bitmap. +BOOL CDIBSectionLite::SetBitmap(LPCTSTR lpszResourceName) +{ + HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetResourceHandle(), + lpszResourceName, + IMAGE_BITMAP, + 0,0, +#ifdef _WIN32_WCE + 0 +#else + LR_CREATEDIBSECTION +#endif + ); + + if (!hBmp) + { + TRACE0("Unable to LoadImage"); + return FALSE; + } + + BOOL bResult = SetBitmap(hBmp); + ::DeleteObject(hBmp); + return bResult; +} + +// --- In  : lpBitmapInfo - pointer to a BITMAPINFO structure +// lpBits - pointer to image bits +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Initialises the bitmap using the information in lpBitmapInfo to determine +// the dimensions and colors, and the then sets the bits from the bits in +// lpBits. If failure, then object is initialised back to an empty bitmap. +BOOL CDIBSectionLite::SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits) +{ + DeleteObject(); + + if (!lpBitmapInfo || !lpBits) + return FALSE; + + HDC hDC = NULL; + TRY { + BITMAPINFOHEADER& bmih = lpBitmapInfo->bmiHeader; + + // Compute the number of colors in the color table + m_iColorTableSize = NumColorEntries(bmih.biBitCount, bmih.biCompression); + + DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD); + + // Copy over BITMAPINFO contents + memcpy(&m_DIBinfo, lpBitmapInfo, dwBitmapInfoSize); + + // Should now have all the info we need to create the sucker. + //TRACE(_T("Width %d, Height %d, Bits/pixel %d, Image Size %d\n"), + // bmih.biWidth, bmih.biHeight, bmih.biBitCount, bmih.biSizeImage); + + // Create a DC which will be used to get DIB, then create DIBsection + hDC = ::GetDC(NULL); + if (!hDC) + { + TRACE0("Unable to get DC\n"); + AfxThrowResourceException(); + } + + m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo, + m_iColorDataType, &m_ppvBits, NULL, 0); + ::ReleaseDC(NULL, hDC); + if (!m_hBitmap) + { + TRACE0("CreateDIBSection failed\n"); + AfxThrowResourceException(); + } + + if (m_DIBinfo.bmiHeader.biSizeImage == 0) + { + int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth, + lpBitmapInfo->bmiHeader.biBitCount); + m_DIBinfo.bmiHeader.biSizeImage = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight; + } + +#ifndef _WIN32_WCE + // Flush the GDI batch queue + GdiFlush(); +#endif + + memcpy(m_ppvBits, lpBits, m_DIBinfo.bmiHeader.biSizeImage); + +#ifndef DIBSECTION_NO_PALETTE + if (!CreatePalette()) + { + TRACE0("Unable to create palette\n"); + AfxThrowResourceException(); + } +#endif // DIBSECTION_NO_PALETTE + } + CATCH (CException, e) + { + e->Delete(); + _ShowLastError(); + if (hDC) + ::ReleaseDC(NULL, hDC); + DeleteObject(); + return FALSE; + } + END_CATCH + + return TRUE; +} + +// --- In  : hBitmap - handle to image +// pPalette - optional palette to use when setting image +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Initialises the bitmap from the HBITMAP supplied. If failure, then +// object is initialised back to an empty bitmap. +BOOL CDIBSectionLite::SetBitmap(HBITMAP hBitmap +#ifndef DIBSECTION_NO_PALETTE + , CPalette* pPalette /*= NULL*/ +#endif + ) +{ + DeleteObject(); + + if (!hBitmap) + return FALSE; + + // Get dimensions of bitmap + BITMAP bm; + if (!::GetObject(hBitmap, sizeof(bm),(LPVOID)&bm)) + return FALSE; + bm.bmHeight = abs(bm.bmHeight); + + CWindowDC dc(NULL); +#ifndef DIBSECTION_NO_PALETTE + CPalette* pOldPalette = NULL; +#endif // DIBSECTION_NO_PALETTE + + TRY { + m_iColorTableSize = NumColorEntries(bm.bmBitsPixel, BI_RGB); + + // Initialize the BITMAPINFOHEADER in m_DIBinfo + BITMAPINFOHEADER& bih = m_DIBinfo.bmiHeader; + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = bm.bmWidth; + bih.biHeight = bm.bmHeight; + bih.biPlanes = 1; // Must always be 1 according to docs + bih.biBitCount = bm.bmBitsPixel; + bih.biCompression = BI_RGB; + bih.biSizeImage = BytesPerLine(bm.bmWidth, bm.bmBitsPixel) * bm.bmHeight; + bih.biXPelsPerMeter = 0; + bih.biYPelsPerMeter = 0; + bih.biClrUsed = 0; + bih.biClrImportant = 0; + + GetColorTableEntries(dc.GetSafeHdc(), hBitmap); + +#ifndef DIBSECTION_NO_PALETTE + // If we have a palette supplied, then set the palette (and hance DIB color + // table) using this palette + if (pPalette) + SetPalette(pPalette); + + if (m_Palette.GetSafeHandle()) + { + pOldPalette = dc.SelectPalette(&m_Palette, FALSE); + dc.RealizePalette(); + } +#endif // DIBSECTION_NO_PALETTE + + // Create it! + m_hBitmap = CreateDIBSection(dc.m_hDC, + (const BITMAPINFO*) m_DIBinfo, + m_iColorDataType, + &m_ppvBits, + NULL, 0); +#ifndef DIBSECTION_NO_PALETTE + if (pOldPalette) + dc.SelectPalette(pOldPalette, FALSE); + pOldPalette = NULL; +#endif // DIBSECTION_NO_PALETTE + + if (!m_hBitmap) + { + TRACE0("Unable to CreateDIBSection\n"); + AfxThrowResourceException(); + } + +#ifndef DIBSECTION_NO_PALETTE + // If palette was supplied then create a palette using the entries in the DIB + // color table. + if (!pPalette) + CreatePalette(); +#endif // DIBSECTION_NO_PALETTE + + // Need to copy the supplied bitmap onto the newly created DIBsection + CDC memDC, CopyDC; + if (!CopyDC.CreateCompatibleDC(&dc) || !memDC.CreateCompatibleDC(&dc)) + { + TRACE0("Unable to create compatible DC's\n"); + AfxThrowResourceException(); + } + +#ifndef DIBSECTION_NO_PALETTE + if (m_Palette.GetSafeHandle()) + { + memDC.SelectPalette(&m_Palette, FALSE); memDC.RealizePalette(); + CopyDC.SelectPalette(&m_Palette, FALSE); CopyDC.RealizePalette(); + } +#endif // DIBSECTION_NO_PALETTE + +#ifndef _WIN32_WCE + // Flush the GDI batch queue + GdiFlush(); +#endif + + HBITMAP hOldMemBitmap = (HBITMAP) SelectObject(memDC.m_hDC, hBitmap); + HBITMAP hOldCopyBitmap = (HBITMAP) SelectObject(CopyDC.m_hDC, m_hBitmap); + + CopyDC.BitBlt(0,0, bm.bmWidth, bm.bmHeight, &memDC, 0,0, SRCCOPY); + + SelectObject(memDC.m_hDC, hOldMemBitmap); + SelectObject(CopyDC.m_hDC, hOldCopyBitmap); + +#ifndef DIBSECTION_NO_PALETTE + if (m_Palette.GetSafeHandle()) + { + memDC.SelectStockObject(DEFAULT_PALETTE); + CopyDC.SelectStockObject(DEFAULT_PALETTE); + } +#endif // DIBSECTION_NO_PALETTE + } + CATCH (CException, e) + { + e->Delete(); + _ShowLastError(); +#ifndef DIBSECTION_NO_PALETTE + if (pOldPalette) + dc.SelectPalette(pOldPalette, FALSE); + #endif // DIBSECTION_NO_PALETTE + DeleteObject(); + return FALSE; + } + END_CATCH + + return TRUE; +} + + +////////////////////////////////////////////////////////////////////////////// +// Persistance... + +// --- In  : lpszFileName - image filename +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Loads the bitmap from a bitmap file with the name lpszFileName. +// If failure, then object is initialised back to an empty bitmap. +BOOL CDIBSectionLite::Load(LPCTSTR lpszFileName) +{ + CFile file; + if (!file.Open(lpszFileName, CFile::modeRead)) + return FALSE; + + // Get the current file position. + DWORD dwFileStart = file.GetPosition(); + + // The first part of the file contains the file header. + // This will tell us if it is a bitmap, how big the header is, and how big + // the file is. The header size in the file header includes the color table. + BITMAPFILEHEADER BmpFileHdr; + int nBytes; + nBytes = file.Read(&BmpFileHdr, sizeof(BmpFileHdr)); + if (nBytes != sizeof(BmpFileHdr)) + { + TRACE0("Failed to read file header\n"); + return FALSE; + } + + // Check that we have the magic 'BM' at the start. + if (BmpFileHdr.bfType != DS_BITMAP_FILEMARKER) + { + TRACE0("Not a bitmap file\n"); + return FALSE; + } + + // Read the header (assuming it's a DIB). + DIBINFO BmpInfo; + nBytes = file.Read(&BmpInfo, sizeof(BITMAPINFOHEADER)); + if (nBytes != sizeof(BITMAPINFOHEADER)) + { + TRACE0("Failed to read BITMAPINFOHEADER\n"); + return FALSE; + } + + // Check that we have a real Windows DIB file. + if (BmpInfo.bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) + { + TRACE0(" File is not a Windows DIB\n"); + return FALSE; + } + + // See how big the color table is in the file (if there is one). + int nColors = NumColorEntries(BmpInfo.bmiHeader.biBitCount, BmpInfo.bmiHeader.biCompression); + if (nColors > 0) + { + // Read the color table from the file. + int nColorTableSize = nColors * sizeof(RGBQUAD); + nBytes = file.Read(BmpInfo.ColorTable(), nColorTableSize); + if (nBytes != nColorTableSize) + { + TRACE0("Failed to read color table\n"); + return FALSE; + } + } + + // So how big the bitmap surface is. + int nBitsSize = BmpFileHdr.bfSize - BmpFileHdr.bfOffBits; + + // Allocate the memory for the bits and read the bits from the file. + BYTE* pBits = (BYTE*) malloc(nBitsSize); + if (!pBits) + { + TRACE0("Out of memory for DIB bits\n"); + return FALSE; + } + + // Seek to the bits in the file. + file.Seek(dwFileStart + BmpFileHdr.bfOffBits, CFile::begin); + + // read the bits + nBytes = file.Read(pBits, nBitsSize); + if (nBytes != nBitsSize) + { + TRACE0("Failed to read bits\n"); + free(pBits); + return FALSE; + } + + // Everything went OK. + BmpInfo.bmiHeader.biSizeImage = nBitsSize; + + if (!SetBitmap((LPBITMAPINFO) BmpInfo, pBits)) + { + TRACE0("Failed to set bitmap info\n"); + free(pBits); + return FALSE; + } + + free(pBits); + + return TRUE; +} + +// --- In  : lpszFileName - image filename +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Saves the image to file. +BOOL CDIBSectionLite::Save(LPCTSTR lpszFileName) +{ + BITMAPFILEHEADER hdr; + LPBITMAPINFOHEADER lpbi = GetBitmapInfoHeader(); + + if (!lpbi || !lpszFileName) + return FALSE; + + CFile file; + if (!file.Open(lpszFileName, CFile::modeWrite|CFile::modeCreate)) + return FALSE; + + DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD); + DWORD dwFileHeaderSize = dwBitmapInfoSize + sizeof(hdr); + + // Fill in the fields of the file header + hdr.bfType = DS_BITMAP_FILEMARKER; + hdr.bfSize = dwFileHeaderSize + lpbi->biSizeImage; + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + hdr.bfOffBits = dwFileHeaderSize; + + // Write the file header + file.Write(&hdr, sizeof(hdr)); + + // Write the DIB header + file.Write(lpbi, dwBitmapInfoSize); + + // Write DIB bits + file.Write(GetDIBits(), lpbi->biSizeImage); + + return TRUE; +} + +// --- In  : Bitmap - DIBSection object to be copied +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Creates a copy of another CDIBSection object +BOOL CDIBSectionLite::Copy(CDIBSectionLite& Bitmap) +{ + BOOL bResult = SetBitmap(Bitmap.GetBitmapInfo(), Bitmap.GetDIBits()); + + if (bResult) + { + SetColorTable(Bitmap.GetColorTableSize(), Bitmap.GetColorTable()); +#ifndef DIBSECTION_NO_PALETTE + CreatePalette(); +#endif +#ifndef DIBSECTION_NO_DITHER + SetDither(Bitmap.GetDither()); +#endif + } + + return bResult; +} + +///////////////////////////////////////////////////////////////////////////// +// CDIBSectionLite palette stuff + +// --- In  : nNumColors - number of colors to set +// pColors - array of RGBQUAD's containing colors to set +// --- Out : +// --- Returns : Returns TRUE on success, FALSE otherwise +// --- Effect : Sets the colors used by the image. Only works if # colors <= 256 +BOOL CDIBSectionLite::SetColorTable(UINT nNumColors, RGBQUAD *pColors) +{ + if (!m_hBitmap ||!pColors || !nNumColors || m_iColorTableSize == 0 + || nNumColors > 256) + return FALSE; + +#ifdef _WIN32_WCE + LPRGBQUAD pColorTable = GetColorTable(); + ASSERT(pColorTable); + + int nCount = min(m_iColorTableSize, nNumColors); + ::memset(pColorTable, 0, m_iColorTableSize*sizeof(RGBQUAD)); + ::memcpy(pColorTable, pColors, nCount*sizeof(RGBQUAD)); +#else + // Create a memory DC compatible with the screen + CDC MemDC; + if (!MemDC.CreateCompatibleDC(NULL)) + return FALSE; + + HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap); + + ::SetDIBColorTable(MemDC.GetSafeHdc(), 0, nNumColors, pColors); + + // Clean up + if (hOldBitmap) + ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap); +#endif + + return TRUE; +} + +#ifndef DIBSECTION_NO_PALETTE + +// --- In  : +// --- Out : +// --- Returns : TRUE on success +// --- Effect : Creates the palette from the DIBSection's color table. Assumes +// m_iColorTableSize has been set and the DIBsection m_hBitmap created +BOOL CDIBSectionLite::CreatePalette() +{ + m_Palette.DeleteObject(); + + if (!m_hBitmap) + return FALSE; + + // Create a 256 color halftone palette if there is no color table in the DIBSection + if (m_iColorTableSize == 0) + return CreateHalftonePalette(m_Palette, 256); + + // Get space for the color entries + RGBQUAD *pRGB = new RGBQUAD[m_iColorTableSize]; + if (!pRGB) + return CreateHalftonePalette(m_Palette, m_iColorTableSize); + + HDC hDC = ::GetDC(NULL); + if (!hDC) + { + delete [] pRGB; + return FALSE; + } + + // Create a memory DC compatible with the current DC + CDC MemDC; + MemDC.CreateCompatibleDC(CDC::FromHandle(hDC)); + if (!MemDC.GetSafeHdc()) + { + delete [] pRGB; + ::ReleaseDC(NULL, hDC); + return CreateHalftonePalette(m_Palette, m_iColorTableSize); + } + ::ReleaseDC(NULL, hDC); + + HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap); + if (!hOldBitmap) + { + delete [] pRGB; + return CreateHalftonePalette(m_Palette, m_iColorTableSize); + } + + // Get the colors used. WinCE does not support GetDIBColorTable so if you + // are using this on a CE device with palettes, then you need to replace + // the call with code that manually gets the color table from the m_DIBinfo structure. +#ifdef _WIN32_WCE + int nColors = ::CEGetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB); +#else + int nColors = ::GetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB); +#endif + + // Clean up + ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap); + + if (!nColors) // No colors retrieved => the bitmap in the DC is not a DIB section + { + delete [] pRGB; + return CreateHalftonePalette(m_Palette, m_iColorTableSize); + } + + // Create and fill a LOGPALETTE structure with the colors used. + PALETTEINFO PaletteInfo; + PaletteInfo.palNumEntries = m_iColorTableSize; + + for (int i = 0; i < nColors; i++) + { + PaletteInfo.palPalEntry[i].peRed = pRGB[i].rgbRed; + PaletteInfo.palPalEntry[i].peGreen = pRGB[i].rgbGreen; + PaletteInfo.palPalEntry[i].peBlue = pRGB[i].rgbBlue; + PaletteInfo.palPalEntry[i].peFlags = 0; + } + + delete [] pRGB; + + // Create Palette! + return m_Palette.CreatePalette(&PaletteInfo); +} + +// --- In  : pPalette - new palette to use +// --- Out : +// --- Returns : TRUE on success +// --- Effect : Sets the current palette used by the image from the supplied CPalette, +// and sets the color table in the DIBSection +BOOL CDIBSectionLite::SetPalette(CPalette* pPalette) +{ + m_Palette.DeleteObject(); + + if (!pPalette) + return FALSE; + + UINT nColors = pPalette->GetEntryCount(); + if (nColors <= 0 || nColors > 256) + return FALSE; + + // Get palette entries + PALETTEINFO pi; + pi.palNumEntries = (WORD) pPalette->GetPaletteEntries(0, nColors, (LPPALETTEENTRY) pi); + + return SetLogPalette(&pi); +} + +// --- In  : pLogPalette - new palette to use +// --- Out : +// --- Returns : TRUE on success +// --- Effect : Sets the current palette used by the image from the supplied LOGPALETTE +BOOL CDIBSectionLite::SetLogPalette(LOGPALETTE* pLogPalette) +{ + if (!pLogPalette) + { + CreatePalette(); + return FALSE; + } + + ASSERT(pLogPalette->palVersion == (WORD) 0x300); + + UINT nColors = pLogPalette->palNumEntries; + if (nColors <= 0 || nColors > 256) + { + CreatePalette(); + return FALSE; + } + + // Create new palette + m_Palette.DeleteObject(); + if (!m_Palette.CreatePalette(pLogPalette)) + { + CreatePalette(); + return FALSE; + } + + if (m_iColorTableSize == 0) + return TRUE; + + // Set the DIB colors + RGBQUAD RGBquads[256]; + for (UINT i = 0; i < nColors; i++) + { + RGBquads[i].rgbRed = pLogPalette->palPalEntry[i].peRed; + RGBquads[i].rgbGreen = pLogPalette->palPalEntry[i].peGreen; + RGBquads[i].rgbBlue = pLogPalette->palPalEntry[i].peBlue; + RGBquads[i].rgbReserved = 0; + } + + return FillDIBColorTable(nColors, RGBquads); +} + +// --- In  : nNumColors - number of colors to set +// pRGB - colors to fill +// --- Out : +// --- Returns : Returns TRUE on success +// --- Effect : Sets the colors used by the image. Only works if # colors <= 256 +BOOL CDIBSectionLite::FillDIBColorTable(UINT nNumColors, RGBQUAD *pRGB) +{ + if (!pRGB || !nNumColors || !m_iColorTableSize || nNumColors > 256) + return FALSE; + + // get the number of colors to return per BITMAPINFOHEADER docs + UINT nColors; + LPBITMAPINFOHEADER pBmih = GetBitmapInfoHeader(); + if (pBmih->biClrUsed) + nColors = pBmih->biClrUsed; + else + nColors = 1 << (pBmih->biBitCount*pBmih->biPlanes); + + // Initialize the loop variables + nColors = min(nNumColors, nColors); + + LPRGBQUAD pColorTable = GetColorTable(); + for (UINT iColor = 0; iColor < nColors; iColor++) + { + pColorTable[iColor].rgbReserved = 0; + pColorTable[iColor].rgbBlue = pRGB[iColor].rgbBlue; + pColorTable[iColor].rgbRed = pRGB[iColor].rgbRed; + pColorTable[iColor].rgbGreen = pRGB[iColor].rgbGreen; + } + + return TRUE; +} + +#endif // DIBSECTION_NO_PALETTE + + +// --- In  : hdc - the Device Context in which the DIBSection is selected +// hBitmap - the bitmap whose solor entries are to be queried +// lpbi - a pointer to a BITMAPINFO structure that will have it's +// color table filled. +// --- Out : +// --- Returns : the number of colors placed in the color table +// --- Effect : This function is a replacement for GetDIBits, in that it retrieves +// (or synthesizes) the color table from the given bitmap, and stores +// the values in the BITMAPINFO structure supplied. +UINT CDIBSectionLite::GetColorTableEntries(HDC hdc, HBITMAP hBitmap) +{ +#ifndef _WIN32_WCE + + // Call GetDIBits with NULL bits pointer to fill in the BITMAPINFOHEADER data + // Basically we are just getting the color table entries with a minimum of + // effort + if (!::GetDIBits(hdc, hBitmap, 0, GetHeight(), NULL, m_DIBinfo, m_iColorDataType)) + { + TRACE0("Unable to GetDIBits\n"); + AfxThrowResourceException(); + } + + // If the driver did not fill in the biSizeImage field, then compute it + // Each scan line of the image is aligned on a DWORD (32bit) boundary + if (m_DIBinfo.bmiHeader.biSizeImage == 0) + m_DIBinfo.bmiHeader.biSizeImage = BytesPerLine(m_DIBinfo.bmiHeader.biWidth, + m_DIBinfo.bmiHeader.biBitCount) + * m_DIBinfo.bmiHeader.biHeight; + + return m_iColorTableSize; + +#else + + if (!m_iColorTableSize) + return 0; + + // Fill the color table with the colors from the bitmap's color table + LPRGBQUAD pColorTable = GetColorTable(); + + // Get the color table from the HBITMAP and copy them over. + UINT nCount; + RGBQUAD* pRGB = new RGBQUAD[m_iColorTableSize]; + if (pRGB) + { + HBITMAP hOldBitmap = (HBITMAP) SelectObject(hdc, hBitmap); + nCount = CEGetDIBColorTable(hdc, 0, m_iColorTableSize, pRGB); + SelectObject(hdc, hOldBitmap); + if (nCount) + { + // m_iColorTableSize = nCount; + memcpy(pColorTable, pRGB, nCount*sizeof(RGBQUAD)); + } + } + delete [] pRGB; + + // Didn't work - so synthesize one. + if (!nCount) + { + nCount = min( m_iColorTableSize, sizeof(ms_StdColors) / sizeof(ms_StdColors[0]) ); + memcpy(pColorTable, ms_StdColors, nCount*sizeof(RGBQUAD)); + } + + return nCount; +#endif +} + +#ifdef _WIN32_WCE +/********************************************************************** +This function is from the MS KB article "HOWTO: Get the Color Table of +a DIBSection in Windows CE". + +PARAMETERS: +HDC - the Device Context in which the DIBSection is selected +UINT - the index of the first color table entry to retrieve +UINT - the number of color table entries to retrieve +RGBQUAD - a buffer large enough to hold the number of RGBQUAD +entries requested + +RETURNS: +UINT - the number of colors placed in the buffer + +***********************************************************************/ +UINT CEGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, + RGBQUAD *pColors) +{ + if (pColors == NULL) + return 0; // No place to put them, fail + + // Get a description of the DIB Section + HBITMAP hDIBSection = (HBITMAP) GetCurrentObject( hdc, OBJ_BITMAP ); + + DIBSECTION ds; + DWORD dwSize = GetObject( hDIBSection, sizeof(DIBSECTION), &ds ); + + if (dwSize != sizeof(DIBSECTION)) + return 0; // Must not be a DIBSection, fail + + if (ds.dsBmih.biBitCount > 8) + return 0; // Not Palettized, fail + + // get the number of colors to return per BITMAPINFOHEADER docs + UINT cColors; + if (ds.dsBmih.biClrUsed) + cColors = ds.dsBmih.biClrUsed; + else + cColors = 1 << (ds.dsBmih.biBitCount*ds.dsBmih.biPlanes); + + // Create a mask for the palette index bits for 1, 2, 4, and 8 bpp + WORD wIndexMask = (0xFF << (8 - ds.dsBmih.biBitCount)) & 0x00FF; + + // Get the pointer to the image bits + LPBYTE pBits = (LPBYTE) ds.dsBm.bmBits; + + // Initialize the loop variables + cColors = min( cColors, cEntries ); + BYTE OldPalIndex = *pBits; + + UINT TestPixelY; + if (ds.dsBmih.biHeight > 0 ) + // If button up DIB, pBits points to last row + TestPixelY = ds.dsBm.bmHeight-1; + else + // If top down DIB, pBits points to first row + TestPixelY = 0; + + for (UINT iColor = uStartIndex; iColor < cColors; iColor++) + { + COLORREF rgbColor; + + // Set the palette index for the test pixel, + // modifying only the bits for one pixel + *pBits = (iColor << (8 - ds.dsBmih.biBitCount)) | + (*pBits & ~wIndexMask); + + // now get the resulting color + rgbColor = GetPixel( hdc, 0, TestPixelY ); + + pColors[iColor - uStartIndex].rgbReserved = 0; + pColors[iColor - uStartIndex].rgbBlue = GetBValue(rgbColor); + pColors[iColor - uStartIndex].rgbRed = GetRValue(rgbColor); + pColors[iColor - uStartIndex].rgbGreen = GetGValue(rgbColor); + } + + // Restore the test pixel + *pBits = OldPalIndex; + + return cColors; +} +#endif + +// --- In  : pDC - device context to use when calling CreateCompatibleDC +// bSelectPalette - if TRUE, the current palette will be preselected +// --- Out : +// --- Returns : A pointer to a memory DC +// --- Effect : Creates a memory DC and selects in the current bitmap so it can be +// modified using the GDI functions. Only one memDC can be created for +// a given CDIBSectionLite object. If you have a memDC but wish to recreate it +// as compatible with a different DC, then call ReleaseMemoryDC first. +// If the memory DC has already been created then it will be recycled. +// Note that if using this in an environment where the color depth of +// the screen may change, then you will need to set "m_bReuseMemDC" to FALSE +CDC* CDIBSectionLite::GetMemoryDC(CDC* pDC /*=NULL*/, BOOL bSelectPalette /*=TRUE*/) +{ +#ifdef DIBSECTION_NO_MEMDC_REUSE + ReleaseMemoryDC(TRUE); +#else + if (!m_bReuseMemDC) + ReleaseMemoryDC(TRUE); + else if (m_MemDC.GetSafeHdc()) // Already created? + { +#ifndef _WIN32_WCE + // Flush the GDI batch queue + GdiFlush(); +#endif + return &m_MemDC; + } +#endif // DIBSECTION_NO_MEMDC_REUSE + + // Create a memory DC compatible with the given DC + if (!m_MemDC.CreateCompatibleDC(pDC)) + return NULL; + + // Select in the bitmap + m_hOldBitmap = (HBITMAP) ::SelectObject(m_MemDC.GetSafeHdc(), m_hBitmap); + +#ifndef DIBSECTION_NO_PALETTE + // Select in the palette + if (bSelectPalette && UsesPalette(&m_MemDC)) + { + // Palette should already have been created - but just in case... + if (!m_Palette.GetSafeHandle()) + CreatePalette(); + + m_pOldPalette = m_MemDC.SelectPalette(&m_Palette, FALSE); + m_MemDC.RealizePalette(); + } + else + m_pOldPalette = NULL; +#endif // DIBSECTION_NO_PALETTE + +#ifndef _WIN32_WCE + // Flush the GDI batch queue + GdiFlush(); +#endif // _WIN32_WCE + + return &m_MemDC; +} + +// --- In  : bForceRelease - if TRUE, then the memory DC is forcibly released +// --- Out : +// --- Returns : TRUE on success +// --- Effect : Selects out the current bitmap and deletes the mem dc. If bForceRelease +// is FALSE, then the DC release will not actually occur. This is provided +// so you can have +// +// GetMemoryDC(...) +// ... do something +// ReleaseMemoryDC() +// +// bracketed calls. If m_bReuseMemDC is subsequently set to FALSE, then +// the same code fragment will still work. +BOOL CDIBSectionLite::ReleaseMemoryDC(BOOL bForceRelease /*=FALSE*/) +{ + if ( !m_MemDC.GetSafeHdc() +#ifndef DIBSECTION_NO_MEMDC_REUSE + || (m_bReuseMemDC && !bForceRelease) +#endif // DIBSECTION_NO_MEMDC_REUSE + ) + return TRUE; // Nothing to do + +#ifndef _WIN32_WCE + // Flush the GDI batch queue + GdiFlush(); +#endif // _WIN32_WCE + + // Select out the current bitmap + if (m_hOldBitmap) + ::SelectObject(m_MemDC.GetSafeHdc(), m_hOldBitmap); + m_hOldBitmap = NULL; + +#ifndef DIBSECTION_NO_PALETTE + // Select out the current palette + if (m_pOldPalette) + m_MemDC.SelectPalette(m_pOldPalette, FALSE); + m_pOldPalette = NULL; +#endif // DIBSECTION_NO_PALETTE + + // Delete the memory DC + return m_MemDC.DeleteDC(); +} + + +#ifdef _DEBUG +// Makes trace windows a little bit more informative... +void CDIBSectionLite::_ShowLastError() +{ + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); + TRACE1("Last error: %s\n", lpMsgBuf); + LocalFree(lpMsgBuf); +} +#else +void CDIBSectionLite::_ShowLastError() {} +#endif diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.h new file mode 100644 index 0000000..7bb0705 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DIBSectionLite.h @@ -0,0 +1,243 @@ +#if !defined(AFX_CDIBSECTIONLITE_H__35D9F3D4_B960_11D2_A981_2C4476000000__INCLUDED_) +#define AFX_CDIBSECTIONLITE_H__35D9F3D4_B960_11D2_A981_2C4476000000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// DIBSectionLite.h : header file +// + +// Copyright © Dundas Software Ltd. 1999, All Rights Reserved + +// ////////////////////////////////////////////////////////////////////////// + +// Properties: +// NO Abstract class (does not have any objects) +// NO Derived from CWnd +// NO Is a CWnd. +// NO Two stage creation (constructor & Create()) +// NO Has a message map +// NO Needs a resource (template) +// YES Persistent objects (saveable on disk) +// YES Uses exceptions + +// ////////////////////////////////////////////////////////////////////////// + +// Desciption : + +// CDIBSectionLite is DIBSection wrapper class for win32 and WinCE platforms. +// This class provides a simple interface to DIBSections including loading, +// saving and displaying DIBsections. +// +// Full palette support is provided for Win32 and CE 2.11 and above. + +// Using CDIBSectionLite : + +// This class is very simple to use. The bitmap can be set using either SetBitmap() +// (which accepts either a Device dependant or device independant bitmap, or a +// resource ID) or by using Load(), which allows an image to be loaded from disk. +// To display the bitmap simply use Draw or Stretch. +// +// eg. +// +// CDIBsection dibsection; +// dibsection.Load(_T("image.bmp")); +// dibsection.Draw(pDC, CPoint(0,0)); // pDC is of type CDC* +// +// CDIBsection dibsection; +// dibsection.SetBitmap(IDB_BITMAP); +// dibsection.Draw(pDC, CPoint(0,0)); // pDC is of type CDC* +// +// The CDIBsection API includes many methods to extract information about the +// image, as well as palette options for getting and setting the current palette. +// +// Author: Chris Maunder (cmaunder@dundas.com) +// Date : 12 April 1999 + + +///////////////////////////////////////////////////////////////////////////// +// defines + +//#define DIBSECTION_NO_DITHER // Disallow dithering via DrawDib functions +#define DIBSECTION_NO_MEMDC_REUSE // Disallow the reuse of memory DC's +//#define DIBSECTION_NO_PALETTE // Remove palette support +/*// Only provide palette support for non-CE platforms, or for CE 2.11 and above +#ifdef _WIN32_WCE +#define DIBSECTION_NO_DITHER // DrawDib not supported on CE +#if (_WIN32_WCE < 211) +#define DIBSECTION_NO_PALETTE // No palette support on early CE devices +#endif +#endif +*/ +// Include headers and lib for DrawDib routines +#ifndef DIBSECTION_NO_DITHER +#include +#pragma comment(lib, "vfw32") +#endif + + +#define DS_BITMAP_FILEMARKER ((WORD) ('M' << 8) | 'B') // is always "BM" = 0x4D42 + +///////////////////////////////////////////////////////////////////////////// +// BITMAPINFO wrapper + +struct DIBINFO : public BITMAPINFO +{ + RGBQUAD arColors[255]; // Color table info - adds an extra 255 entries to palette + + operator LPBITMAPINFO() { return (LPBITMAPINFO) this; } + operator LPBITMAPINFOHEADER() { return &bmiHeader; } + RGBQUAD* ColorTable() { return bmiColors; } +}; + +///////////////////////////////////////////////////////////////////////////// +// LOGPALETTE wrapper + +#ifndef DIBSECTION_NO_PALETTE +struct PALETTEINFO : public LOGPALETTE +{ + PALETTEENTRY arPalEntries[255]; // Palette entries + + PALETTEINFO() + { + palVersion = (WORD) 0x300; + palNumEntries = 0; + ::memset(palPalEntry, 0, 256*sizeof(PALETTEENTRY)); + } + + operator LPLOGPALETTE() { return (LPLOGPALETTE) this; } + operator LPPALETTEENTRY() { return (LPPALETTEENTRY) (palPalEntry); } +}; +#endif // DIBSECTION_NO_PALETTE + + +///////////////////////////////////////////////////////////////////////////// +// CDIBSectionLite object + +class CDIBSectionLite : public CObject +{ +// Construction +public: + CDIBSectionLite(); + virtual ~CDIBSectionLite(); + void DeleteObject(); + +// static helpers +public: + static int BytesPerLine(int nWidth, int nBitsPerPixel); + static int NumColorEntries(int nBitsPerPixel, int nCompression); + + static RGBQUAD ms_StdColors[]; +#ifndef DIBSECTION_NO_PALETTE + static BOOL UsesPalette(CDC* pDC) { return (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE); } + static BOOL CreateHalftonePalette(CPalette& palette, int nNumColors); +#endif // DIBSECTION_NO_PALETTE + +// Attributes +public: + HBITMAP GetSafeHandle() const { return (this)? m_hBitmap : NULL; } + operator HBITMAP() const { return GetSafeHandle(); } + CSize GetSize() const { return CSize(GetWidth(), GetHeight()); } + int GetHeight() const { return m_DIBinfo.bmiHeader.biHeight; } + int GetWidth() const { return m_DIBinfo.bmiHeader.biWidth; } + int GetPlanes() const { return m_DIBinfo.bmiHeader.biPlanes; } + int GetBitCount() const { return m_DIBinfo.bmiHeader.biBitCount; } + LPVOID GetDIBits() { return m_ppvBits; } + LPBITMAPINFO GetBitmapInfo() { return (BITMAPINFO*) m_DIBinfo; } + DWORD GetImageSize() const { return m_DIBinfo.bmiHeader.biSizeImage; } + LPBITMAPINFOHEADER GetBitmapInfoHeader() { return (BITMAPINFOHEADER*) m_DIBinfo; } + +// Operations (Palette) +public: + LPRGBQUAD GetColorTable() { return m_DIBinfo.ColorTable(); } + BOOL SetColorTable(UINT nNumColors, RGBQUAD *pColors); + int GetColorTableSize() { return m_iColorTableSize; } +#ifndef DIBSECTION_NO_PALETTE + CPalette *GetPalette() { return &m_Palette; } + BOOL SetPalette(CPalette* pPalette); + BOOL SetLogPalette(LOGPALETTE* pLogPalette); +#endif // DIBSECTION_NO_PALETTE + +// Operations (Setting the bitmap) +public: + BOOL SetBitmap(UINT nIDResource); + BOOL SetBitmap(LPCTSTR lpszResourceName); + BOOL SetBitmap(HBITMAP hBitmap +#ifndef DIBSECTION_NO_PALETTE + , CPalette* pPalette = NULL +#endif + ); + BOOL SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits); + + BOOL Load(LPCTSTR lpszFileName); + BOOL Save(LPCTSTR lpszFileName); + BOOL Copy(CDIBSectionLite& Bitmap); + +// Operations (Display) +public: + BOOL Draw(CDC* pDC, CPoint ptDest, BOOL bForceBackground = FALSE); + BOOL Stretch(CDC* pDC, CPoint ptDest, CSize size, BOOL bForceBackground = FALSE); + +#ifndef DIBSECTION_NO_DITHER + BOOL SetDither(BOOL bDither); + BOOL GetDither(); +#endif // DIBSECTION_NO_DITHER + + CDC* GetMemoryDC(CDC* pDC = NULL, BOOL bSelectPalette = TRUE); + BOOL ReleaseMemoryDC(BOOL bForceRelease = FALSE); + +// Overrideables + +// Implementation +public: +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Implementation +protected: + void _ShowLastError(); +#ifndef DIBSECTION_NO_PALETTE + BOOL CreatePalette(); + BOOL FillDIBColorTable(UINT nNumColors, RGBQUAD *pRGB); +#endif // DIBSECTION_NO_PALETTE + UINT GetColorTableEntries(HDC hdc, HBITMAP hBitmap); +#ifndef DIBSECTION_NO_DITHER + HDRAWDIB GetDrawDibContext(); +#endif // DIBSECTION_NO_DITHER + +protected: + HBITMAP m_hBitmap; // Handle to DIBSECTION + DIBINFO m_DIBinfo; // Bitmap header & color table info + VOID *m_ppvBits; // Pointer to bitmap bits + UINT m_iColorDataType; // color data type (palette or RGB values) + UINT m_iColorTableSize; // Size of color table + + CDC m_MemDC; // Memory DC for drawing on bitmap + +#ifndef DIBSECTION_NO_DITHER + BOOL m_bDither; // Use DrawDib routines for dithering? + HDRAWDIB m_hDrawDib; // handle to a DrawDib DC +#endif + +#ifndef DIBSECTION_NO_MEMDC_REUSE + BOOL m_bReuseMemDC; // Reeuse the memory DC? (Quicker, but not fully tested) +#endif + +#ifndef DIBSECTION_NO_PALETTE + CPalette m_Palette; // Color palette + CPalette *m_pOldPalette; +#endif // DIBSECTION_NO_PALETTE + +private: + HBITMAP m_hOldBitmap; // Storage for previous bitmap in Memory DC +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CDIBSECTIONLITE_H__35D9F3D4_B960_11D2_A981_2C4476000000__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.cpp new file mode 100644 index 0000000..f77fb96 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.cpp @@ -0,0 +1,245 @@ +// DefaultsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "DefaultsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDefaultsDlg dialog + + +CDefaultsDlg::CDefaultsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDefaultsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDefaultsDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CDefaultsDlg"); +} + + +void CDefaultsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDefaultsDlg) + DDX_Control(pDX, IDC_EDSCHEDWINDOW, m_edSchedWindow); + DDX_Control(pDX, IDC_EDAUTOREFRESHSECS, m_edAutoRefresh); + DDX_Control(pDX, IDC_CBREOPENSTATUS, m_cbStatusReopen); + DDX_Control(pDX, IDC_CBNEWSTATUS, m_cbStatusNew); + DDX_Control(pDX, IDC_CBCLOSEDSTATUS, m_cbStatusClosed); + DDX_Control(pDX, IDC_CKESTIMATES, m_ckEstimates); + DDX_Control(pDX, IDC_EDPROVSTATE, m_edProvState); + DDX_Control(pDX, IDC_EDPOSTAL, m_edPostal); + DDX_Control(pDX, IDC_EDCOUNTRY, m_edCountry); + DDX_Control(pDX, IDC_EDCITY, m_edCity); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDefaultsDlg, CDialog) + //{{AFX_MSG_MAP(CDefaultsDlg) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_BN_CLICKED(IDC_CKESTIMATES, OnCkestimates) + ON_EN_KILLFOCUS(IDC_EDAUTOREFRESHSECS, OnKillfocusEdautorefreshsecs) + ON_EN_KILLFOCUS(IDC_EDSCHEDWINDOW, OnKillfocusEdschedwindow) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDefaultsDlg message handlers + +BOOL CDefaultsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + CString strData; + bool bEstimates; + + //rs->SetConnect(m_pApp->strConnectString); + + + CString q,strIndex; + long lData; + //FILL STATUS LIST + m_cbStatusClosed.Clear(); + m_cbStatusClosed.AddRow(" ","0"); + + m_cbStatusNew.Clear(); + m_cbStatusNew.AddRow(" ","0"); + + m_cbStatusReopen.Clear(); + m_cbStatusReopen.AddRow(" ","0"); + + + rs->QueryReadOnly("SELECT probstat.id, probstat.notes FROM probstat ORDER BY probstat.id;"); + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("notes",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbStatusClosed.AddRow(strData,strIndex); + m_cbStatusNew.AddRow(strData,strIndex); + m_cbStatusReopen.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + rs->Query("SELECT * FROM defaults;"); + + rs->FetchField("city",&strData); + m_edCity.SetWindowText(strData); + + rs->FetchField("stateprov",&strData); + m_edProvState.SetWindowText(strData); + + rs->FetchField("postal",&strData); + m_edPostal.SetWindowText(strData); + + rs->FetchField("country",&strData); + m_edCountry.SetWindowText(strData); + + rs->FetchField("woestimate",&bEstimates); + m_ckEstimates.SetCheck(bEstimates ? TRUE : FALSE); + + rs->FetchField("wonewstat",&lData); + m_cbStatusNew.Select(lData); + + rs->FetchField("woclosestat",&lData); + m_cbStatusClosed.Select(lData); + + rs->FetchField("woreopenstat",&lData); + m_cbStatusReopen.Select(lData); + + rs->FetchField("schedrfrshsecs",&lData);//m_pApp->m_nSchedRefreshSecs); + strData.Format("%u",lData); + m_edAutoRefresh.SetWindowText(strData); + + rs->FetchField("schedwindow",&lData);//m_pApp->m_nSchedRefreshSecs); + strData.Format("%u",lData); + m_edSchedWindow.SetWindowText(strData); + + + + + + + + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +CDefaultsDlg::~CDefaultsDlg() +{ +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CDefaultsDlg::OnBtndone() +{ + CString strData; + bool bEstimates; + long lData; + + m_edCity.GetWindowText(strData); + rs->UpdateField("city",&strData); + + m_edProvState.GetWindowText(strData); + rs->UpdateField("stateprov",&strData); + + m_edPostal.GetWindowText(strData); + rs->UpdateField("postal",&strData); + + m_edCountry.GetWindowText(strData); + rs->UpdateField("country",&strData); + + bEstimates=m_ckEstimates.GetCheck() ? true : false; + rs->UpdateField("woestimate",&bEstimates); + + lData=atol(m_cbStatusNew.GetCurrentRowID()); + rs->UpdateField("wonewstat",&lData); + m_pApp->m_lDefNewWOStatus=lData; + + lData=atol(m_cbStatusClosed.GetCurrentRowID()); + rs->UpdateField("woclosestat",&lData); + m_pApp->m_lDefClosedWOStatus=lData; + + + lData=atol(m_cbStatusReopen.GetCurrentRowID()); + rs->UpdateField("woreopenstat",&lData); + m_pApp->m_lDefReOpenWOStatus=lData; + + + m_edAutoRefresh.GetWindowText(strData); + lData=atol(strData); + rs->UpdateField("schedrfrshsecs",&lData); + m_pApp->m_lSchedRefreshSecs=lData; + + m_edSchedWindow.GetWindowText(strData); + lData=atol(strData); + rs->UpdateField("schedwindow",&lData); + m_pApp->m_lSchedWindowDays=lData; + + + + + rs->SaveRecord(); + CDialog::OnOK(); +} + +void CDefaultsDlg::OnCkestimates() +{ + // TODO: Add your control notification handler code here + +} + +void CDefaultsDlg::OnKillfocusEdautorefreshsecs() +{ + long x; + CString str; + m_edAutoRefresh.GetWindowText(str); + x=atol(str); + if(x!=0) + { + if(x<60) + { + AfxMessageBox("Must be at least one minute (60 seconds)"); + m_edAutoRefresh.SetWindowText("60"); + } + + } + + +} + +void CDefaultsDlg::OnKillfocusEdschedwindow() +{ + long x; + CString str; + m_edSchedWindow.GetWindowText(str); + x=atol(str); + if(x<4) + { + AfxMessageBox("Must be at least 4 days"); + m_edAutoRefresh.SetWindowText("30"); + } + + if(x>60) + { + AfxMessageBox("Caution: too high a setting may result in slow updates on schedule screen"); + } + + + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.h new file mode 100644 index 0000000..93175e7 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DefaultsDlg.h @@ -0,0 +1,62 @@ +#if !defined(AFX_DEFAULTSDLG_H__3A9EE8C1_43C8_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_DEFAULTSDLG_H__3A9EE8C1_43C8_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DefaultsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDefaultsDlg dialog +#include "gzrset.h" +#include "gzcombo.h" +class CDefaultsDlg : public CDialog +{ +// Construction +public: + ~CDefaultsDlg(); + CDefaultsDlg(CWnd* pParent = NULL); // standard constructor + GZRset* rs; + CSpApp* m_pApp; +// Dialog Data + //{{AFX_DATA(CDefaultsDlg) + enum { IDD = IDD_DEFAULTS }; + CEdit m_edSchedWindow; + CEdit m_edAutoRefresh; + CgzCombo m_cbStatusReopen; + CgzCombo m_cbStatusNew; + CgzCombo m_cbStatusClosed; + CButton m_ckEstimates; + CEdit m_edProvState; + CEdit m_edPostal; + CEdit m_edCountry; + CEdit m_edCity; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDefaultsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDefaultsDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnBtndone(); + afx_msg void OnCkestimates(); + afx_msg void OnKillfocusEdautorefreshsecs(); + afx_msg void OnKillfocusEdschedwindow(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DEFAULTSDLG_H__3A9EE8C1_43C8_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.cpp new file mode 100644 index 0000000..9a316b5 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.cpp @@ -0,0 +1,1381 @@ +// DispatchFieldsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "DispatchFieldsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDispatchFieldsDlg dialog + + +CDispatchFieldsDlg::CDispatchFieldsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CDispatchFieldsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDispatchFieldsDlg) + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Dispatch field selection "); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("Error at:CDispatchFieldsDlg"); + + pdv=new CDispatchView; + +} + +CDispatchFieldsDlg::~CDispatchFieldsDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + delete pdv; +} + + +void CDispatchFieldsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDispatchFieldsDlg) + DDX_Control(pDX, IDC_CKPROJECT, m_ckProject); + DDX_Control(pDX, IDC_CBPROJECTS, m_cbProjects); + DDX_Control(pDX, IDC_CBCATEGORIES, m_cbCategories); + DDX_Control(pDX, IDC_CKCATEGORY, m_ckCategory); + DDX_Control(pDX, IDC_CKSCHEDDATE_TOMORROW, m_ckSchedDate_TOMORROW); + DDX_Control(pDX, IDC_CKCUSTREF, m_ckCustRef); + DDX_Control(pDX, IDC_CKSTATUS, m_ckStatus); + DDX_Control(pDX, IDC_CKOURREF, m_ckOurRef); + DDX_Control(pDX, IDC_CKDATE, m_ckDate); + DDX_Control(pDX, IDC_CKINVOICE, m_ckInvoice); + DDX_Control(pDX, IDC_DTENTRYDATE, m_dtEntryDate); + DDX_Control(pDX, IDC_CBENTRY, m_cbEntry); + DDX_Control(pDX, IDC_LBL16, m_lbl16); + DDX_Control(pDX, IDC_CBREPORTS, m_cbReports); + DDX_Control(pDX, IDC_LBL15, m_lbl15); + DDX_Control(pDX, IDC_CKPREVIEW, m_ckPreview); + DDX_Control(pDX, IDC_CKSCHEDDATE_BETWEEN, m_ckSchedDate_BETWEEN); + DDX_Control(pDX, IDC_EDSQL, m_edSQL); + DDX_Control(pDX, IDC_EDLASTACTIVITY_DAYSAGO, m_edLastActivity_DAYS); + DDX_Control(pDX, IDC_DTCHEDDATE_BETWEEN_START, m_dtSchedDate_START); + DDX_Control(pDX, IDC_DTCHEDDATE_BETWEEN_END, m_dtSchedDate_END); + DDX_Control(pDX, IDC_CKSCHEDDATE_TODAY, m_ckSchedDate_TODAY); + DDX_Control(pDX, IDC_CKSCHEDDATE_THISWEEK, m_ckSchedDate_THISWEEK); + DDX_Control(pDX, IDC_CKSCHEDDATE_THISMONTH, m_ckSchedDate_THISMONTH); + DDX_Control(pDX, IDC_CKSCHEDDATE_ANY, m_ckSchedDate_ANY); + DDX_Control(pDX, IDC_CKONSITE_ONSITEONLY, m_ckOnsite_ONSITE); + DDX_Control(pDX, IDC_CKONSITE_INHOUSEONLY, m_ckOnsite_INHOUSE); + DDX_Control(pDX, IDC_CKONSITE_BOTH, m_ckOnsite_BOTH); + DDX_Control(pDX, IDC_CKLASTACTIVITY_ANY, m_ckLastActivity_ANY); + DDX_Control(pDX, IDC_CKCLOSEDOPEN_OPENONLY, m_ckClosedOpen_OPEN); + DDX_Control(pDX, IDC_CKCLOSEDOPEN_CLOSEDONLY, m_ckClosedOpen_CLOSED); + DDX_Control(pDX, IDC_CKCLOSEDOPEN_BOTH, m_ckClosedOpen_BOTH); + DDX_Control(pDX, IDC_CBZONES, m_cbZone); + DDX_Control(pDX, IDC_CBTECHS, m_cbTech); + DDX_Control(pDX, IDC_CBCLIENTS, m_cbClient); + DDX_Control(pDX, IDC_LBL14, m_lbl14); + DDX_Control(pDX, IDC_LBL9, m_lbl9); + DDX_Control(pDX, IDC_LBL8, m_lbl8); + DDX_Control(pDX, IDC_LBL7, m_lbl7); + DDX_Control(pDX, IDC_LBL6, m_lbl6); + DDX_Control(pDX, IDC_LBL5, m_lbl5); + DDX_Control(pDX, IDC_LBL4, m_lbl4); + DDX_Control(pDX, IDC_LBL3, m_lbl3); + DDX_Control(pDX, IDC_LBL2, m_lbl2); + DDX_Control(pDX, IDC_LBL13, m_lbl13); + DDX_Control(pDX, IDC_LBL12, m_lbl12); + DDX_Control(pDX, IDC_LBL11, m_lbl11); + DDX_Control(pDX, IDC_LBL10, m_lbl10); + DDX_Control(pDX, IDC_LBL1, m_lbl1); + DDX_Control(pDX, IDC_CKZONE, m_ckZone); + DDX_Control(pDX, IDC_CKWO, m_ckWO); + DDX_Control(pDX, IDC_CKSCHEDTECH, m_ckSchedTech); + DDX_Control(pDX, IDC_CKSCHEDEND, m_ckSchedEndDate); + DDX_Control(pDX, IDC_CKSCHEDDATE, m_ckSchedDate); + DDX_Control(pDX, IDC_CKPOSTAL, m_ckPostal); + DDX_Control(pDX, IDC_CKONSITE, m_ckOnsite); + DDX_Control(pDX, IDC_CKLASTACTIVITY, m_ckLastActivity); + DDX_Control(pDX, IDC_CKENTRYDATE, m_ckEntryDate); + DDX_Control(pDX, IDC_CKCLOSEDDATE, m_ckClosedDate); + DDX_Control(pDX, IDC_CKCLOSED, m_ckClosed); + DDX_Control(pDX, IDC_CKCLIENT, m_ckClient); + DDX_Control(pDX, IDC_CKCITY, m_ckCity); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CBSTATUS, m_cbStatus); + DDX_Control(pDX, IDC_LBLCREATEDDAYS, m_lblCreatedDays); + DDX_Control(pDX, IDC_EDCREATEDDAYS, m_edCreatedDays); +} + + +BEGIN_MESSAGE_MAP(CDispatchFieldsDlg, CDialog) +//{{AFX_MSG_MAP(CDispatchFieldsDlg) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_BN_CLICKED(IDC_BTNCANCEL, OnBtncancel) +ON_BN_CLICKED(IDC_BUTTON1, OnButton1) +ON_BN_CLICKED(IDC_CKCLOSEDOPEN_BOTH, OnCkclosedopenBoth) +ON_BN_CLICKED(IDC_CKCLOSEDOPEN_OPENONLY, OnCkclosedopenOpenonly) +ON_BN_CLICKED(IDC_CKCLOSEDOPEN_CLOSEDONLY, OnCkclosedopenClosedonly) +ON_BN_CLICKED(IDC_CKONSITE_BOTH, OnCkonsiteBoth) +ON_BN_CLICKED(IDC_CKONSITE_INHOUSEONLY, OnCkonsiteInhouseonly) +ON_BN_CLICKED(IDC_CKONSITE_ONSITEONLY, OnCkonsiteOnsiteonly) +ON_BN_CLICKED(IDC_CKSCHEDDATE_ANY, OnCkscheddateAny) +ON_BN_CLICKED(IDC_CKSCHEDDATE_BETWEEN, OnCkscheddateBetween) +ON_BN_CLICKED(IDC_CKSCHEDDATE_THISMONTH, OnCkscheddateThismonth) +ON_BN_CLICKED(IDC_CKSCHEDDATE_THISWEEK, OnCkscheddateThisweek) +ON_BN_CLICKED(IDC_CKSCHEDDATE_TODAY, OnCkscheddateToday) +ON_BN_CLICKED(IDC_CKLASTACTIVITY_ANY, OnCklastactivityAny) + ON_CBN_CLOSEUP(IDC_CBENTRY, OnCloseupCbentry) + ON_BN_CLICKED(IDC_CKINVOICE, OnCkinvoice) + ON_BN_CLICKED(IDC_CKDATE, OnCkdate) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTCHEDDATE_BETWEEN_START, OnDatetimechangeDtcheddateBetweenStart) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTCHEDDATE_BETWEEN_END, OnDatetimechangeDtcheddateBetweenEnd) + ON_BN_CLICKED(IDC_CKOURREF, OnCkourref) + ON_BN_CLICKED(IDC_CKSTATUS, OnCkstatus) + ON_BN_CLICKED(IDC_CKSCHEDDATE_TOMORROW, OnCkscheddateTomorrow) + ON_CBN_CLOSEUP(IDC_CBCATEGORIES, OnCloseupCbcategories) + ON_BN_CLICKED(IDC_CKCATEGORY, OnCkcategory) +ON_CBN_CLOSEUP(IDC_CBCLIENTS, BuildSQL) +ON_CBN_CLOSEUP(IDC_CBTECHS, BuildSQL) +ON_CBN_CLOSEUP(IDC_CBZONES, BuildSQL) +ON_BN_CLICKED(IDC_CKCITY, BuildSQL) +ON_BN_CLICKED(IDC_CKCLIENT, BuildSQL) +ON_BN_CLICKED(IDC_CKCLOSED, BuildSQL) +ON_BN_CLICKED(IDC_CKCLOSEDDATE, BuildSQL) +ON_BN_CLICKED(IDC_CKENTRYDATE, BuildSQL) +ON_BN_CLICKED(IDC_CKLASTACTIVITY, BuildSQL) +ON_BN_CLICKED(IDC_CKONSITE, BuildSQL) +ON_BN_CLICKED(IDC_CKPOSTAL, BuildSQL) +ON_BN_CLICKED(IDC_CKSCHEDDATE, BuildSQL) +ON_BN_CLICKED(IDC_CKSCHEDEND, BuildSQL) +ON_BN_CLICKED(IDC_CKSCHEDTECH, BuildSQL) +ON_BN_CLICKED(IDC_CKWO, BuildSQL) +ON_BN_CLICKED(IDC_CKZONE, BuildSQL) +ON_EN_KILLFOCUS(IDC_EDLASTACTIVITY_DAYSAGO, BuildSQL) + ON_BN_CLICKED(IDC_CKPROJECT, OnCkproject) + ON_CBN_CLOSEUP(IDC_CBPROJECTS, OnCloseupCbprojects) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDispatchFieldsDlg message handlers + +void CDispatchFieldsDlg::OnBtndone() +{ + + BuildSQL(); + if(*passeddv==*pdv) //cool operator overload! + pdv->IsModified=false; + else + pdv->IsModified=true; + + + *passeddv=*pdv; + + CDialog::OnOK(); +} + + +//******************************************************* +void CDispatchFieldsDlg::SetReturnVariable(CDispatchView * dvReturn) +{ + passeddv=dvReturn; + *pdv=*passeddv; +} + + +//******************************************************* +void CDispatchFieldsDlg::OnOK() +{} + +BOOL CDispatchFieldsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + ShowWindow(FALSE); + CString str; + CWaitCursor wait; + FillLists(); + ASSERT(pdv!=NULL); + + m_lbl1.SetFontBold(TRUE); + m_lbl2.SetFontBold(TRUE); + m_lbl3.SetFontBold(TRUE); + m_lbl4.SetFontBold(TRUE); + m_lbl5.SetFontBold(TRUE); + m_lbl6.SetFontBold(TRUE); + m_lbl7.SetFontBold(TRUE); + m_lbl8.SetFontBold(TRUE); + m_lbl9.SetFontBold(TRUE); + m_lbl10.SetFontBold(TRUE); + m_lbl11.SetFontBold(TRUE); + m_lbl12.SetFontBold(TRUE); + m_lbl13.SetFontBold(TRUE); + //title: + m_lbl14.SetFontBold(TRUE); + m_lbl14.SetFontSize(14); + + + m_lbl15.SetFontBold(TRUE); + m_lbl16.SetFontBold(TRUE); + //WO ENTRY DATE + m_dtEntryDate.SetTime(pdv->woentrydate); + + //WOENTERY DATE TYPE CODE + m_cbEntry.SetCurSel(pdv->woentrydatetype); + + m_edCreatedDays.ShowWindow(FALSE); + m_lblCreatedDays.ShowWindow(FALSE); + m_dtEntryDate.ShowWindow(FALSE); + + + if(pdv->woentrydatetype==1 || pdv->woentrydatetype==2) + { + m_dtEntryDate.ShowWindow(TRUE); + } + + //More than / less than days + if(12==pdv->woentrydatetype || 13==pdv->woentrydatetype) + { + m_edCreatedDays.ShowWindow(TRUE); + m_lblCreatedDays.ShowWindow(TRUE); + + } + str.Format("%u",pdv->lCreatedDays); + m_edCreatedDays.SetWindowText(str); + + + //CLIENT + m_ckClient.SetCheck(pdv->client==0 ? FALSE : TRUE); + m_cbClient.Select(pdv->client); + + //DATE - combined standard/quick date + m_ckDate.SetCheck(pdv->date==0 ? FALSE : TRUE); + + //SCHED DATE + m_dtSchedDate_START.EnableWindow(FALSE); + m_dtSchedDate_END.EnableWindow(FALSE); + m_ckSchedDate.SetCheck(pdv->schedstart==0 ? FALSE : TRUE); + switch( pdv->schedstart) + {//0 = not displayed otherwise 1=any,2=today,3=week,4=month,5=between, 6=TOMORROW + case 1: + m_ckSchedDate_ANY.SetCheck(TRUE); + break; + case 2: + m_ckSchedDate_TODAY.SetCheck(TRUE); + break; + case 3: + m_ckSchedDate_THISWEEK.SetCheck(TRUE); + break; + case 4: + m_ckSchedDate_THISMONTH.SetCheck(TRUE); + break; + case 6: + m_ckSchedDate_TOMORROW.SetCheck(TRUE); + break; + default ://between + { + m_ckSchedDate_BETWEEN.SetCheck(TRUE); + m_dtSchedDate_START.EnableWindow(TRUE); + m_dtSchedDate_END.EnableWindow(TRUE); + m_dtSchedDate_START.SetTime(pdv->scheddatestart); + m_dtSchedDate_END.SetTime(pdv->scheddateend); + } + + + } + + //SCHED END DATE + m_ckSchedEndDate.SetCheck(pdv->schedenddate==0 ? FALSE : TRUE); + + //SCHED TECH + m_ckSchedTech.SetCheck(pdv->schedtech==-2 ? FALSE : TRUE); + m_cbTech.Select(pdv->schedtech); + + //ENTRY DATE + m_ckEntryDate.SetCheck(pdv->wocreateddate==0 ? FALSE : TRUE); + + //LAST ACTIVITY + m_edLastActivity_DAYS.EnableWindow(FALSE); + m_ckLastActivity_ANY.SetCheck(TRUE); + m_ckLastActivity.SetCheck(TRUE); + switch( pdv->lastactivity) + {//0 = not displayed otherwise -1=any, or x days + case 0: + m_ckLastActivity.SetCheck(FALSE); + break; + case -1: + m_ckLastActivity.SetCheck(TRUE); + break; + default ://X days + m_ckLastActivity_ANY.SetCheck(FALSE); + m_edLastActivity_DAYS.EnableWindow(TRUE); + str.Format("%u",pdv->lastactivity); + m_edLastActivity_DAYS.SetWindowText(str); + } + + //ONSITE + m_ckOnsite.SetCheck(TRUE); + switch( pdv->onsite) + { //0 = not displayed otherwise 1="both", 2= "onsite", 3="inhouse" + case 0: + m_ckOnsite.SetCheck(FALSE); + break; + case 1: + m_ckOnsite_BOTH.SetCheck(TRUE); + break; + case 2: + m_ckOnsite_ONSITE.SetCheck(TRUE); + break; + case 3: + m_ckOnsite_INHOUSE.SetCheck(TRUE); + break; + } + + //CLOSED + m_ckClosed.SetCheck(TRUE); + switch( pdv->closed) + {//0 = not displayed 1=both,2="closed",3="open" + case 0: + m_ckClosed.SetCheck(FALSE); + break; + case 1: + m_ckClosedOpen_BOTH.SetCheck(TRUE); + break; + case 2: + m_ckClosedOpen_CLOSED.SetCheck(TRUE); + break; + case 3: + m_ckClosedOpen_OPEN.SetCheck(TRUE); + break; + } + + //CLOSED DATE + m_ckClosedDate.SetCheck(pdv->closeddate==0 ? FALSE : TRUE); + + //POSTAL + m_ckPostal.SetCheck(pdv->postal==0 ? FALSE : TRUE); + + //CITY + m_ckCity.SetCheck(pdv->city==0 ? FALSE : TRUE); + + //WORKORDER + m_ckWO.SetCheck(pdv->workorder==0 ? FALSE : TRUE); + + //INVOICE # + m_ckInvoice.SetCheck(pdv->invoice==0 ? FALSE : TRUE); + + //Our ref # + m_ckOurRef.SetCheck(pdv->ourrefnumber==0 ? FALSE : TRUE); + + //Cust ref # + m_ckCustRef.SetCheck(pdv->custrefnumber==0 ? FALSE : TRUE); + + //Status + m_ckStatus.SetCheck(pdv->status==0 ? FALSE : TRUE); + m_cbStatus.Select(pdv->status); + + //ZONE + m_ckZone.SetCheck(pdv->zone==0 ? FALSE : TRUE); + m_cbZone.Select(pdv->zone); + + //CATEGORY + m_ckCategory.SetCheck(pdv->category==0 ? FALSE : TRUE); + m_cbCategories.Select(pdv->category); + + //PROJECTS + m_ckProject.SetCheck(pdv->project==0 ? FALSE : TRUE); + m_cbProjects.Select(pdv->project); + + + //PREVIEW DESCripTION + m_ckPreview.SetCheck(pdv->preview==0 ? FALSE : TRUE); + + //REPORT NAME + m_cbReports.Select(pdv->virtualreport); + + + ShowWindow(SW_MAXIMIZE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +//************************************************* +void CDispatchFieldsDlg::OnBtncancel() +{ + + CDialog::OnCancel(); +} + + + +//**************************************** +//Build the SQL statement +//Set the various dispatchview class values +//update the user interface to provide feedback +void CDispatchFieldsDlg::BuildSQL() +{ + bool NoChoices=true; + CString str1,str2; + long lData; + COleDateTime dtData1,dtData2,dtDefault; + dtDefault.SetDate(1968,03,12); + //AfxMessageBox("BuildSQL"); + //Iterate through the fields and build the WHERE clause + //of the sql statement. + pdv->sqlcriteria.Empty(); + + + + + + //CLIENT + if(m_ckClient.GetCheck()==TRUE) + { + pdv->client=-1;//default means show but no criteria + NoChoices=false; + bool bHO=false; + + + //Head office addition June 20 2003 + m_cbClient.GetWindowText(str1); + if(str1.Right(13)=="(head office)") bHO=true; + + str1=m_cbClient.GetCurrentRowID(); + if(str1!="0") + { + //(clients.headoffice)=22) + if(bHO==true) + str2.Format(" ((clients.headoffice)=%s)",str1); + else + str2.Format(" ((wo.client)=%s)",str1); + pdv->sqlcriteria+=str2; + pdv->client=atol(str1); + } + } + else//no client + pdv->client=0; + + + + + + + //ZONE + if(m_ckZone.GetCheck()==TRUE) + { + pdv->zone=-1; + NoChoices=false; + str1=m_cbZone.GetCurrentRowID(); + if(str1!="0") + { + str2.Format(" AND ((clients.czone)=%s)",str1); + pdv->sqlcriteria+=str2; + pdv->zone=atol(str1); + } + + } + else + pdv->zone=0; + + //CATEGORY + if(m_ckCategory.GetCheck()==TRUE) + { + pdv->category=-1; + NoChoices=false; + str1=m_cbCategories.GetCurrentRowID(); + if(str1!="0") + { + str2.Format(" AND ((wo.type)=%s)",str1); + pdv->sqlcriteria+=str2; + pdv->category=atol(str1); + } + + } + else + pdv->category=0; + + + //PROJECT + if(m_ckProject.GetCheck()==TRUE) + { + pdv->project=-1; + NoChoices=false; + str1=m_cbProjects.GetCurrentRowID(); + if(str1!="0") + { + str2.Format(" AND ((wo.project)=%s)",str1); + pdv->sqlcriteria+=str2; + pdv->project=atol(str1); + } + + } + else + pdv->project=0; + + + + + + //TECH + if(m_ckSchedTech.GetCheck()==TRUE) + { + pdv->schedtech=-1; + NoChoices=false; + + str1=m_cbTech.GetCurrentRowID(); + + //Commented out check if tech zero because if you select "any tech" + //it should just show work orders assigned to tech 0 (not assigned) + + //replaced with -1 meaning don't show + if(str1!="-1") + { + //original: + //str2.Format(" AND ((wo.assigntech)=%s)",str1); + str2.Format(" AND ( ((wo.assigntech)=%s) OR ((wo.assigntech2)=%s) OR ((wo.assigntech3)=%s) OR ((wo.assigntech4)=%s) )" + ,str1,str1,str1,str1); + //((wo.assigntech)=2) OR ((wo.assigntech2)=2) OR ((wo.assigntech3)=2) OR ((wo.assigntech4)=2) + pdv->sqlcriteria+=str2; + pdv->schedtech=atol(str1); + } + + } + else + pdv->schedtech=-2;//-2 means don't show the scheduled tech column + + + + //CLOSED/OPEN + str2.Empty(); + if(m_ckClosed.GetCheck()==TRUE) + { + pdv->closed=-1;//default, means show but no criteria + NoChoices=false; + if(m_ckClosedOpen_BOTH.GetCheck()==TRUE) + pdv->closed=1; + + if(m_ckClosedOpen_OPEN.GetCheck()==TRUE) + { + str2.Format(" AND ((wo.closed)=#%s#)",dtDefault.Format(_T("%m/%d/%Y")));//Open + pdv->closed=3; + } + + if(m_ckClosedOpen_CLOSED.GetCheck()==TRUE) + { + str2.Format(" AND ((wo.closed)<>#%s#)",dtDefault.Format(_T("%m/%d/%Y")));//Closed + pdv->closed=2; + } + + pdv->sqlcriteria+=str2; + + } + else + pdv->closed=0; + + + + + //ONSITE + str2.Empty(); + if(m_ckOnsite.GetCheck()==TRUE) + { + pdv->onsite=-1;//default show but no criteria + NoChoices=false; + if(m_ckOnsite_BOTH.GetCheck()==TRUE) + pdv->onsite=1; + + if(m_ckOnsite_ONSITE.GetCheck()==TRUE) + { + pdv->onsite=2; + str2=" AND ((wo.onsite)=True)"; + } + + if(m_ckOnsite_INHOUSE.GetCheck()==TRUE) + { + pdv->onsite=3; + str2=" AND ((wo.onsite)=False)"; + } + + pdv->sqlcriteria+=str2; + + } + else + pdv->onsite=0; + + + + //LAST ACTIVITY + if(m_ckLastActivity.GetCheck()==TRUE) + { + NoChoices=false; + pdv->lastactivity=-1;//default show but no criteria + if(m_ckLastActivity_ANY.GetCheck()!=TRUE) + { + m_edLastActivity_DAYS.GetWindowText(str1); + if(!str1.IsEmpty()) + { + str2.Format(" AND ((wo.modified) < Date( ) - %s)",str1); + pdv->sqlcriteria+=str2; + pdv->lastactivity=atol(str1); + } + } + + + } + else + pdv->lastactivity=0; + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>. +//WO CREATED DATE + //update January 2 2002, changed all date related bits below to use the dateadd function + //was previously stuck on a year hump because it was explicitly looking for wo's within the same year + str1.Empty(); + str2.Empty(); + pdv->woentrydatetype=m_cbEntry.GetCurSel(); + //m_dtEntryDate.SetTime(pdv->woentrydate); + m_dtEntryDate.GetTime(pdv->woentrydate); + pdv->lCreatedDays=0; + + if(pdv->woentrydatetype >0) //0=Anytime + { + switch(pdv->woentrydatetype) + { + case 1://1=After woentrydate + //dtLaborStart.Format(_T("%m/%d/%Y %H:%M:%S") + str1.Format(" AND ((wo.created)>#%s#)", + pdv->woentrydate.Format(_T("%m/%d/%Y 23:59:59"))); + break; + case 2: //2=Before woentrydate + str1.Format(" AND ((wo.created)<#%s#)", + pdv->woentrydate.Format(_T("%m/%d/%Y"))); + break; + case 3: //3=within 1 week + str1=" AND (([wo].[created]))>= (DateAdd(\"d\",-7, Date()))"; + break; + case 4://4=within 2 weeks + str1=" AND (([wo].[created]))>= (DateAdd(\"d\",-14, Date()))"; + break; + case 5: //5=within the last 45 days + str1=" AND (([wo].[created]))>= (DateAdd(\"d\",-45, Date()))"; + break; + case 6: //5=within 1 month + str1=" AND (([wo].[created]))>= (DateAdd(\"m\",-1, Date()))"; + break; + case 7: //6=within 3 months DateAdd("m",-3,Date()) + str1=" AND (([wo].[created]))>= (DateAdd(\"m\",-3, Date()))"; + break; + case 8://7=within 6 months + str1=" AND (([wo].[created]))>= (DateAdd(\"m\",-6, Date()))"; + break; + case 9: //8=within 1 year + str1=" AND (([wo].[created]))>= (DateAdd(\"yyyy\",-1, Date()))"; + break; + case 10: //9=within 2 years + str1=" AND (([wo].[created]))>= (DateAdd(\"yyyy\",-2, Date()))"; + break; + case 11://10=within 5 years + str1=" AND (([wo].[created]))>= (DateAdd(\"yyyy\",-4, Date()))"; + break; + case 12://Less than X days ago + m_edCreatedDays.GetWindowText(str2); + lData=atol(str2); + if(lData==0) + { + str1.Format("Workorder created more than \"%s\" days is invalid\r\n" + "Substituting with 5\r\n",str2); + AfxMessageBox(str1); + m_edCreatedDays.SetWindowText("5"); + m_edCreatedDays.SetFocus(); + lData=5; + } + pdv->lCreatedDays=lData; + str1.Format(" AND (([wo].[created]))>=(DateAdd(\"d\",-%u, Date()))",lData); + break; + case 13://More than X days ago + m_edCreatedDays.GetWindowText(str2); + lData=atol(str2); + if(lData==0) + { + str1.Format("Workorder created more than \"%s\" days is invalid\r\n" + "Substituting with 5\r\n",str2); + AfxMessageBox(str1); + m_edCreatedDays.SetWindowText("5"); + m_edCreatedDays.SetFocus(); + lData=5; + } + pdv->lCreatedDays=lData; + str1.Format(" AND (([wo].[created]))<=(DateAdd(\"d\",-%u, Date()))",lData); + break; + + } + + + +pdv->sqlcriteria+=str1; + + } + + + + + + + //SCHED START DATE + str1.Empty(); + str2.Empty(); + if(m_ckSchedDate.GetCheck()==TRUE) + { + pdv->schedstart=-1;//show but no crit. + NoChoices=false; + + if(m_ckSchedDate_ANY.GetCheck()==TRUE) + pdv->schedstart=1; + + if(m_ckSchedDate_TODAY.GetCheck()==TRUE) + { + str1=" AND ((DatePart(\"y\",[wo].[starttime]))=DatePart(\"y\",Date())) AND ((DatePart(\"yyyy\",[wo].[starttime]))=DatePart(\"yyyy\",Date()))"; + pdv->schedstart=2; + } + + if(m_ckSchedDate_THISWEEK.GetCheck()==TRUE) + { + str1=" AND ((DatePart(\"ww\",[wo].[starttime]))=DatePart(\"ww\",Date())) AND ((DatePart(\"yyyy\",[wo].[starttime]))=DatePart(\"yyyy\",Date()))"; + pdv->schedstart=3; + } + + if(m_ckSchedDate_THISMONTH.GetCheck()==TRUE) + { + str1=" AND ((DatePart(\"m\",[wo].[starttime]))=DatePart(\"m\",Date())) AND ((DatePart(\"yyyy\",[wo].[starttime]))=DatePart(\"yyyy\",Date()))"; + pdv->schedstart=4; + } + + if(m_ckSchedDate_TOMORROW.GetCheck()==TRUE) + { + str1=" AND ((DatePart(\"y\",[wo].[starttime]))=DatePart(\"y\",Date())+1) AND ((DatePart(\"yyyy\",[wo].[starttime]))=DatePart(\"yyyy\",Date()))"; + pdv->schedstart=2; pdv->schedstart=6; + } + + if(m_ckSchedDate_BETWEEN.GetCheck()==TRUE) + { + + m_dtSchedDate_START.GetTime(dtData1); + m_dtSchedDate_END.GetTime(dtData2); + pdv->scheddatestart=dtData1; + pdv->scheddateend=dtData2; + str1.Format(" AND ((wo.starttime) Between #%s# And #%s#)",dtData1.Format(_T("%m/%d/%Y")),dtData2.Format(_T("%m/%d/%Y"))); + pdv->schedstart=5; + + } + pdv->sqlcriteria+=str1; + + } + else + pdv->schedstart=0; + + + + //NON CRITERIA FIELDS: (0=dont display, nonzero means display) + + //POSTAL + pdv->postal=m_ckPostal.GetCheck() ? 1 : 0; + if(pdv->postal==1) NoChoices=false; + //CITY + pdv->city= m_ckCity.GetCheck() ? 1 : 0; + if(pdv->city==1) NoChoices=false; + //workorder + pdv->workorder= m_ckWO.GetCheck() ? 1 : 0; + if(pdv->workorder==1) NoChoices=false; + //CLOSEDDATE + pdv->closeddate = m_ckClosedDate.GetCheck() ? 1 : 0; + if(pdv->closeddate==1) NoChoices=false; + //SCHEDENDDATE + pdv->schedenddate = m_ckSchedEndDate.GetCheck() ? 1 : 0; + if(pdv->schedenddate==1) NoChoices=false; + + //WOCREATEDDATE + pdv->wocreateddate= m_ckEntryDate.GetCheck() ? 1 : 0; + if(pdv->wocreateddate==1) NoChoices=false; + + //DATE - combined standard/quick date column + pdv->date= m_ckDate.GetCheck() ? 1 : 0; + if(pdv->date==1) NoChoices=false; + + + //INVOICE # + pdv->invoice = m_ckInvoice.GetCheck() ? 1 : 0; + if(pdv->invoice==1) NoChoices=false; + + //Our ref # + pdv->ourrefnumber = m_ckOurRef.GetCheck() ? 1 : 0; + if(pdv->ourrefnumber==1) NoChoices=false; + + //Cust ref # + pdv->custrefnumber = m_ckCustRef.GetCheck() ? 1 : 0; + if(pdv->custrefnumber==1) NoChoices=false; + + //STATUS + /*pdv->status = m_ckStatus.GetCheck() ? 1 : 0; + if(pdv->status==1) NoChoices=false;*/ + + if(m_ckStatus.GetCheck()==TRUE) + { + pdv->status=-1; + NoChoices=false; + str1=m_cbStatus.GetCurrentRowID(); + if(str1!="0") + { + str2.Format(" AND ((wo.status)=%s)",str1); + pdv->sqlcriteria+=str2; + pdv->status=atol(str1); + } + + } + else + pdv->status=0; + + //PREVIEW DESCripTION + pdv->preview = m_ckPreview.GetCheck() ? 1 : 0; + if(pdv->preview==1) NoChoices=false; + + + + //FIXUP THE QUERY STRING + if(pdv->sqlcriteria.IsEmpty()) + { + pdv->sqlcriteria.Empty(); + + } + else + { + + if(pdv->sqlcriteria.Left(4)==" AND") + { + str1=pdv->sqlcriteria.Right(pdv->sqlcriteria.GetLength()-4); + pdv->sqlcriteria=str1; + } + + pdv->sqlcriteria=" WHERE(" + pdv->sqlcriteria + ")"; + } + //REPORT NAME + pdv->virtualreport=m_cbReports.GetCurrentRowID(); + + if(NoChoices) //nothing was chosen to display + { + AfxMessageBox("You must select at least one item for display.\r\nI'm going to select workorder # for you now to avoid problems."); + m_ckWO.SetCheck(TRUE); + pdv->workorder=1;//force a workorder to avoid crash + } + +} + + + + + + + + + + + + + +//***************************************** +void CDispatchFieldsDlg::FillLists() +{ + CString strData; + CString strIndex; + long lData; + bool bHO; + m_cbTech.Clear(); + + m_cbTech.AddRow(" ","-1"); + m_cbTech.AddRow("","0"); + rs->Query("SELECT users.id, [last] & \", \" & [first] AS fullname FROM users WHERE (((users.tech)=True)) ORDER BY users.last;"); + if(!rs->IsEmpty()) + { + rs->MoveFirst(); + rs->FetchField("fullname",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTech.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("fullname",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTech.AddRow(strData,strIndex); + } + + } + + + + + //========================================== + //CLIENTS LIST + + m_cbClient.Clear(); + m_cbClient.AddRow("","0"); + + rs->Query("SELECT clients.id, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS name, isheadoffice " + "FROM clients ORDER BY IIf(IsNull([company]),[last] & \", \" & [first],[company]);"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("isheadoffice",&bHO); + rs->FetchField("name",&strData); + if(bHO) + strData=strData+" (head office)"; + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbClient.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } + + //============================================ + + //========================================== + //ZONES LIST + + m_cbZone.Clear(); + m_cbZone.AddRow("","0"); + + rs->Query("SELECT zones.name, zones.id FROM zones ORDER BY zones.name;"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbZone.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } + + //========================================== + //CATEGORIES LIST + + m_cbCategories.Clear(); + m_cbCategories.AddRow("","0"); + + rs->Query("SELECT wotypes.category, wotypes.id FROM wotypes ORDER BY wotypes.category;"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("category",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbCategories.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } +//m_cbCategories.Select("0"); + + //========================================== + //PROJECTS LIST + + m_cbProjects.Clear(); + m_cbProjects.AddRow("","0"); + + rs->Query("SELECT projects.name, projects.id FROM projects ORDER BY projects.name;"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbProjects.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } +//m_cbProjects.Select("0"); + //============================================ + + //REPORTS LIST + m_cbReports.Clear(); + + + rs->Query("SELECT rptsmaster.virtualname, rptsmaster.filename FROM rptsmaster " + "WHERE (((rptsmaster.recordset)=\"wostat\")) " + "ORDER BY rptsmaster.virtualname;"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("virtualname",&strIndex); + rs->FetchField("filename",&strData); + strData=strIndex + " (" + strData + ")"; + m_cbReports.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } + m_cbReports.Select("0");//should force first item selection + + //========================================== + //STATUS LIST + + m_cbStatus.Clear(); + m_cbStatus.AddRow(" < Any status >","0"); + + rs->Query("SELECT probstat.notes, probstat.id FROM probstat ORDER BY probstat.notes;"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("notes",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbStatus.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } + + m_cbStatus.Select("0"); + +} + + +//************************************************** +void CDispatchFieldsDlg::OnButton1() +{ + BuildSQL(); + m_edSQL.SetWindowText(pdv->sqlcriteria); + +} + + +void CDispatchFieldsDlg::RefreshDisplay() +{ + + m_ckClosedOpen_BOTH.SetCheck(FALSE); + m_ckClosedOpen_CLOSED.SetCheck(FALSE); + m_ckClosedOpen_OPEN.SetCheck(FALSE); + switch( pdv->closed) + {//0 = not displayed 1=both,2="closed",3="open" + + case 1: + m_ckClosedOpen_BOTH.SetCheck(TRUE); + break; + case 2: + m_ckClosedOpen_CLOSED.SetCheck(TRUE); + break; + case 3: + m_ckClosedOpen_OPEN.SetCheck(TRUE); + break; + } + + + + + + m_ckOnsite_BOTH.SetCheck(FALSE); + m_ckOnsite_ONSITE.SetCheck(FALSE); + m_ckOnsite_INHOUSE.SetCheck(FALSE); + switch(pdv->onsite) + { //0 = not displayed otherwise 1="both", 2= "onsite", 3="inhouse" + + case 1: + m_ckOnsite_BOTH.SetCheck(TRUE); + break; + case 2: + m_ckOnsite_ONSITE.SetCheck(TRUE); + break; + case 3: + m_ckOnsite_INHOUSE.SetCheck(TRUE); + break; + } + + + + + m_ckSchedDate_ANY.SetCheck(FALSE); + m_ckSchedDate_TODAY.SetCheck(FALSE); + m_ckSchedDate_THISWEEK.SetCheck(FALSE); + m_ckSchedDate_THISMONTH.SetCheck(FALSE); + m_ckSchedDate_BETWEEN.SetCheck(FALSE); + switch( pdv->schedstart) + {//0 = not displayed otherwise 1=any,2=today,3=week,4=month,5=between + case 1: + m_ckSchedDate_ANY.SetCheck(TRUE); + break; + case 2: + m_ckSchedDate_TODAY.SetCheck(TRUE); + break; + case 3: + m_ckSchedDate_THISWEEK.SetCheck(TRUE); + break; + case 4: + m_ckSchedDate_THISMONTH.SetCheck(TRUE); + break; + case 5 ://between + m_ckSchedDate_BETWEEN.SetCheck(TRUE); + break; + } + + + m_ckLastActivity.SetCheck(FALSE); + if( pdv->lastactivity==-1) + m_ckLastActivity.SetCheck(TRUE); + +} + + + + + + +//*************************************************************** + +void CDispatchFieldsDlg::OnCkclosedopenBoth() +{ + m_ckClosedOpen_CLOSED.SetCheck(FALSE); + //m_ckClosedOpen_BOTH.SetCheck(FALSE); + m_ckClosedOpen_OPEN.SetCheck(FALSE); + BuildSQL(); + +} + +void CDispatchFieldsDlg::OnCkclosedopenOpenonly() +{ + m_ckClosedOpen_CLOSED.SetCheck(FALSE); + m_ckClosedOpen_BOTH.SetCheck(FALSE); + //m_ckClosedOpen_OPEN.SetCheck(FALSE); + BuildSQL(); + +} + +void CDispatchFieldsDlg::OnCkclosedopenClosedonly() +{ + //m_ckClosedOpen_CLOSED.SetCheck(FALSE); + m_ckClosedOpen_BOTH.SetCheck(FALSE); + m_ckClosedOpen_OPEN.SetCheck(FALSE); + BuildSQL(); + +} + +//*********************************************************** + +void CDispatchFieldsDlg::OnCkonsiteBoth() +{ + //m_ckOnsite_BOTH.SetCheck(FALSE); + m_ckOnsite_INHOUSE.SetCheck(FALSE); + m_ckOnsite_ONSITE.SetCheck(FALSE); + BuildSQL(); + + +} + +void CDispatchFieldsDlg::OnCkonsiteInhouseonly() +{ + m_ckOnsite_BOTH.SetCheck(FALSE); + //m_ckOnsite_INHOUSE.SetCheck(FALSE); + m_ckOnsite_ONSITE.SetCheck(FALSE); + BuildSQL(); +} + +void CDispatchFieldsDlg::OnCkonsiteOnsiteonly() +{ + m_ckOnsite_BOTH.SetCheck(FALSE); + m_ckOnsite_INHOUSE.SetCheck(FALSE); + //m_ckOnsite_ONSITE.SetCheck(FALSE); + BuildSQL(); +} + + +//******************************************************** +void CDispatchFieldsDlg::OnCkscheddateAny() +{ + m_ckSchedDate_TODAY.SetCheck(FALSE); + m_ckSchedDate_THISWEEK.SetCheck(FALSE); + m_ckSchedDate_THISMONTH.SetCheck(FALSE); + m_ckSchedDate_TOMORROW.SetCheck(FALSE); + m_ckSchedDate_BETWEEN.SetCheck(FALSE); + m_dtSchedDate_START.EnableWindow(FALSE); + m_dtSchedDate_END.EnableWindow(FALSE); + BuildSQL(); + +} + +void CDispatchFieldsDlg::OnCkscheddateBetween() +{ + m_ckSchedDate_TODAY.SetCheck(FALSE); + m_ckSchedDate_THISWEEK.SetCheck(FALSE); + m_ckSchedDate_THISMONTH.SetCheck(FALSE); + m_ckSchedDate_ANY.SetCheck(FALSE); + m_ckSchedDate_TOMORROW.SetCheck(FALSE); + m_dtSchedDate_START.EnableWindow(TRUE); + m_dtSchedDate_END.EnableWindow(TRUE); + m_dtSchedDate_START.SetTime(COleDateTime::GetCurrentTime()); + m_dtSchedDate_END.SetTime(COleDateTime::GetCurrentTime()); + +} + +void CDispatchFieldsDlg::OnCkscheddateThismonth() +{ + m_ckSchedDate_TODAY.SetCheck(FALSE); + m_ckSchedDate_THISWEEK.SetCheck(FALSE); + m_ckSchedDate_TOMORROW.SetCheck(FALSE); + m_ckSchedDate_ANY.SetCheck(FALSE); + m_ckSchedDate_BETWEEN.SetCheck(FALSE); + m_dtSchedDate_START.EnableWindow(FALSE); + m_dtSchedDate_END.EnableWindow(FALSE); + BuildSQL(); +} + +void CDispatchFieldsDlg::OnCkscheddateThisweek() +{ + m_ckSchedDate_TODAY.SetCheck(FALSE); + m_ckSchedDate_TOMORROW.SetCheck(FALSE); + m_ckSchedDate_THISMONTH.SetCheck(FALSE); + m_ckSchedDate_ANY.SetCheck(FALSE); + m_ckSchedDate_BETWEEN.SetCheck(FALSE); + m_dtSchedDate_START.EnableWindow(FALSE); + m_dtSchedDate_END.EnableWindow(FALSE); + BuildSQL(); +} + +void CDispatchFieldsDlg::OnCkscheddateToday() +{ + m_ckSchedDate_TOMORROW.SetCheck(FALSE); + m_ckSchedDate_THISWEEK.SetCheck(FALSE); + m_ckSchedDate_THISMONTH.SetCheck(FALSE); + m_ckSchedDate_ANY.SetCheck(FALSE); + m_ckSchedDate_BETWEEN.SetCheck(FALSE); + m_dtSchedDate_START.EnableWindow(FALSE); + m_dtSchedDate_END.EnableWindow(FALSE); + BuildSQL(); +} + +void CDispatchFieldsDlg::OnCkscheddateTomorrow() +{ + + m_ckSchedDate_TODAY.SetCheck(FALSE); + m_ckSchedDate_THISWEEK.SetCheck(FALSE); + m_ckSchedDate_THISMONTH.SetCheck(FALSE); + m_ckSchedDate_ANY.SetCheck(FALSE); + m_ckSchedDate_BETWEEN.SetCheck(FALSE); + m_dtSchedDate_START.EnableWindow(FALSE); + m_dtSchedDate_END.EnableWindow(FALSE); + BuildSQL(); + +} + +//************************************************************** + +void CDispatchFieldsDlg::OnCklastactivityAny() +{ + if(m_ckLastActivity_ANY.GetCheck()==TRUE) + { + m_edLastActivity_DAYS.SetWindowText(""); + m_edLastActivity_DAYS.EnableWindow(FALSE); + } + else + { + m_edLastActivity_DAYS.SetWindowText("7"); + m_edLastActivity_DAYS.EnableWindow(TRUE); + } + +} + + +void CDispatchFieldsDlg::OnCloseupCbentry() +{ + int x=0; + x=m_cbEntry.GetCurSel(); + m_edCreatedDays.ShowWindow(FALSE); + m_lblCreatedDays.ShowWindow(FALSE); + m_dtEntryDate.ShowWindow(FALSE); + if(x==1 || x==2) + { + m_dtEntryDate.ShowWindow(TRUE); + } + + if(12==x || 13==x) + { + m_edCreatedDays.ShowWindow(TRUE); + m_lblCreatedDays.ShowWindow(TRUE); + + } +} + +void CDispatchFieldsDlg::OnCkinvoice() +{ + // TODO: Add your control notification handler code here + +} + +void CDispatchFieldsDlg::OnCkdate() +{ + // TODO: Add your control notification handler code here + +} + +void CDispatchFieldsDlg::OnDatetimechangeDtcheddateBetweenStart(NMHDR* pNMHDR, LRESULT* pResult) +{ + + BuildSQL(); + *pResult = 0; +} + +void CDispatchFieldsDlg::OnDatetimechangeDtcheddateBetweenEnd(NMHDR* pNMHDR, LRESULT* pResult) +{ + + BuildSQL(); + *pResult = 0; +} + +void CDispatchFieldsDlg::OnCkourref() +{ + // TODO: Add your control notification handler code here + +} + +void CDispatchFieldsDlg::OnCkstatus() +{ + // TODO: Add your control notification handler code here + +} + + +void CDispatchFieldsDlg::OnCloseupCbcategories() +{ + // TODO: Add your control notification handler code here + +} + +void CDispatchFieldsDlg::OnCkcategory() +{ + // TODO: Add your control notification handler code here + +} + +void CDispatchFieldsDlg::OnCkproject() +{ + // TODO: Add your control notification handler code here + +} + +void CDispatchFieldsDlg::OnCloseupCbprojects() +{ + // TODO: Add your control notification handler code here + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.h new file mode 100644 index 0000000..e89e221 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchFieldsDlg.h @@ -0,0 +1,154 @@ +#if !defined(AFX_DISPATCHFIELDSDLG_H__BDBF57C1_37BC_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_DISPATCHFIELDSDLG_H__BDBF57C1_37BC_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DispatchFieldsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDispatchFieldsDlg dialog +#include "label.h" +#include "gzcombo.h" +#include "gzrset.h" +#include "DispatchView.H" +#include "afxwin.h" +class CDispatchFieldsDlg : public CDialog +{ +// Construction +public: + ~CDispatchFieldsDlg(); + void RefreshDisplay(); + void FillLists(); + + void BuildSQL(); + void SetReturnVariable(CDispatchView * dvReturn); + + CDispatchFieldsDlg(CWnd* pParent = NULL); // standard constructor + CDispatchView* pdv; + CDispatchView* passeddv; + CSpApp* m_pApp; + GZRset* rs; + +// Dialog Data + //{{AFX_DATA(CDispatchFieldsDlg) + enum { IDD = IDD_DISPATCHFIELDS }; + CButton m_ckProject; + CgzCombo m_cbProjects; + CgzCombo m_cbCategories; + CButton m_ckCategory; + CButton m_ckSchedDate_TOMORROW; + CButton m_ckCustRef; + CButton m_ckStatus; + CButton m_ckOurRef; + CButton m_ckDate; + CButton m_ckInvoice; + CDateTimeCtrl m_dtEntryDate; + CComboBox m_cbEntry; + CLabel m_lbl16; + CgzCombo m_cbReports; + CLabel m_lbl15; + CButton m_ckPreview; + CButton m_ckSchedDate_BETWEEN; + CEdit m_edSQL; + CEdit m_edLastActivity_DAYS; + CDateTimeCtrl m_dtSchedDate_START; + CDateTimeCtrl m_dtSchedDate_END; + CButton m_ckSchedDate_TODAY; + CButton m_ckSchedDate_THISWEEK; + CButton m_ckSchedDate_THISMONTH; + CButton m_ckSchedDate_ANY; + CButton m_ckOnsite_ONSITE; + CButton m_ckOnsite_INHOUSE; + CButton m_ckOnsite_BOTH; + CButton m_ckLastActivity_ANY; + CButton m_ckClosedOpen_OPEN; + CButton m_ckClosedOpen_CLOSED; + CButton m_ckClosedOpen_BOTH; + CgzCombo m_cbZone; + CgzCombo m_cbTech; + CgzCombo m_cbClient; + CLabel m_lbl14; + CLabel m_lbl9; + CLabel m_lbl8; + CLabel m_lbl7; + CLabel m_lbl6; + CLabel m_lbl5; + CLabel m_lbl4; + CLabel m_lbl3; + CLabel m_lbl2; + CLabel m_lbl13; + CLabel m_lbl12; + CLabel m_lbl11; + CLabel m_lbl10; + CLabel m_lbl1; + CButton m_ckZone; + CButton m_ckWO; + CButton m_ckSchedTech; + CButton m_ckSchedEndDate; + CButton m_ckSchedDate; + CButton m_ckPostal; + CButton m_ckOnsite; + CButton m_ckLastActivity; + CButton m_ckEntryDate; + CButton m_ckClosedDate; + CButton m_ckClosed; + CButton m_ckClient; + CButton m_ckCity; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDispatchFieldsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDispatchFieldsDlg) + afx_msg void OnBtndone(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnBtncancel(); + afx_msg void OnButton1(); + afx_msg void OnCkclosedopenBoth(); + afx_msg void OnCkclosedopenOpenonly(); + afx_msg void OnCkclosedopenClosedonly(); + afx_msg void OnCkonsiteBoth(); + afx_msg void OnCkonsiteInhouseonly(); + afx_msg void OnCkonsiteOnsiteonly(); + afx_msg void OnCkscheddateAny(); + afx_msg void OnCkscheddateBetween(); + afx_msg void OnCkscheddateThismonth(); + afx_msg void OnCkscheddateThisweek(); + afx_msg void OnCkscheddateToday(); + afx_msg void OnCklastactivityAny(); + afx_msg void OnCloseupCbentry(); + afx_msg void OnCkinvoice(); + afx_msg void OnCkdate(); + afx_msg void OnDatetimechangeDtcheddateBetweenStart(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDatetimechangeDtcheddateBetweenEnd(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnCkourref(); + afx_msg void OnCkstatus(); + afx_msg void OnCkscheddateTomorrow(); + afx_msg void OnCloseupCbcategories(); + afx_msg void OnCkcategory(); + afx_msg void OnCkproject(); + afx_msg void OnCloseupCbprojects(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CgzCombo m_cbStatus; + CStatic m_lblCreatedDays; + CEdit m_edCreatedDays; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DISPATCHFIELDSDLG_H__BDBF57C1_37BC_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.cpp new file mode 100644 index 0000000..f158fd4 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.cpp @@ -0,0 +1,96 @@ +// DispatchView.cpp: implementation of the CDispatchView class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +//#include "sp.h" +#include "DispatchView.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CDispatchView::CDispatchView() +{ + IsModified=false; + +} + +CDispatchView::~CDispatchView() +{ + +} + +bool CDispatchView::operator==(CDispatchView other) +{ + + if(other.city!=city) + return false; + if(other.client!= client) + return false; + if(other.virtualreport!= virtualreport) + return false; + if(other.zone!= zone) + return false; + if(other.postal!= postal) + return false; + if(other.workorder!= workorder) + return false; + if(other.closed!= closed) + return false; + if(other.closeddate!= closeddate) + return false; + if(other.onsite!= onsite) + return false; + if(other.schedstart!= schedstart) + return false; + if(other.scheddatestart!= scheddatestart) + return false; + if(other.scheddateend!= scheddateend) + return false; + if(other.schedenddate!= schedenddate) + return false; + if(other.schedtech!= schedtech) + return false; + if(other.wocreateddate!= wocreateddate) + return false; + if(other.lastactivity!= lastactivity) + return false; + if(other.preview != preview) + return false; + if(other.woentrydate != woentrydate) + return false; + if(other.woentrydatetype != woentrydatetype) + return false; + if(other.invoice != invoice) + return false; + if(other.date != date) + return false; + if(other.ourrefnumber != ourrefnumber) + return false; + if(other.status != status) + return false; + if(other.custrefnumber != custrefnumber) + return false; + + if(other.category != category) + return false; + + if(other.project != project) + return false; + + if(other.lCreatedDays != lCreatedDays) + return false; + + + + return true; + + +} \ No newline at end of file diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.h new file mode 100644 index 0000000..cdf4f71 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DispatchView.h @@ -0,0 +1,113 @@ +// DispatchView.h: interface for the CDispatchView class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_DISPATCHVIEW_H__8543FA81_389E_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_DISPATCHVIEW_H__8543FA81_389E_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +//for check/combo combinations +//-1 means show with no specific one +//0 means don't show at all +//specific value means show and query for only certain type. +class CDispatchView +{ +public: + long id; + CString viewname; + CString viewprofile; + CString virtualreport; + long client; + long zone; + long postal; + long city; + long workorder; + long closed; + //0 = not displayed 1="closed",2="open" ,3= "both" + long closeddate;//0=not displayed else display + long onsite; + //0 = not displayed otherwise 1="both", 2= "onsite", 3="inhouse" + long schedstart; + //0 = not displayed otherwise 1=any,2=today,3=week,4=month,5=between + COleDateTime scheddatestart; + COleDateTime scheddateend; + + //type field means following: + //< anytime >;After...;Before...;in the last week; + //in the last 2 weeks;in the last 45 days;this month;in the last 3 months; + //in the last 6 months;this year;in the last 2 years;in the last 5 years; + //Less than...;More than...;;; + //0=Anytime + //1=After woentrydate + //2=Before woentrydate + //3=within 1 week + //4=within 2 weeks + //5=last 45 days + //6=within 1 month + //7=within 3 months + //8=within 6 months + //9=within 1 year + //10=within 2 years + //11=within 5 years + //12=Less than X days + //13=More than X days + // + long woentrydatetype; + + COleDateTime woentrydate;// + long schedenddate; + //0=not displayed + + long schedtech; + long wocreateddate; + long lastactivity; + //0 = not displayed otherwise -1= "any" or positive x meaning x days ago + CString sqlcriteria; + CString sqlorderby;//order by string - duh! + bool IsModified; + + //show wo description + long preview; + + //show invoice number + long invoice; + + //show combined date in one column + //sched date for scheduled, open workorders + //closed date for scheduled closed workorders + //entry date for quick workorders + long date; + + //Show workorder overall status field + long status; + + //Show our reference number field + long ourrefnumber; + + //Show cust reference number field + long custrefnumber; + + //Category + long category; + + //Project + long project; + + //created less than greater than days + long lCreatedDays; + + + + + + bool operator==(CDispatchView other); + CDispatchView(); + virtual ~CDispatchView(); + +}; + +#endif // !defined(AFX_DISPATCHVIEW_H__8543FA81_389E_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.cpp new file mode 100644 index 0000000..d8aca3c --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.cpp @@ -0,0 +1,263 @@ +// DlgDispStatPopup.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "DlgDispStatPopup.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgDispStatPopup dialog + + +CDlgDispStatPopup::CDlgDispStatPopup(CWnd* pParent /*=NULL*/) + : CDialog(CDlgDispStatPopup::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgDispStatPopup) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + //Initialize recordset pointer + rs=m_pApp->rsPool->GetRS("CDlgDispStatPopup"); + +} + + +void CDlgDispStatPopup::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgDispStatPopup) + DDX_Control(pDX, IDC_LBLWOINFO, m_lblWOInfo); + DDX_Control(pDX, IDC_DTSTARTTIME, m_dtStartTime); + DDX_Control(pDX, IDC_DTENDTIME, m_dtEndTime); + DDX_Control(pDX, IDC_DTSCHEDENDDATE, m_dtEndDate); + DDX_Control(pDX, IDC_DTSCHEDSTARTDATE, m_dtStartDate); + DDX_Control(pDX, IDC_LBLTECHS, m_lblTechNumber); + DDX_Control(pDX, IDC_CBTECHLIST, m_cbTechList); + DDX_Control(pDX, IDC_CBSTATUSITEMLIST, m_cbStatus); + DDX_Control(pDX, IDC_LBLSTATUSLIST, m_lblStatus); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDlgDispStatPopup, CDialog) + //{{AFX_MSG_MAP(CDlgDispStatPopup) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_BN_CLICKED(IDC_BTN_CANCEL, OnBtnCancel) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTSCHEDSTARTDATE, OnDatetimechangeDtschedstartdate) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgDispStatPopup message handlers + +void CDlgDispStatPopup::OnOK() +{} + +CDlgDispStatPopup::~CDlgDispStatPopup() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + +} + +BOOL CDlgDispStatPopup::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + CString q; + q.Format("Assigned tech number %s is:",*m_pstrSelectedTechNumber); + m_lblTechNumber.SetWindowText(q); + FillTechList(); + FillList(); + m_dtEndDate.SetTime(*m_pdtEnd); + m_dtStartDate.SetTime(*m_pdtStart); + + m_dtEndTime.SetTime(*m_pdtEnd); + m_dtStartTime.SetTime(*m_pdtStart); + + //added for MASS benefit + m_lblWOInfo.SetWindowText(m_strWOInfo); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CDlgDispStatPopup::FillList() +{ + CString q,strData,strIndex; + long lData; +//FILL STATUS LIST + m_cbStatus.Clear(); + m_cbStatus.AddRow(" ","0"); + rs->QueryReadOnly("SELECT probstat.id, probstat.notes FROM probstat ORDER BY probstat.id;"); + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("notes",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbStatus.AddRow(strData,strIndex); + }while(rs->MoveForward()); + if(m_pstrSelectedStatus->IsEmpty()) + m_cbStatus.SetCurSel(0); + else + m_cbStatus.Select(*m_pstrSelectedStatus); + + } + +} + + + +void CDlgDispStatPopup::OnBtndone() +{ + + CString q; + COleDateTime dtDate,dtTime; + *m_pstrSelectedStatus=m_cbStatus.GetCurrentRowID(); + *m_pstrSelectedTech=m_cbTechList.GetCurrentRowID(); + + //fetch colours if it's a valid status item + if(*m_pstrSelectedStatus!="0") + { + q.Format("SELECT probstat.red, probstat.green, probstat.blue " + "FROM probstat WHERE (((probstat.id)=%s));",*m_pstrSelectedStatus); + rs->QueryReadOnly(q); + rs->FetchField("red",m_plRed); + rs->FetchField("green",m_plGreen); + rs->FetchField("blue",m_plBlue); + } + else + { + *m_plRed=0; + *m_plGreen=0; + *m_plBlue=0; + + + } + + + + //store date and times + m_dtStartDate.GetTime(dtDate); + m_dtStartTime.GetTime(dtTime); + m_pdtStart->SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(), + dtTime.GetHour(),dtTime.GetMinute(),0); + + m_dtEndDate.GetTime(dtDate); + m_dtEndTime.GetTime(dtTime); + m_pdtEnd->SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(), + dtTime.GetHour(),dtTime.GetMinute(),0); + + + + CDialog::OnOK(); + +} + +void CDlgDispStatPopup::FillTechList() +{ + CString strData; + CString strIndex; + CString q; + long lData; + m_cbTechList.Clear(); + m_cbTechList.AddRow(" ","0"); + //look for selected tech and see if in inactive list: + if(!m_pstrSelectedTech->IsEmpty() && *m_pstrSelectedTech!="0") + { + q.Format("SELECT users.id, [last] & \", \" & [first] AS fullname " + "FROM users " + "WHERE (((users.id)=%s) AND ((users.active)=False));",*m_pstrSelectedTech); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) //it's an inactive tech put them in the list "manually" + { + rs->FetchField("fullname",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + q=" " + strData; + m_cbTechList.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); + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + rs->MoveFirst(); + rs->FetchField("fullname",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTechList.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("fullname",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTechList.AddRow(strData,strIndex); + } + + } + + //if(!m_pstrSelectedTech->IsEmpty()) + m_cbTechList.Select(*m_pstrSelectedTech); + //else + //{//attempt to select by current user id + // m_pstrSelectedTech->Format("%u",m_pApp->m_lusrID); + // m_cbTechList.Select(*m_pstrSelectedTech); +// } + + + +} + +void CDlgDispStatPopup::OnBtnCancel() +{ + CDialog::OnCancel(); +} + +void CDlgDispStatPopup::OnDatetimechangeDtschedstartdate(NMHDR* pNMHDR, LRESULT* pResult) +{ + // TODO: Add your control notification handler code here + COleDateTime dtData; + m_dtStartDate.GetTime(dtData); + m_dtEndDate.SetTime(dtData); + *pResult = 0; +} + +void CDlgDispStatPopup::Security() +{ + int x=m_pApp->Allowed(RWORKORDER,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + + m_cbStatus.EnableWindow(FALSE); + m_cbTechList.EnableWindow(FALSE); + m_dtEndDate.EnableWindow(FALSE); + m_dtEndTime.EnableWindow(FALSE); + m_dtStartDate.EnableWindow(FALSE); + m_dtStartTime.EnableWindow(FALSE); + + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.h new file mode 100644 index 0000000..e08009e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgDispStatPopup.h @@ -0,0 +1,81 @@ +#if !defined(AFX_DLGDISPSTATPOPUP_H__B6217656_2D59_48A7_9254_58300EFE0CF8__INCLUDED_) +#define AFX_DLGDISPSTATPOPUP_H__B6217656_2D59_48A7_9254_58300EFE0CF8__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DlgDispStatPopup.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgDispStatPopup dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" + +class CDlgDispStatPopup : public CDialog +{ +// Construction +public: + CString m_strWOInfo; + COleDateTime* m_pdtStart; + COleDateTime* m_pdtEnd; + void FillTechList(); + CDlgDispStatPopup(CWnd* pParent = NULL); // standard constructor + CSpApp* m_pApp; + GZRset* rs; + CString* m_pstrSelectedStatus; + CString* m_pstrSelectedTech; + //added 07/27/01 to accomodate multi-techs + CString* m_pstrSelectedTechNumber; + + long* m_plRed; + long* m_plGreen; + long* m_plBlue; + + + void FillList(); + ~CDlgDispStatPopup(); +// Dialog Data + //{{AFX_DATA(CDlgDispStatPopup) + enum { IDD = IDD_SCHED_STAT_POPUP }; + CStatic m_lblWOInfo; + CDateTimeCtrl m_dtStartTime; + CDateTimeCtrl m_dtEndTime; + CDateTimeCtrl m_dtEndDate; + CDateTimeCtrl m_dtStartDate; + CStatic m_lblTechNumber; + CgzCombo m_cbTechList; + CgzCombo m_cbStatus; + CLabel m_lblStatus; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgDispStatPopup) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgDispStatPopup) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnBtndone(); + afx_msg void OnBtnCancel(); + afx_msg void OnDatetimechangeDtschedstartdate(NMHDR* pNMHDR, LRESULT* pResult); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + void Security(); + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGDISPSTATPOPUP_H__B6217656_2D59_48A7_9254_58300EFE0CF8__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.cpp new file mode 100644 index 0000000..0694c1d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.cpp @@ -0,0 +1,503 @@ +// DlgSchedMarkers.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "DlgSchedMarkers.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgSchedMarkers dialog + + +CDlgSchedMarkers::CDlgSchedMarkers(CWnd* pParent /*=NULL*/) +: CDialog(CDlgSchedMarkers::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgSchedMarkers) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + //Initialize recordset pointer + rs=m_pApp->rsPool->GetRS("CDlgSchedMarkers"); +} + +CDlgSchedMarkers::~CDlgSchedMarkers() +{ + //delete rs; + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CDlgSchedMarkers::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgSchedMarkers) + DDX_Control(pDX, IDC_BTNCOLOR, m_btnColor); + DDX_Control(pDX, IDC_BTNREFRESH, m_btnRefresh); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + DDX_Control(pDX, IDC_LSTMARKERS, m_lsMarkers); + DDX_Control(pDX, IDC_LBLSAMPLE, m_lblSample); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_DTTSTART, m_dtStartTime); + DDX_Control(pDX, IDC_DTTEND, m_dtEndTime); + DDX_Control(pDX, IDC_DTSTART, m_dtStartDate); + DDX_Control(pDX, IDC_DTEND, m_dtEndDate); + DDX_Control(pDX, IDC_CBAPPLIESTO, m_cbAppliesTo); + DDX_Control(pDX, IDC_BTNDEL, m_btnDelete); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDlgSchedMarkers, CDialog) +//{{AFX_MSG_MAP(CDlgSchedMarkers) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_LBN_SELCHANGE(IDC_LSTMARKERS, OnSelchangeLstmarkers) +ON_BN_CLICKED(IDC_BTNCOLOR, OnBtncolor) + ON_EN_KILLFOCUS(IDC_EDNOTES, OnKillfocusEdnotes) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTSTART, OnDatetimechangeDtstart) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTEND, OnDatetimechangeDtend) + ON_CBN_CLOSEUP(IDC_CBAPPLIESTO, OnCloseupCbappliesto) + ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) + ON_NOTIFY(NM_KILLFOCUS, IDC_DTTSTART, OnKillfocusDttstart) + ON_NOTIFY(NM_KILLFOCUS, IDC_DTTEND, OnKillfocusDttend) + ON_BN_CLICKED(IDC_BTNREFRESH, OnBtnrefresh) + ON_BN_CLICKED(IDC_BTNDEL, OnBtndel) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgSchedMarkers message handlers + + + +BOOL CDlgSchedMarkers::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + m_lblSample.SetFontBold(TRUE); + m_lblSample.SetFontSize(14); + m_lblSample.SetBkColor(RGB(128,128,128)); + m_lGreen=m_lBlue=m_lRed=128; + m_lblSample.SetTextColor(RGB(0,0,0)); + m_edNotes.SetLimitText(15); + FillAppliesToList(); + FillMarkerList(); + m_bAddMode=false; + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + + +void CDlgSchedMarkers::FillAppliesToList() +{ + CString strData, strIndex; + long lData; + m_cbAppliesTo.Clear(); + strData="< Office >"; + strIndex="0"; + m_cbAppliesTo.AddRow(strData,strIndex); + + + rs->QueryReadOnly("SELECT users.id, [last] & \", \" & [first] AS name " + "FROM users WHERE (((users.id)<>1) AND ((users.tech)=True) AND ((users.active)=True)) " + "ORDER BY [last] & \", \" & [first];"); + + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbAppliesTo.AddRow(strData,strIndex); + }while(rs->MoveForward()); + m_cbAppliesTo.Select("0"); + } + +} + +void CDlgSchedMarkers::OnBtndone() +{ + + CDialog::OnOK(); + +} + +void CDlgSchedMarkers::OnOK() +{} + + + +//Fill list of items +void CDlgSchedMarkers::FillMarkerList() +{ + long lData; + CString strIndex,strData,strNotes,strName; + COleDateTime dtStart,dtEnd; + m_lsMarkers.Clear(); + EnableFields(false); + rs->QueryReadOnly( + "SELECT schedmarkers.id, schedmarkers.link, schedmarkers.startdate, schedmarkers.notes, " + "users.first, users.last " + "FROM schedmarkers LEFT JOIN users ON schedmarkers.link = users.id " + "ORDER BY schedmarkers.startdate DESC;"); + + if(!rs->IsEmpty()) + { + EnableFields(true); + do{ + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + + rs->FetchField("startdate",&dtStart); + strNotes=dtStart.Format(); + + rs->FetchField("notes",&strData); + strNotes+="\t"+strData; + + rs->FetchField("link",&lData); + if(lData==0) + { + strName=""; + } + else + { + rs->FetchField("last",&strData); + strName=strData; + rs->FetchField("first",&strData); + strName+=", " + strData; + } + + strNotes+=" - "+strName; + + m_lsMarkers.AddRow(strNotes,strIndex); + }while(rs->MoveForward()); + + if(m_strSelectedItem.IsEmpty()) + { + m_lsMarkers.SetCurSel(0); + m_lsMarkers.RebuildIndex();//<--------FIXES PROBLEM + m_strSelectedItem=m_lsMarkers.GetSelectedItem(0);//<-------problem + } + else + m_lsMarkers.Select(m_strSelectedItem,true); + //OnSelchangeLstmarkers(); + FillFields(); + + } + +} + + + + +void CDlgSchedMarkers::OnSelchangeLstmarkers() +{ + + CString q,strID,strNotes,strAppliesTo; + COleDateTime dtStart,dtEnd; + + + m_lsMarkers.RebuildIndex();//<--------FIXES PROBLEM + m_strSelectedItem=m_lsMarkers.GetSelectedItem(0);//<-------problem +FillFields(); + + +} + +void CDlgSchedMarkers::OnBtncolor() +{ + CString q; + + CColorDialog dlg(RGB(255,0,0),CC_SOLIDCOLOR/*|CC_PREVENTFULLOPEN*/); + + if (dlg.DoModal() == IDOK) + { + COLORREF color = dlg.GetColor(); + + m_lRed=GetRValue(color); + m_lGreen=GetGValue(color); + m_lBlue=GetBValue(color); + + + m_lblSample.SetBkColor(RGB(m_lRed,m_lGreen,m_lBlue)); + m_lblSample.SetTextColor(RGB(0,0,0)); + } + SaveRecord(false); + +} + + +//save new record or update existing record +void CDlgSchedMarkers::SaveRecord(bool bNew) +{ + //only save or update a record if out of add mode + if(m_bAddMode) return; + CString q,strID,strNotes,strAppliesTo; + COleDateTime dtStart,dtEnd,dtTime,dtDate; + long lData; + + + /*m_lsMarkers.RebuildIndex();//<--------FIXES PROBLEM + strID=m_lsMarkers.GetSelectedItem(0);//<-------problem + */ + + //get start date/time + m_dtStartTime.GetTime(dtTime); + m_dtStartDate.GetTime(dtDate); + dtStart.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + + //get End date/time + m_dtEndTime.GetTime(dtTime); + m_dtEndDate.GetTime(dtDate); + dtEnd.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + + //Get notes + m_edNotes.GetWindowText(strNotes); + if(strNotes.IsEmpty()) strNotes="??"; + + //Get link + strAppliesTo=m_cbAppliesTo.GetCurrentRowID(); + + //BUGBUG: on change of date schedule reverts to gray color + + if(bNew) + { + + q.Format( + "INSERT INTO schedmarkers ( link, startdate, enddate, notes, red, green, blue ) " + "SELECT %s, #%s#, #%s#, '%s', %u, %u, %u;",strAppliesTo,dtStart.Format(_T("%m/%d/%Y %H:%M:%S")), + dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),strNotes,m_lRed,m_lGreen,m_lBlue); + rs->Ex(q,&lData); + m_strSelectedItem.Format("%u",lData); + + + } + else + { + ASSERT(!m_strSelectedItem.IsEmpty()); + strID=m_strSelectedItem; + q.Format( + "UPDATE schedmarkers SET schedmarkers.link = %s, schedmarkers.startdate = #%s#, " + "schedmarkers.enddate = #%s#, schedmarkers.notes = '%s', schedmarkers.red = %u, " + "schedmarkers.green = %u, schedmarkers.blue = %u " + "WHERE (((schedmarkers.id)=%s));",strAppliesTo,dtStart.Format(_T("%m/%d/%Y %H:%M:%S")), + dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),strNotes,m_lRed,m_lGreen,m_lBlue,strID); + +#ifdef _DEBUG + //m_pApp->ShowStuff(q); +#endif + rs->Ex(q); + + + } + + //force a delay to flush change before refilling list + rs->QueryReadOnly("SELECT * FROM defaults;"); + rs->Close(); + m_pApp->Delay(1); + + +} + + +void CDlgSchedMarkers::OnBtnadd() +{ + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + if(m_bAddMode) + { + m_bAddMode=false; + m_btnAdd.SetWindowText("Add"); + m_btnDone.ShowWindow(TRUE); + m_btnDelete.ShowWindow(TRUE); + m_btnRefresh.ShowWindow(TRUE); + SaveRecord(true); + m_strSelectedItem.Empty(); + FillMarkerList(); + } + else + { + EnableFields(true); + m_bAddMode=true; + m_btnAdd.SetWindowText("SAVE"); + m_btnDone.ShowWindow(FALSE); + m_btnRefresh.ShowWindow(FALSE); + m_lblSample.SetBkColor(RGB(128,128,128)); + m_lblSample.SetTextColor(RGB(0,0,0)); + m_lGreen=m_lBlue=m_lRed=128; + m_btnDelete.ShowWindow(FALSE); + m_dtEndDate.SetTime(dtData); + m_dtStartDate.SetTime(dtData); + dtData.SetTime(0,0,0); + m_dtStartTime.SetTime(dtData); + dtData.SetTime(23,59,59); + m_dtEndTime.SetTime(dtData); + m_edNotes.SetWindowText("??"); + + + } + +} + + + +void CDlgSchedMarkers::OnKillfocusDttstart(NMHDR* pNMHDR, LRESULT* pResult) +{ + SaveRecord(false); + + *pResult = 0; +} + +void CDlgSchedMarkers::OnKillfocusDttend(NMHDR* pNMHDR, LRESULT* pResult) +{ +SaveRecord(false); + *pResult = 0; +} + +void CDlgSchedMarkers::OnKillfocusEdnotes() +{ +SaveRecord(false); +} + + +void CDlgSchedMarkers::OnDatetimechangeDtstart(NMHDR* pNMHDR, LRESULT* pResult) +{ + COleDateTime dtData; + if(m_bAddMode)//change stop date to start date when in add mode + { + m_dtStartDate.GetTime(dtData); + m_dtEndDate.SetTime(dtData); + + } +SaveRecord(false); + *pResult = 0; +} + +void CDlgSchedMarkers::OnDatetimechangeDtend(NMHDR* pNMHDR, LRESULT* pResult) +{ +SaveRecord(false); + *pResult = 0; +} + +void CDlgSchedMarkers::OnCloseupCbappliesto() +{ + SaveRecord(false); + +} + + +//refresh list +void CDlgSchedMarkers::OnBtnrefresh() +{ +FillMarkerList(); +} + + + +void CDlgSchedMarkers::FillFields() +{ + CString q,strNotes,strAppliesTo; + COleDateTime dtStart,dtEnd; + long lData; + + ASSERT(!m_strSelectedItem.IsEmpty()); + q.Format("SELECT schedmarkers.* " + "FROM schedmarkers " + "WHERE (((schedmarkers.id)=%s));",m_strSelectedItem); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + rs->FetchField("startdate",&dtStart); + rs->FetchField("enddate",&dtEnd); + rs->FetchField("notes",&strNotes); + rs->FetchField("red",&m_lRed); + rs->FetchField("green",&m_lGreen); + rs->FetchField("blue",&m_lBlue); + rs->FetchField("link",&lData); + m_dtStartDate.SetTime(dtStart); + m_dtStartTime.SetTime(dtStart); + m_dtEndDate.SetTime(dtEnd); + m_dtEndTime.SetTime(dtEnd); + m_edNotes.SetWindowText(strNotes); + m_lblSample.SetBkColor(RGB(m_lRed,m_lGreen,m_lBlue)); + m_lblSample.SetTextColor(RGB(0,0,0)); + m_cbAppliesTo.Select(lData); + + } +} + +void CDlgSchedMarkers::OnBtndel() +{ + + if(AfxMessageBox("Delete selected item?\r\nAre you sure?",MB_YESNO)==IDNO) return; + CString q; + q.Format("DELETE schedmarkers.*, schedmarkers.id " + "FROM schedmarkers " + "WHERE (((schedmarkers.id)=%s));",m_strSelectedItem); + + rs->Ex(q); + rs->QueryReadOnly("SELECT * FROM defaults;"); + rs->Close(); + m_pApp->Delay(1); + + m_strSelectedItem.Empty(); + FillMarkerList(); + +} + + +//enable fields +void CDlgSchedMarkers::EnableFields(bool bEnable) +{ + if(m_bReadOnly) return; + + BOOL e= bEnable ? TRUE:FALSE; + m_btnDelete.EnableWindow(e); + m_dtEndDate.EnableWindow(e); + m_dtStartDate.EnableWindow(e); + m_cbAppliesTo.EnableWindow(e); + m_dtEndTime.EnableWindow(e); + m_dtStartTime.EnableWindow(e); + m_edNotes.EnableWindow(e); + m_btnColor.EnableWindow(e); + + + + +} + +void CDlgSchedMarkers::Security() +{ +m_bReadOnly=false; + int x=m_pApp->Allowed(RSCHEDMARKERS,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + + m_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_btnColor.EnableWindow(FALSE); + m_cbAppliesTo.EnableWindow(FALSE); + m_dtEndDate.EnableWindow(FALSE); + m_dtEndTime.EnableWindow(FALSE); + m_dtStartDate.EnableWindow(FALSE); + m_dtStartTime.EnableWindow(FALSE); + m_edNotes.EnableWindow(FALSE); + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.h new file mode 100644 index 0000000..ecdae2d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgSchedMarkers.h @@ -0,0 +1,91 @@ +#if !defined(AFX_DLGSCHEDMARKERS_H__EA79FE52_81E9_4C2A_8177_1E8070B8BAC6__INCLUDED_) +#define AFX_DLGSCHEDMARKERS_H__EA79FE52_81E9_4C2A_8177_1E8070B8BAC6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DlgSchedMarkers.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgSchedMarkers dialog +#include "gzrset.h" +#include "label.h" +#include "gzlistbox.h" +#include "gzcombo.h" + +class CDlgSchedMarkers : public CDialog +{ +// Construction +public: + void FillFields(); + CString m_strSelectedItem; + void SaveRecord(bool bNew); + long m_lRed; + long m_lGreen; + long m_lBlue; + void FillMarkerList(); + void FillAppliesToList(); + ~CDlgSchedMarkers(); + CDlgSchedMarkers(CWnd* pParent = NULL); // standard constructor + + CSpApp* m_pApp; + GZRset* rs; + bool m_bAddMode; + // Dialog Data + //{{AFX_DATA(CDlgSchedMarkers) + enum { IDD = IDD_SCHED_MARKERS }; + CButton m_btnColor; + CButton m_btnRefresh; + CButton m_btnDone; + CButton m_btnAdd; + CgzListBox m_lsMarkers; + CLabel m_lblSample; + CEdit m_edNotes; + CDateTimeCtrl m_dtStartTime; + CDateTimeCtrl m_dtEndTime; + CDateTimeCtrl m_dtStartDate; + CDateTimeCtrl m_dtEndDate; + CgzCombo m_cbAppliesTo; + CButton m_btnDelete; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgSchedMarkers) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgSchedMarkers) + virtual BOOL OnInitDialog(); + afx_msg void OnBtndone(); + virtual void OnOK(); + afx_msg void OnSelchangeLstmarkers(); + afx_msg void OnBtncolor(); + afx_msg void OnKillfocusEdnotes(); + afx_msg void OnDatetimechangeDtstart(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDatetimechangeDtend(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnCloseupCbappliesto(); + afx_msg void OnBtnadd(); + afx_msg void OnKillfocusDttstart(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKillfocusDttend(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnBtnrefresh(); + afx_msg void OnBtndel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + bool m_bReadOnly; + void Security(); + void EnableFields(bool bEnable); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGSCHEDMARKERS_H__EA79FE52_81E9_4C2A_8177_1E8070B8BAC6__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.cpp new file mode 100644 index 0000000..07dd886 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.cpp @@ -0,0 +1,51 @@ +// DlgStartUp.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "DlgStartUp.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgStartUp dialog + + +CDlgStartUp::CDlgStartUp(CWnd* pParent /*=NULL*/) + : CDialog(CDlgStartUp::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgStartUp) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CDlgStartUp::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgStartUp) + DDX_Control(pDX, IDC_PG, m_pc); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDlgStartUp, CDialog) + //{{AFX_MSG_MAP(CDlgStartUp) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgStartUp message handlers + +BOOL CDlgStartUp::OnInitDialog() +{ + CDialog::OnInitDialog(); + +m_pc.SetRange(0,18); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.h new file mode 100644 index 0000000..b583451 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgStartUp.h @@ -0,0 +1,46 @@ +#if !defined(AFX_DLGSTARTUP_H__85A91F44_E745_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_DLGSTARTUP_H__85A91F44_E745_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DlgStartUp.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgStartUp dialog + +class CDlgStartUp : public CDialog +{ +// Construction +public: + CDlgStartUp(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgStartUp) + enum { IDD = IDD_DLGSTARTUP }; + CProgressCtrl m_pc; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgStartUp) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgStartUp) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGSTARTUP_H__85A91F44_E745_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.cpp new file mode 100644 index 0000000..0f18d49 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.cpp @@ -0,0 +1,446 @@ +// DlgTasks.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "DlgTasks.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgTasks dialog + + +CDlgTasks::CDlgTasks(CWnd* pParent /*=NULL*/) + : CDialog(CDlgTasks::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgTasks) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bAddMode=false; + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Tasks dialog"); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + + rs=m_pApp->rsPool->GetRS("CDlgTasks"); + + m_pstrReturnValue=NULL; + m_strSelectedTask.Empty(); + +} + +CDlgTasks::~CDlgTasks() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CDlgTasks::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgTasks) + DDX_Control(pDX, IDC_LBLTASKS, m_lblTasks); + DDX_Control(pDX, IDC_CKACTIVE, m_ckActive); + DDX_Control(pDX, IDC_EDMINUTES, m_edMinutes); + DDX_Control(pDX, IDC_EDDETAILS, m_edDetails); + DDX_Control(pDX, IDC_EDDESCRIPTION, m_edDescription); + DDX_Control(pDX, IDC_CBTASKS, m_cbTasks); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNDELETE, m_btnDelete); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDlgTasks, CDialog) + //{{AFX_MSG_MAP(CDlgTasks) + ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) + ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_CBN_CLOSEUP(IDC_CBTASKS, OnCloseupCbtasks) + ON_EN_KILLFOCUS(IDC_EDDESCRIPTION, OnKillfocusEddescription) + ON_EN_KILLFOCUS(IDC_EDDETAILS, OnKillfocusEddetails) + ON_EN_KILLFOCUS(IDC_EDMINUTES, OnKillfocusEdminutes) + ON_BN_CLICKED(IDC_CKACTIVE, OnCkactive) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgTasks message handlers + +BOOL CDlgTasks::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + // TODO: Add extra initialization here + FillList(); + if(m_bReadOnly) + { + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_edDescription.SetReadOnly(TRUE); + m_edDetails.SetReadOnly(TRUE); + m_ckActive.EnableWindow(FALSE); + m_edMinutes.SetReadOnly(TRUE); + + + + } + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + +//***************************************** +void CDlgTasks::OnBtnadd() +{ + CString strData; + bool bData; + long lData; + + if(!m_bAddMode) + { //go add mode + DisableAll(false); + m_bAddMode=true; + m_btnDelete.SetWindowText("CANCEL"); + m_btnAdd.SetWindowText("SAVE"); + m_btnDone.ShowWindow(FALSE); + m_lblTasks.ShowWindow(FALSE); + m_cbTasks.ShowWindow(FALSE); + ClearFields(); + return; + + + } + else + {//SAVE Record + + + m_edDescription.GetWindowText(strData); + if(strData.IsEmpty()) + { + AfxMessageBox("You must enter a task description"); + return; + } + + + if(!rs->AddNewRecord()) + return; + + //SAVE DESCRIPTION + rs->UpdateField("description",&strData); + + //ACTIVE + bData=(m_ckActive.GetCheck() ? true : false); + rs->UpdateField("active",&bData); + + //DETAILS + m_edDetails.GetWindowText(strData); + rs->UpdateField("details",&strData); + + //Minutes + m_edMinutes.GetWindowText(strData); + lData=atol(strData); + rs->UpdateField("minutes",&lData); + + + //ATTEMPT TO SAVE + if(!rs->SaveRecord()) + return; + m_bAddMode=false; + m_lblTasks.ShowWindow(TRUE); + m_cbTasks.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_btnAdd.SetWindowText("Add"); + m_btnDone.ShowWindow(TRUE); + FillList(); + m_edDescription.GetWindowText(strData); + m_cbTasks.SelectString(-1,strData); + OnCloseupCbtasks(); + return; + } + + +} + + +//******************************************* +void CDlgTasks::OnBtndelete() +{ + CString q; + + if(m_bAddMode) + { + m_bAddMode=false; + m_lblTasks.ShowWindow(TRUE); + m_cbTasks.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_btnAdd.SetWindowText("Add"); + m_btnDone.ShowWindow(TRUE); + FillList(); + return; + + } + +//DELETE..... + + + + //check if unused and deletable + //IN PMPARTS??? + q.Format("SELECT probs.taskid FROM probs " + "WHERE (((probs.taskid)=%s));",m_strSelectedTask); + rs->Query(q); + if(!rs->IsEmpty()) + { + AfxMessageBox("DATA INTEGRITY PROTECTION:\r\n" + "This task appears in one or more workorders\r\n" + "and cannot be deleted at this time."); + return; + + + } + + + + if(AfxMessageBox("Permanently delete part?",MB_YESNO)==IDYES) + { + q.Format("DELETE tasks.*, tasks.id " + "FROM tasks WHERE (((tasks.id)=%s));",m_strSelectedTask); + rs->Ex(q); + m_strSelectedTask=""; + FillList(); + } + + + +} + + + + +//****************************************** +void CDlgTasks::OnBtndone() +{ + if(m_pstrReturnValue!=NULL) + *m_pstrReturnValue=m_strSelectedTask; + CDialog::OnOK(); +} + +void CDlgTasks::OnCloseupCbtasks() +{ + //FILL FIELDS + CString strData,q; + bool bData; + long lData; + + strData=m_cbTasks.GetCurrentRowID(); + + q.Format("SELECT tasks.* FROM tasks " + "WHERE (((tasks.id)=%s));",m_cbTasks.GetCurrentRowID()); + + rs->Query(q); + if(rs->IsEmpty()) + { + + return; + } + + + //DESCRIPTION + rs->FetchField("description",&strData); + m_edDescription.SetWindowText(strData); + + //DETAILS + rs->FetchField("details",&strData); + m_edDetails.SetWindowText(strData); + + + //ACTIVE + rs->FetchField("active",&bData); + m_ckActive.SetCheck(bData ? TRUE : FALSE); + + + //MINUTES + rs->FetchField("minutes",&lData); + strData.Format("%u",lData); + m_edMinutes.SetWindowText(strData); + + + m_strSelectedTask=m_cbTasks.GetCurrentRowID(); + + + +} + +void CDlgTasks::OnKillfocusEddescription() +{ + SaveField(&m_edDescription,"description",false); +} + +void CDlgTasks::OnKillfocusEddetails() +{ + SaveField(&m_edDetails,"details",true); + +} + +void CDlgTasks::OnKillfocusEdminutes() +{ + if(m_bAddMode) return; + long lData; + CString strData; + m_edMinutes.GetWindowText(strData); + lData=atol(strData); + rs->UpdateField("minutes",&lData); + + +} + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CDlgTasks::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + return true; +} + + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CDlgTasks::SaveField(CButton *ckControl,CString fldname) +{ + if(m_bAddMode) return true;//dont attempt to update + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + return true; +} + + +//********************************** +void CDlgTasks::FillList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbTasks.Clear(); + + rs->Query("SELECT tasks.* FROM tasks " + "ORDER BY tasks.description;"); + + + if(rs->IsEmpty()) + { + DisableAll(true); + return; + } + + + rs->MoveFirst(); + + do + { + rs->FetchField("description",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTasks.AddRow(strData,strIndex); + + }while(rs->MoveForward()); + + + //pretend user has selected so that other fields get filled in + if(m_strSelectedTask.IsEmpty()) //first time in + { + m_cbTasks.SetCurSel(0); + m_strSelectedTask=m_cbTasks.GetCurrentRowID(); + + } + else//something valid was selected before so stick with it + m_cbTasks.Select(m_strSelectedTask); + + + OnCloseupCbtasks(); + + +} + + + +//******************************* +void CDlgTasks::ClearFields() +{ + m_edDetails.SetWindowText(""); + m_edDescription.SetWindowText(""); + m_edMinutes.SetWindowText("0"); + m_ckActive.SetCheck(TRUE); + + +} + +void CDlgTasks::OnCkactive() +{ + SaveField(&m_ckActive,"active"); +} + +void CDlgTasks::DisableAll(bool disable) +{ + BOOL e = disable ? FALSE : TRUE; + m_btnDelete.EnableWindow(e); + m_cbTasks.EnableWindow(e); + m_ckActive.EnableWindow(e); + m_edDescription.EnableWindow(e); + m_edMinutes.EnableWindow(e); + m_edDetails.EnableWindow(e); + + +} + +void CDlgTasks::Security() +{ +int x=m_pApp->Allowed(RTASKS,true); +m_bReadOnly=false; +if(x==2)//read only +m_bReadOnly=true; +if(x==0) +{ + m_pApp->SecurityWarning(); + CDialog::OnCancel(); +} + + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.h new file mode 100644 index 0000000..4af7146 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/DlgTasks.h @@ -0,0 +1,77 @@ +#if !defined(AFX_DLGTASKS_H__69649FC1_2BEE_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_DLGTASKS_H__69649FC1_2BEE_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DlgTasks.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgTasks dialog +#include "gzcombo.h" +#include "gzrset.h" + +class CDlgTasks : public CDialog +{ +// Construction +public: + bool m_bReadOnly; + void Security(); + void DisableAll(bool disable); + void ClearFields(); + void FillList(); + CDlgTasks(CWnd* pParent = NULL); // standard constructor + CSpApp* m_pApp; + GZRset* rs; + GZRset* cbrs; + CString * m_pstrReturnValue; + ~CDlgTasks(); + bool m_bAddMode; + CString m_strSelectedTask; + bool SaveField(CEdit *edControl,CString fldname,bool AllowEmpty); + bool SaveField(CButton *ckControl,CString fldname); +// Dialog Data + //{{AFX_DATA(CDlgTasks) + enum { IDD = IDD_TASKS }; + CStatic m_lblTasks; + CButton m_ckActive; + CEdit m_edMinutes; + CEdit m_edDetails; + CEdit m_edDescription; + CgzCombo m_cbTasks; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgTasks) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgTasks) + virtual BOOL OnInitDialog(); + afx_msg void OnBtnadd(); + afx_msg void OnBtndelete(); + afx_msg void OnBtndone(); + afx_msg void OnCloseupCbtasks(); + afx_msg void OnKillfocusEddescription(); + afx_msg void OnKillfocusEddetails(); + afx_msg void OnKillfocusEdminutes(); + afx_msg void OnCkactive(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGTASKS_H__69649FC1_2BEE_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.cpp new file mode 100644 index 0000000..8b1db14 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.cpp @@ -0,0 +1,206 @@ +// FindClientDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "FindClientDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFindClientDlg dialog + + +CFindClientDlg::CFindClientDlg(CWnd* pParent /*=NULL*/) +: CDialog(CFindClientDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CFindClientDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Find client dialog"); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CFindClientDlg"); + rs->Query("SELECT * FROM users WHERE users.id=0"); + m_pstrReturnValue=NULL; +} + + +CFindClientDlg::~CFindClientDlg() +{ +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CFindClientDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CFindClientDlg) + DDX_Control(pDX, IDC_EDACCT, m_edAccount); + DDX_Control(pDX, IDC_LBLRESULTS, m_lblResults); + DDX_Control(pDX, IDC_EDSN, m_edSN); + DDX_Control(pDX, IDC_EDPHONE, m_edPhone); + DDX_Control(pDX, IDC_EDEMAIL, m_edEmail); + DDX_Control(pDX, IDC_BTNSEARCH, m_btnSearch); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CFindClientDlg, CDialog) +//{{AFX_MSG_MAP(CFindClientDlg) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_BN_CLICKED(IDC_BTNSEARCH, OnBtnsearch) +ON_BN_CLICKED(IDC_BTNCLEAR, OnBtnclear) +ON_BN_CLICKED(IDC_BTNCANCEL, OnBtncancel) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFindClientDlg message handlers + +void CFindClientDlg::OnBtndone() +{ + CDialog::OnOK(); +} + +//**************************************** +void CFindClientDlg::OnBtnsearch() +{ + CString strData,q; + long lData; + int x=0; + *m_pstrReturnValue="0"; + m_lblResults.SetWindowText(""); + + m_edSN.GetWindowText(strData); + + if(strData.IsEmpty()) + { + m_edPhone.GetWindowText(strData); + x=1; + } + + + if(strData.IsEmpty()) + { + m_edEmail.GetWindowText(strData); + x=2; + } + + + if(strData.IsEmpty()) + { + m_edAccount.GetWindowText(strData); + x=3; + } + + if(strData.IsEmpty()) + return;//nothing entered + + //prepare the query based on what field was filled out + switch (x) + { + case 0://SERIAL NUMBER + q.Format("SELECT clients.id, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS name " + "FROM units INNER JOIN clients ON units.client = clients.id " + "WHERE (((units.sn)=\"%s\"));",strData); + break; + + case 1://PHONE NUMBER + q.Format("SELECT clients.id, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS name " + "FROM clients WHERE (((clients.bizphone)=\"%s\"));",strData); + break; + + case 2://EMAIL + q.Format("SELECT clients.id, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS name " + "FROM clients WHERE (((clients.email)=\"%s\"));",strData); + break; + + case 3://Client account number + q.Format("SELECT clients.id, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS name " + "FROM clients WHERE (((clients.acctnumber)=\"%s\"));",strData); + break; + } + + //FUTURE: Modify this to allow for more than one match + //FILL a list box or something + //AfxMessageBox(q); + rs->Query(q); + if(rs->IsEmpty()) + { + m_lblResults.SetFontBold(FALSE); + m_lblResults.SetTextColor(RGB(255,0,0)); + m_lblResults.SetText("No match found"); + } + else + { + m_lblResults.SetTextColor(RGB(0,0,255)); + + m_lblResults.SetFontBold(TRUE); + rs->FetchField("name",&strData); + strData="Found---> " + strData; + m_lblResults.SetText(strData); + + //get the ID value + rs->FetchField("id",&lData); + m_pstrReturnValue->Format("%u",lData); + } + +} + + + +//**************************************** +BOOL CFindClientDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ASSERT(m_pstrReturnValue!=NULL); + //Hyperlink find label + m_lblResults.SetFontSize(12); + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +//***************************************** +void CFindClientDlg::SetReturn(CString *strReturnClientID) +{ + m_pstrReturnValue=strReturnClientID; + +} + + +//***************************** +void CFindClientDlg::OnBtnclear() +{ + m_edEmail.SetWindowText(""); + m_edPhone.SetWindowText(""); + m_edSN.SetWindowText(""); + m_lblResults.SetWindowText(""); +} + + +//******************************* +void CFindClientDlg::OnBtncancel() +{ + *m_pstrReturnValue="0"; + CDialog::OnCancel(); +} + + +//Do nothing when user presses enter key +void CFindClientDlg::OnOK() +{ + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.h new file mode 100644 index 0000000..0349597 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FindClientDlg.h @@ -0,0 +1,64 @@ +#if !defined(AFX_FINDCLIENTDLG_H__CA8D53C8_2FB6_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_FINDCLIENTDLG_H__CA8D53C8_2FB6_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// FindClientDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CFindClientDlg dialog + +#include "gzrset.h" +#include "label.h" + +class CFindClientDlg : public CDialog +{ +// Construction +public: + ~CFindClientDlg(); + void SetReturn(CString* strReturnClientID); + CFindClientDlg(CWnd* pParent = NULL); // standard constructor +CSpApp* m_pApp; +GZRset* rs; +CString * m_pstrReturnValue; +// Dialog Data + //{{AFX_DATA(CFindClientDlg) + enum { IDD = IDD_FINDCLIENT }; + CEdit m_edAccount; + CLabel m_lblResults; + CEdit m_edSN; + CEdit m_edPhone; + CEdit m_edEmail; + CButton m_btnSearch; + CButton m_btnDone; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFindClientDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CFindClientDlg) + afx_msg void OnBtndone(); + afx_msg void OnBtnsearch(); + virtual BOOL OnInitDialog(); + afx_msg void OnBtnclear(); + afx_msg void OnBtncancel(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FINDCLIENTDLG_H__CA8D53C8_2FB6_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.cpp new file mode 100644 index 0000000..662a7aa --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.cpp @@ -0,0 +1,1440 @@ +//////////////////////////////////////////////////////////////////////////// +// File: CFlatHeaderCtrl.cpp +// Version: 1.0.4 +// +// Author: Maarten Hoeben +// E-mail: hoeben@nwn.com +// +// Implementation of the CFlatHeaderCtrl and associated classes. +// +// This code may be used in compiled form in any way you desire. This +// file may be redistributed unmodified by any means PROVIDING it is +// not sold for profit without the authors written consent, and +// providing that this notice and the authors name and all copyright +// notices remains intact. +// +// An email letting me know how you are using it would be nice as well. +// +// This file is provided "as is" with no expressed or implied warranty. +// The author accepts no liability for any damage/loss of business that +// this product may cause. +// +// Version history +// +// 1.0.0 - Initial release +// 1.0.1 - Fixed FHDragWnd destroy warning (thanks Philippe Terrier) +// - Fixed double sent HDN_ITEMCLICK +// - Added a property that adjusts for ListCtrls that use a static +// border for flat look. +// 1.0.2 - Fixed another destroy warning +// - Fixed InsertItem array exception handling +// - Fixed incorrect header width painting +// - Changed DrawItem argument passing +// - Changed HDITEMEX struct item names +// - Added handler for HDM_SETIMAGELIST (precalculate image dimensions) +// - Changed DrawImage to clip images +// - Changed InsertItem ASSERT check to position limitation +// - Added new-style "HotDivider" arrows +// - Fixed some GDI objects +// - Added 'don't drop cursor' support to indicate drag&drop +// outside control +// - Added drag&drop target window support +// - Changed CFHDragWnd to support externally created items +// - Removed topmost-style from CFHDropWnd +// - Fixed OnSetHotDivider order bug +// - Added extended styles +// - Added item width estimation function +// 1.0.3 - Added WM_CANCELMODE handler +// 1.0.4 - Changed copyright message +// - Added tooltip style +// +//////////////////////////////////////////////////////////////////////////// + + +// FlatHeaderCtrl.cpp : implementation file +// + +#include "stdafx.h" +#include "FlatHeaderCtrl.h" + +#include + +#include "MemDC.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFHDragWnd + +CFHDragWnd::CFHDragWnd() +{ + // Register the window class if it has not already been registered. + WNDCLASS wndclass; + HINSTANCE hInst = AfxGetInstanceHandle(); + + if(!(::GetClassInfo(hInst, FHDRAGWND_CLASSNAME, &wndclass))) + { + // otherwise we need to register a new class + wndclass.style = CS_SAVEBITS ; + wndclass.lpfnWndProc = ::DefWindowProc; + wndclass.cbClsExtra = wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor( hInst, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = FHDRAGWND_CLASSNAME; + if (!AfxRegisterClass(&wndclass)) + AfxThrowResourceException(); + } + + m_pFlatHeaderCtrl = NULL; + m_iItem = -1; + m_lphdiItem = NULL; +} + +CFHDragWnd::~CFHDragWnd() +{ +} + + +BEGIN_MESSAGE_MAP(CFHDragWnd, CWnd) +//{{AFX_MSG_MAP(CFHDragWnd) +ON_WM_PAINT() +ON_WM_ERASEBKGND() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CFHDragWnd message handlers + +BOOL CFHDragWnd::Create(CRect rect, CFlatHeaderCtrl* pFlatHeaderCtrl, INT iItem, LPHDITEM lphdiItem) +{ + ASSERT_VALID(pFlatHeaderCtrl); + ASSERT(pFlatHeaderCtrl->IsKindOf(RUNTIME_CLASS(CFlatHeaderCtrl))); + + m_pFlatHeaderCtrl = pFlatHeaderCtrl; + m_iItem = iItem; + m_lphdiItem = lphdiItem; + + DWORD dwStyle = WS_POPUP|WS_DISABLED; + DWORD dwExStyle = WS_EX_TOOLWINDOW|WS_EX_TOPMOST; + + return CreateEx(dwExStyle, FHDRAGWND_CLASSNAME, NULL, dwStyle, + rect.left, rect.top, rect.Width(), rect.Height(), + NULL, NULL, NULL ); +} + + +void CFHDragWnd::OnPaint() +{ + CPaintDC dc(this); + + if(m_pFlatHeaderCtrl->m_bDoubleBuffer) + { + CMemDC MemDC(&dc); + OnDraw(&MemDC); + } + else + OnDraw(&dc); +} + +BOOL CFHDragWnd::OnEraseBkgnd(CDC* pDC) +{ + return TRUE; +} + +void CFHDragWnd::OnDraw(CDC* pDC) +{ + CRect rect; + GetClientRect(rect); + + pDC->FillSolidRect(rect, m_pFlatHeaderCtrl->m_cr3DFace); + pDC->Draw3dRect(rect, m_pFlatHeaderCtrl->m_cr3DHighLight, m_pFlatHeaderCtrl->m_cr3DShadow); + + CPen* pPen = pDC->GetCurrentPen(); + CFont* pFont = pDC->SelectObject(m_pFlatHeaderCtrl->GetFont()); + + pDC->SetBkColor(m_pFlatHeaderCtrl->m_cr3DFace); + pDC->SetTextColor(m_pFlatHeaderCtrl->m_crText); + + rect.DeflateRect(m_pFlatHeaderCtrl->m_iSpacing, 0); + m_pFlatHeaderCtrl->DrawItem( + pDC, + rect, + m_lphdiItem, + m_pFlatHeaderCtrl->m_iSortColumn == m_iItem, + m_pFlatHeaderCtrl->m_bSortAscending + ); + + pDC->SelectObject(pFont); + pDC->SelectObject(pPen); +} + +void CFHDragWnd::PostNcDestroy() +{ + CWnd::PostNcDestroy(); + delete this; +} + +///////////////////////////////////////////////////////////////////////////// +// CFHDropWnd + +CFHDropWnd::CFHDropWnd(COLORREF crColor) +{ + m_brush.CreateSolidBrush(crColor); + + // Register the window class if it has not already been registered. + WNDCLASS wndclass; + HINSTANCE hInst = AfxGetInstanceHandle(); + + if(!(::GetClassInfo(hInst, FHDROPWND_CLASSNAME, &wndclass))) + { + // otherwise we need to register a new class + wndclass.style = CS_SAVEBITS ; + wndclass.lpfnWndProc = ::DefWindowProc; + wndclass.cbClsExtra = wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor( hInst, IDC_ARROW ); + wndclass.hbrBackground = (HBRUSH)m_brush; + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = FHDROPWND_CLASSNAME; + if (!AfxRegisterClass(&wndclass)) + AfxThrowResourceException(); + } +} + +CFHDropWnd::~CFHDropWnd() +{ +} + + +BEGIN_MESSAGE_MAP(CFHDropWnd, CWnd) +//{{AFX_MSG_MAP(CFHDropWnd) +ON_WM_ERASEBKGND() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CFHDropWnd message handlers + +BOOL CFHDropWnd::Create(INT iHeight) +{ + m_iHeight = iHeight + 20; + + DWORD dwStyle = WS_POPUP|WS_DISABLED; + DWORD dwExStyle = WS_EX_TOOLWINDOW ; + + BOOL bResult = CreateEx(dwExStyle, FHDROPWND_CLASSNAME, NULL, dwStyle, + 0, 0, 12, m_iHeight, + NULL, NULL, NULL ); + + CRgn rgn1, rgn2; + POINT ptArrow[7]; + + ptArrow[0].x = 8; ptArrow[0].y = 0; + ptArrow[1].x = 8; ptArrow[1].y = 4; + ptArrow[2].x = 11; ptArrow[2].y = 4; + ptArrow[3].x = 6; ptArrow[3].y = 9; + ptArrow[4].x = 1; ptArrow[4].y = 4; + ptArrow[5].x = 4; ptArrow[5].y = 4; + ptArrow[6].x = 4; ptArrow[6].y = 0; + rgn1.CreatePolygonRgn(ptArrow, 7, ALTERNATE); + + + ptArrow[0].x = 4; ptArrow[0].y = m_iHeight; + ptArrow[1].x = 4; ptArrow[1].y = m_iHeight-4; + ptArrow[2].x = 0; ptArrow[2].y = m_iHeight-4; + ptArrow[3].x = 6; ptArrow[3].y = m_iHeight-10; + ptArrow[4].x = 12; ptArrow[4].y = m_iHeight-4; + ptArrow[5].x = 8; ptArrow[5].y = m_iHeight-4; + ptArrow[6].x = 8; ptArrow[6].y = m_iHeight; + rgn2.CreatePolygonRgn(ptArrow, 7, ALTERNATE); + + m_rgn.CreateRectRgn(0, 0, 12, iHeight); + m_rgn.CombineRgn(&rgn1, &rgn2, RGN_OR); + SetWindowRgn(m_rgn, FALSE); + + rgn1.DeleteObject(); + rgn2.DeleteObject(); + + return bResult; +} + + +void CFHDropWnd::PostNcDestroy() +{ + m_rgn.DeleteObject(); + + CWnd::PostNcDestroy(); + delete this; +} + +BOOL CFHDropWnd::OnEraseBkgnd(CDC* pDC) +{ + pDC->FillRect(CRect(0, 0, 12, m_iHeight), &m_brush); + return TRUE; +} + +void CFHDropWnd::SetWindowPos(INT x, INT y) +{ + CWnd::SetWindowPos( + &wndTop, + x-6, y-(m_iHeight/2), + 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE + ); +} + +///////////////////////////////////////////////////////////////////////////// +// CFlatHeaderCtrl + +IMPLEMENT_DYNCREATE(CFlatHeaderCtrl, CHeaderCtrl) + +CFlatHeaderCtrl::CFlatHeaderCtrl() +{ + m_bDoubleBuffer = TRUE; + m_iSpacing = 6; + m_sizeArrow.cx = 8; + m_sizeArrow.cy = 8; + m_sizeImage.cx = 0; + m_sizeImage.cy = 0; + m_bStaticBorder = FALSE; + m_nDontDropCursor = 0; + m_hDropTarget = NULL; + m_rcDropTarget.SetRectEmpty(); + m_iDropResult = 0; + + m_iHotIndex = -1; + m_bHotItemResizable = FALSE; + + m_bResizing = FALSE; + + m_iHotDivider = -1; + m_crHotDivider = 0x000000FF; + m_pDropWnd = NULL; + + m_bDragging = FALSE; + m_pDragWnd = NULL; + + m_nClickFlags = 0; + + m_bSortAscending = FALSE; + m_iSortColumn = -1; + m_arrayHdrItemEx.SetSize(0, 8); + + m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT); + m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW); + m_cr3DFace = ::GetSysColor(COLOR_3DFACE); + m_crText = ::GetSysColor(COLOR_BTNTEXT); +} + +CFlatHeaderCtrl::~CFlatHeaderCtrl() +{ + if(m_pDropWnd != NULL) + { + m_pDropWnd->DestroyWindow(); + m_pDropWnd = NULL; + } + + if(m_pDragWnd != NULL) + { + m_pDragWnd->DestroyWindow(); + m_pDragWnd = NULL; + } +} + +BEGIN_MESSAGE_MAP(CFlatHeaderCtrl, CHeaderCtrl) +//{{AFX_MSG_MAP(CFlatHeaderCtrl) +ON_MESSAGE(HDM_INSERTITEMA, OnInsertItem) +ON_MESSAGE(HDM_INSERTITEMW, OnInsertItem) +ON_MESSAGE(HDM_DELETEITEM, OnDeleteItem) +ON_MESSAGE(HDM_SETIMAGELIST, OnSetImageList) +ON_MESSAGE(HDM_SETHOTDIVIDER, OnSetHotDivider) +ON_MESSAGE(HDM_LAYOUT, OnLayout) +ON_NOTIFY_EX(TTN_NEEDTEXTA, 0, OnToolTipNotify) +ON_NOTIFY_EX(TTN_NEEDTEXTW, 0, OnToolTipNotify) +ON_WM_NCHITTEST() +ON_WM_SETCURSOR() +ON_WM_LBUTTONDOWN() +ON_WM_LBUTTONDBLCLK() +ON_WM_PAINT() +ON_WM_SYSCOLORCHANGE() +ON_WM_ERASEBKGND() +ON_WM_LBUTTONUP() +ON_WM_MOUSEMOVE() +ON_WM_CANCELMODE() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFlatHeaderCtrl attributes + +BOOL CFlatHeaderCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam) +{ + switch(wParam) + { + case FH_PROPERTY_SPACING: + m_iSpacing = (INT)lParam; + break; + + case FH_PROPERTY_ARROW: + m_sizeArrow.cx = LOWORD(lParam); + m_sizeArrow.cy = HIWORD(lParam); + break; + + case FH_PROPERTY_STATICBORDER: + m_bStaticBorder = (BOOL)lParam; + break; + + case FH_PROPERTY_DONTDROPCURSOR: + m_nDontDropCursor = (UINT)lParam; + break; + + case FH_PROPERTY_DROPTARGET: + m_hDropTarget = (HWND)lParam; + break; + + case FH_PROPERTY_ENABLETOOLTIPS: + EnableToolTips((BOOL)lParam); + break; + + default: + return FALSE; + } + + Invalidate(); + return TRUE; +} + +BOOL CFlatHeaderCtrl::GetItemEx(INT iPos, HDITEMEX* phditemex) const +{ + if(iPos>=m_arrayHdrItemEx.GetSize()) + return FALSE; + + phditemex->nStyle = m_arrayHdrItemEx[iPos].nStyle; + phditemex->iMinWidth = m_arrayHdrItemEx[iPos].iMinWidth; + phditemex->iMaxWidth = m_arrayHdrItemEx[iPos].iMaxWidth; + phditemex->strToolTip = m_arrayHdrItemEx[iPos].strToolTip; + return TRUE; +} + +BOOL CFlatHeaderCtrl::SetItemEx(INT iPos, HDITEMEX* phditemex) +{ + if(iPos>=m_arrayHdrItemEx.GetSize()) + return FALSE; + + BOOL bUpdate = FALSE; + + HDITEM hditem; + hditem.mask = HDI_WIDTH; + if(!GetItem(iPos, &hditem)) + return FALSE; + + HDITEMEX hditemex = *phditemex; + + if(hditemex.nStyle&HDF_EX_AUTOWIDTH) + { + TCHAR szText[FLATHEADER_TEXT_MAX]; + + HDITEM hdi; + hdi.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP; + hdi.pszText = szText; + hdi.cchTextMax = sizeof(szText); + VERIFY(GetItem(iPos, &hdi)); + + hditem.cxy = GetItemWidth(&hdi, hditemex.nStyle&HDF_EX_INCLUDESORT ? TRUE:FALSE); + bUpdate = TRUE; + } + + if((!(hditemex.nStyle&HDF_EX_FIXEDWIDTH)) && (hditemex.iMinWidth<=hditemex.iMaxWidth)) + { + if(hditem.cxy < hditemex.iMinWidth) + { + hditem.cxy = hditemex.iMinWidth; + bUpdate = TRUE; + } + + if(hditem.cxy > hditemex.iMaxWidth) + { + hditem.cxy = hditemex.iMaxWidth; + bUpdate = TRUE; + } + } + + if(bUpdate) + SetItem(iPos, &hditem); + + m_arrayHdrItemEx.SetAt(iPos, hditemex); + return TRUE; +} + +INT CFlatHeaderCtrl::GetItemWidth(LPHDITEM lphdi, BOOL bIncludeSort) +{ + INT iWidth = 0; + + CBitmap* pBitmap = NULL; + BITMAP biBitmap; + if(lphdi->fmt&HDF_BITMAP) + { + ASSERT(lphdi->mask&HDI_BITMAP); + ASSERT(lphdi->hbm); + + pBitmap = CBitmap::FromHandle(lphdi->hbm); + if(pBitmap) + VERIFY(pBitmap->GetObject(sizeof(BITMAP), &biBitmap)); + } + + iWidth += m_iSpacing; + iWidth += lphdi->fmt&HDF_IMAGE ? m_sizeImage.cx+m_iSpacing:0; + iWidth += lphdi->fmt&HDF_BITMAP ? biBitmap.bmWidth+m_iSpacing:0; + iWidth += bIncludeSort ? m_sizeArrow.cx+m_iSpacing:0; + + if(lphdi->mask&HDI_TEXT && lphdi->fmt&HDF_STRING) + { + CClientDC dc(this); + CFont* pFont = dc.SelectObject(GetFont()); + + iWidth += dc.GetTextExtent(lphdi->pszText).cx + m_iSpacing; + + dc.SelectObject(pFont); + } + + return iWidth; +} + +void CFlatHeaderCtrl::SetSortColumn(INT iPos, BOOL bSortAscending) +{ + ASSERT(iPos < GetItemCount()); + + m_bSortAscending = bSortAscending; + m_iSortColumn = iPos; + Invalidate(); +} + +INT CFlatHeaderCtrl::GetSortColumn(BOOL* pbSortAscending) +{ + if(pbSortAscending) + *pbSortAscending = m_bSortAscending; + + return m_iSortColumn; +} + +INT CFlatHeaderCtrl::GetDropResult() +{ + return m_iDropResult; +} + +///////////////////////////////////////////////////////////////////////////// +// CFlatHeaderCtrl implementation + +void CFlatHeaderCtrl::DrawCtrl(CDC* pDC) +{ + CRect rectClip; + if (pDC->GetClipBox(&rectClip) == ERROR) + return; + + CRect rectClient, rectItem; + GetClientRect(&rectClient); + + pDC->FillSolidRect(rectClip, m_cr3DFace); + + INT iItems = GetItemCount(); + ASSERT(iItems >= 0); + + CPen penHighLight(PS_SOLID, 1, m_cr3DHighLight); + CPen penShadow(PS_SOLID, 1, m_cr3DShadow); + CPen* pPen = pDC->GetCurrentPen(); + + CFont* pFont = pDC->SelectObject(GetFont()); + + pDC->SetBkColor(m_cr3DFace); + pDC->SetTextColor(m_crText); + + INT iWidth = 0; + + for(INT i=0;i= rectClip.left || rectItem.left <= rectClip.right) + { + if(hditem.fmt&HDF_OWNERDRAW) + { + DRAWITEMSTRUCT disItem; + disItem.CtlType = ODT_BUTTON; + disItem.CtlID = GetDlgCtrlID(); + disItem.itemID = iItem; + disItem.itemAction = ODA_DRAWENTIRE; + disItem.itemState = 0; + disItem.hwndItem = m_hWnd; + disItem.hDC = pDC->m_hDC; + disItem.rcItem = rectItem; + disItem.itemData = 0; + + DrawItem(&disItem); + } + else + { + rectItem.DeflateRect(m_iSpacing, 0); + DrawItem(pDC, rectItem, &hditem, iItem == m_iSortColumn, m_bSortAscending); + rectItem.InflateRect(m_iSpacing, 0); + + if(m_nClickFlags&MK_LBUTTON && m_iHotIndex == iItem && m_hdhtiHotItem.flags&HHT_ONHEADER) + pDC->InvertRect(rectItem); + } + + if(i < iItems-1) + { + pDC->SelectObject(&penShadow); + pDC->MoveTo(rectItem.right-1, rectItem.top+2); + pDC->LineTo(rectItem.right-1, rectItem.bottom-2); + + pDC->SelectObject(&penHighLight); + pDC->MoveTo(rectItem.right, rectItem.top+2); + pDC->LineTo(rectItem.right, rectItem.bottom-2); + } + } + + iWidth += hditem.cxy; + } + + if(iWidth > 0) + { + rectClient.right = rectClient.left + iWidth; + pDC->Draw3dRect(rectClient, m_cr3DHighLight, m_cr3DShadow); + } + + pDC->SelectObject(pFont); + pDC->SelectObject(pPen); + + penHighLight.DeleteObject(); + penShadow.DeleteObject(); +} + +void CFlatHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT) +{ + ASSERT(FALSE); // must override for self draw header controls +} + +void CFlatHeaderCtrl::DrawItem(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bSort, BOOL bSortAscending) +{ + ASSERT(lphdi->mask&HDI_FORMAT); + + INT iWidth = 0; + + CBitmap* pBitmap = NULL; + BITMAP BitmapInfo; + if(lphdi->fmt&HDF_BITMAP) + { + ASSERT(lphdi->mask&HDI_BITMAP); + ASSERT(lphdi->hbm); + + pBitmap = CBitmap::FromHandle(lphdi->hbm); + if(pBitmap) + VERIFY(pBitmap->GetObject(sizeof(BITMAP), &BitmapInfo)); + } + + switch(lphdi->fmt&HDF_JUSTIFYMASK) + { + case HDF_LEFT: + rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0; + if(lphdi->fmt&HDF_IMAGE && !iWidth) + break; + rect.right -= bSort ? m_iSpacing+m_sizeArrow.cx : 0; + rect.left += (iWidth = DrawText(pDC, rect, lphdi)) ? iWidth+m_iSpacing : 0; + if(bSort) + { + rect.right += m_iSpacing+m_sizeArrow.cx; + rect.left += DrawArrow(pDC, rect, bSortAscending, FALSE)+m_iSpacing; + } + DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE); + break; + + case HDF_CENTER: + rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0; + if(lphdi->fmt&HDF_IMAGE && !iWidth) + break; + + rect.left += bSort ? m_iSpacing+m_sizeArrow.cx : 0; + rect.right -= (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) ? iWidth+m_iSpacing:0; + if(bSort) + { + rect.left -= m_iSpacing+m_sizeArrow.cx; + rect.right -= DrawArrow(pDC, rect, bSortAscending, TRUE)+2*m_iSpacing; + } + DrawText(pDC, rect, lphdi); + break; + + case HDF_RIGHT: + if(!(lphdi->fmt&HDF_BITMAP_ON_RIGHT)) + rect.left += (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, FALSE)) ? iWidth+m_iSpacing:0; + + rect.left += (iWidth = DrawImage(pDC, rect, lphdi, FALSE)) ? iWidth+m_iSpacing : 0; + if(lphdi->fmt&HDF_IMAGE && !iWidth) + break; + + rect.left += bSort && (lphdi->fmt&HDF_BITMAP_ON_RIGHT) ? m_iSpacing+m_sizeArrow.cx : 0; + if(lphdi->fmt&HDF_BITMAP_ON_RIGHT) + rect.right -= (iWidth=DrawBitmap(pDC, rect, lphdi, pBitmap, &BitmapInfo, TRUE)) ? iWidth+m_iSpacing:0; + if(bSort) + { + rect.left -= (lphdi->fmt&HDF_BITMAP_ON_RIGHT) ? m_iSpacing+m_sizeArrow.cx:0; + rect.right -= DrawArrow(pDC, rect, bSortAscending, TRUE)+2*m_iSpacing; + } + DrawText(pDC, rect, lphdi); + break; + } +} + +INT CFlatHeaderCtrl::DrawImage(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bRight) +{ + CImageList* pImageList = GetImageList(); + INT iWidth = 0; + + if(lphdi->mask&HDI_IMAGE && lphdi->fmt&HDF_IMAGE) + { + ASSERT(pImageList); + ASSERT(lphdi->iImage>=0 && lphdi->iImageGetImageCount()); + + if(rect.Width()>0) + { + POINT point; + + point.y = rect.CenterPoint().y - (m_sizeImage.cy>>1); + + if(bRight) + point.x = rect.right - m_sizeImage.cx; + else + point.x = rect.left; + + SIZE size; + size.cx = rect.Width()DrawIndirect(pDC, lphdi->iImage, point, size, CPoint(0, 0)); + + iWidth = m_sizeImage.cx; + } + } + + return iWidth; +} + +INT CFlatHeaderCtrl::DrawBitmap(CDC* pDC, CRect rect, LPHDITEM lphdi, CBitmap* pBitmap, BITMAP* pBitmapInfo, BOOL bRight) +{ + INT iWidth = 0; + + if(pBitmap) + { + iWidth = pBitmapInfo->bmWidth; + if(iWidth<=rect.Width() && rect.Width()>0) + { + POINT point; + + point.y = rect.CenterPoint().y - (pBitmapInfo->bmHeight>>1); + + if(bRight) + point.x = rect.right - iWidth; + else + point.x = rect.left; + + /* + CDC dc; + if(dc.CreateCompatibleDC(pDC) == TRUE) + { + VERIFY(dc.SelectObject(pBitmap)); + iWidth = pDC->BitBlt( + point.x, point.y, + pBitmapInfo->bmWidth, pBitmapInfo->bmHeight, + &dc, + 0, 0, + SRCCOPY + ) ? iWidth:0; + } + else iWidth = 0; + */ + //replaced 10/24/00 supposed resource leak + //see:http://codeguru.earthweb.com/mfc/comments/17458.shtml + CDC dc; + if(dc.CreateCompatibleDC(pDC) == TRUE) + { + CBitmap* pOldBit = (CBitmap*) dc.SelectObject(pBitmap); + ASSERT(pOldBit); + iWidth = pDC->BitBlt( + point.x, point.y, + pBitmapInfo->bmWidth, pBitmapInfo->bmHeight, + &dc, 0, 0, SRCCOPY ) + ? iWidth:0; + dc.SelectObject(pOldBit); // need to restore the bitmap + } + else iWidth = 0; + + + + } + else + iWidth = 0; + } + + return iWidth; +} + +INT CFlatHeaderCtrl::DrawText(CDC* pDC, CRect rect, LPHDITEM lphdi) +{ + CSize size; + + if(rect.Width()>0 && lphdi->mask&HDI_TEXT && lphdi->fmt&HDF_STRING) + { + size = pDC->GetTextExtent(lphdi->pszText); + + switch(lphdi->fmt&HDF_JUSTIFYMASK) + { + case HDF_LEFT: + case HDF_LEFT|HDF_RTLREADING: + pDC->DrawText(lphdi->pszText, -1, rect, DT_LEFT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER); + break; + case HDF_CENTER: + case HDF_CENTER|HDF_RTLREADING: + pDC->DrawText(lphdi->pszText, -1, rect, DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER); + break; + case HDF_RIGHT: + case HDF_RIGHT|HDF_RTLREADING: + pDC->DrawText(lphdi->pszText, -1, rect, DT_RIGHT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER); + break; + } + } + + size.cx = rect.Width()>size.cx ? size.cx:rect.Width(); + return size.cx>0 ? size.cx:0; +} + +INT CFlatHeaderCtrl::DrawArrow(CDC* pDC, CRect rect, BOOL bSortAscending, BOOL bRight) +{ + INT iWidth = 0; + + if(rect.Width()>0 && m_sizeArrow.cx<=rect.Width()) + { + iWidth = m_sizeArrow.cx; + + rect.top += (rect.Height() - m_sizeArrow.cy - 1)>>1; + rect.bottom = rect.top + m_sizeArrow.cy - 1; + + rect.left = bRight ? rect.right-m_sizeArrow.cy:rect.left; + + // Set up pens to use for drawing the triangle + CPen penLight(PS_SOLID, 1, m_cr3DHighLight); + CPen penShadow(PS_SOLID, 1, m_cr3DShadow); + CPen *pPen = pDC->SelectObject(&penLight); + + if(bSortAscending) + { + // Draw triangle pointing upwards + pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1) + 1, rect.top); + pDC->LineTo(rect.left + (m_sizeArrow.cx-1), rect.top + m_sizeArrow.cy - 1); + pDC->LineTo(rect.left, rect.top + m_sizeArrow.cy - 1); + + pDC->SelectObject(&penShadow); + pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1), rect.top); + pDC->LineTo(rect.left, rect.top + m_sizeArrow.cy - 1); + } + else + { + // Draw triangle pointing downwards + pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1)+1, rect.top + m_sizeArrow.cy - 1); + pDC->LineTo(rect.left + (m_sizeArrow.cx-1), rect.top); + + pDC->SelectObject(&penShadow); + pDC->MoveTo(rect.left + ((m_sizeArrow.cx-1)>>1), rect.top + m_sizeArrow.cy - 1); + pDC->LineTo(rect.left, rect.top); + pDC->LineTo(rect.left + m_sizeArrow.cx, rect.top); + } + + // Restore the pen + pDC->SelectObject(pPen); + + penLight.DeleteObject(); + penShadow.DeleteObject(); + } + + return iWidth; +} + +INT CFlatHeaderCtrl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const +{ + INT iResult = CHeaderCtrl::OnToolHitTest(point, pTI); + if(iResult != -1) + return iResult; + + HDHITTESTINFO hdhti; + hdhti.pt = point; + iResult = ::SendMessage(GetSafeHwnd(), HDM_HITTEST, 0, (LPARAM)(&hdhti)); + if(iResult > -1) + { + GetItemRect(iResult, &pTI->rect); + + pTI->cbSize = sizeof(TOOLINFO); + pTI->hwnd = GetSafeHwnd(); + pTI->uFlags = TTF_ALWAYSTIP; + pTI->lpszText = LPSTR_TEXTCALLBACK; + pTI->uId = FLATHEADER_TT_MAGIC; + } + + return iResult; +} + +///////////////////////////////////////////////////////////////////////////// +// CHeaderCtrl message handlers + +LRESULT CFlatHeaderCtrl::OnInsertItem(WPARAM wParam, LPARAM lParam) +{ + HDITEMEX hditemex; + hditemex.iMinWidth = 0; + hditemex.iMaxWidth = -1; + + LRESULT lResult = -1; + + WORD wItems = m_arrayHdrItemEx.GetSize(); + wParam = wParam<=wItems ? wParam:wItems; + + try + { + m_arrayHdrItemEx.InsertAt(wParam, hditemex); + + lResult = Default(); + if(lResult < 0) // Cleanup + m_arrayHdrItemEx.RemoveAt(wParam); + } + catch(CMemoryException* e) + { + e->Delete(); + } + + return lResult; +} + +LRESULT CFlatHeaderCtrl::OnDeleteItem(WPARAM wParam, LPARAM lParam) +{ + ASSERT((INT)wParam < m_arrayHdrItemEx.GetSize()); + m_arrayHdrItemEx.RemoveAt(wParam); + + return Default(); +} + +LRESULT CFlatHeaderCtrl::OnSetImageList(WPARAM wParam, LPARAM lParam) +{ + CImageList* pImageList; + pImageList = CImageList::FromHandle((HIMAGELIST)lParam); + + IMAGEINFO info; + if(pImageList->GetImageInfo(0, &info)) + { + m_sizeImage.cx = info.rcImage.right - info.rcImage.left; + m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top; + } + + return Default(); +} + +LRESULT CFlatHeaderCtrl::OnSetHotDivider(WPARAM wParam, LPARAM lParam) +{ + if(wParam) + { + HDHITTESTINFO hdhti; + hdhti.pt.x = LOWORD(lParam); + hdhti.pt.y = HIWORD(lParam); + ScreenToClient(&hdhti.pt); + + INT iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&hdhti)); + if(iHotIndex >= 0) + { + HDITEM hditem; + hditem.mask = HDI_ORDER; + VERIFY(GetItem(iHotIndex, &hditem)); + m_iHotDivider = hditem.iOrder; + + CRect rectItem; + VERIFY(GetItemRect(iHotIndex, rectItem)); + if(hdhti.pt.x > rectItem.CenterPoint().x) + m_iHotDivider++; + } + else + m_iHotDivider = -1; + } + else + m_iHotDivider = (INT)lParam; + + RECT rect; + GetClientRect(&rect); + + INT iItems = GetItemCount(); + if(m_iHotDivider >= 0 && m_iHotDivider<=iItems+1) + { + if(m_pDropWnd == NULL) + { + m_pDropWnd = new CFHDropWnd(m_crHotDivider); + if(m_pDropWnd) + m_pDropWnd->Create(rect.bottom - rect.top); + } + + if(m_pDropWnd != NULL) + { + POINT pt; + pt.y = (rect.bottom-rect.top)/2; + + if(m_iHotDividerSetWindowPos(pt.x, pt.y); + } + } + else + { + if(m_pDropWnd != NULL) + { + m_pDropWnd->DestroyWindow(); + m_pDropWnd = NULL; + } + } + + return(LRESULT)m_iHotDivider; +} + +LRESULT CFlatHeaderCtrl::OnLayout(WPARAM wParam, LPARAM lParam) +{ + LPHDLAYOUT lphdlayout = (LPHDLAYOUT)lParam; + + if(m_bStaticBorder) + lphdlayout->prc->right += GetSystemMetrics(SM_CXBORDER)*2; + + return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam); +} + +BOOL CFlatHeaderCtrl::OnToolTipNotify(UINT nId, NMHDR *pNMHDR, LRESULT *pResult) +{ + TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR; + + if( + pNMHDR->idFrom == (UINT)FLATHEADER_TT_MAGIC && + !m_arrayHdrItemEx[m_iHotIndex].strToolTip.IsEmpty() + ) { + USES_CONVERSION; + + wcscpy((WCHAR*)pTTT->lpszText, A2W((LPCTSTR)m_arrayHdrItemEx[m_iHotIndex].strToolTip)); + pTTT->lpszText = pTTT->szText; + return TRUE; + } + else + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// CFlatHeaderCtrl message handlers + +void CFlatHeaderCtrl::OnSysColorChange() +{ + CHeaderCtrl::OnSysColorChange(); + + m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT); + m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW); + m_cr3DFace = ::GetSysColor(COLOR_3DFACE); + m_crText = ::GetSysColor(COLOR_BTNTEXT); +} + +BOOL CFlatHeaderCtrl::OnEraseBkgnd(CDC* pDC) +{ + return TRUE; +} + +void CFlatHeaderCtrl::OnPaint() +{ + CPaintDC dc(this); + + if (m_bDoubleBuffer) + { + CMemDC MemDC(&dc); + DrawCtrl(&MemDC); + } + else + DrawCtrl(&dc); +} + +UINT CFlatHeaderCtrl::OnNcHitTest(CPoint point) +{ + m_hdhtiHotItem.pt = point; + ScreenToClient(&m_hdhtiHotItem.pt); + + m_iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&m_hdhtiHotItem)); + if(m_iHotIndex >= 0) + { + HDITEM hditem; + hditem.mask = HDI_ORDER; + VERIFY(GetItem(m_iHotIndex, &hditem)); + m_iHotOrder = hditem.iOrder; + + HDITEMEX hditemex; + if(GetItemEx(m_iHotIndex, &hditemex)) + m_bHotItemResizable = hditemex.nStyle&HDF_EX_FIXEDWIDTH ? FALSE:TRUE; + } + + return CHeaderCtrl::OnNcHitTest(point); +} + + +BOOL CFlatHeaderCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + if(m_iHotIndex>=0 && m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN) && !m_bHotItemResizable) + { + SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); + return TRUE; + } + + return CHeaderCtrl::OnSetCursor(pWnd, nHitTest, message); +} + +void CFlatHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point) +{ + m_nClickFlags = nFlags; + m_ptClickPoint = point; + + if(m_iHotIndex >= 0) + { + m_hdiHotItem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP|HDI_ORDER|HDI_LPARAM; + m_hdiHotItem.pszText = m_szHotItemText; + m_hdiHotItem.cchTextMax = sizeof(m_szHotItemText); + VERIFY(GetItem(m_iHotIndex, &m_hdiHotItem)); + + if(m_hdhtiHotItem.flags&HHT_ONHEADER) + { + RECT rectItem; + VERIFY(GetItemRect(m_iHotIndex, &rectItem)); + InvalidateRect(&rectItem); + } + + if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN)) + { + if(!m_bHotItemResizable) + return; + + HDITEMEX hditemex; + VERIFY(GetItemEx(m_iHotIndex, &hditemex)); + + CRect rectItem; + GetItemRect(m_iHotIndex, rectItem); + ClientToScreen(rectItem); + + if(hditemex.iMinWidth <= hditemex.iMaxWidth) + { + CRect rectClip; + GetClipCursor(rectClip); + + POINT point; + GetCursorPos(&point); + + INT iOffset = point.x - rectItem.right; + + rectClip.left = rectItem.left + hditemex.iMinWidth + iOffset; + rectClip.right = rectItem.left + hditemex.iMaxWidth + iOffset; + + ClipCursor(rectClip); + } + + m_bResizing = TRUE; + } + } + + CHeaderCtrl::OnLButtonDown(nFlags, point); +} + + +void CFlatHeaderCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + if(m_iHotIndex>=0 && m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN) && !m_bHotItemResizable) + return; + + CHeaderCtrl::OnLButtonDblClk(nFlags, point); +} + +void CFlatHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point) +{ + m_nClickFlags = nFlags; + m_ptClickPoint = point; + + if(m_iHotIndex >= 0) + { + CWnd* pWnd = GetParent(); + + if(m_hdhtiHotItem.flags&(HHT_ONDIVIDER|HHT_ONDIVOPEN)) + { + if(m_bResizing) + { + ClipCursor(NULL); + m_bResizing = FALSE; + } + } + + if(m_hdhtiHotItem.flags&HHT_ONHEADER) + { + if(m_bDragging) + { + NMHEADER nmhdr; + nmhdr.hdr.hwndFrom = m_hWnd; + nmhdr.hdr.idFrom = GetDlgCtrlID(); + nmhdr.hdr.code = HDN_ENDDRAG; + nmhdr.iItem = m_iHotIndex; + nmhdr.iButton = 0; + nmhdr.pitem = &m_hdiHotItem; + if(pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmhdr)==FALSE && m_iHotDivider>=0) + { + INT iCount = GetItemCount(); + ASSERT(m_iHotOrder < iCount); + ASSERT(m_iHotDivider <= iCount); + + LPINT piArray = new INT[iCount*2]; + if(piArray) + { + GetOrderArray((LPINT)piArray, iCount); + + for(INT i=0,j=0;i=m_iHotDivider && i == m_iHotDivider) + ) + piArray[iCount+i] = piArray[m_iHotOrder]; + else + piArray[iCount+i] = piArray[j++]; + } + + SetOrderArray(iCount, (LPINT)&piArray[iCount]); + delete piArray; + } + else + AfxThrowMemoryException(); + } + + if(m_pDragWnd != NULL) + { + m_pDragWnd->DestroyWindow(); + m_pDragWnd = NULL; + } + + if (GetCapture()->GetSafeHwnd() == GetSafeHwnd()) + ReleaseCapture(); + + m_bDragging = FALSE; + OnSetHotDivider(FALSE, -1); + + Invalidate(); + } + else + { + RECT rectItem; + VERIFY(GetItemRect(m_iHotIndex, &rectItem)); + InvalidateRect(&rectItem); + } + } + } + + CHeaderCtrl::OnLButtonUp(nFlags, point); +} + +void CFlatHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point) +{ + if(m_nClickFlags&MK_LBUTTON && m_iHotIndex>=0) + { + if(m_bResizing) + CHeaderCtrl::OnMouseMove(nFlags, point); + + if(m_hdhtiHotItem.flags&HHT_ONHEADER) + { + if(m_bDragging) + { + if(m_pDragWnd != NULL) + { + CRect rect; + m_pDragWnd->GetWindowRect(&rect); + + CPoint pt = point; + ClientToScreen(&pt); + + pt.Offset(-(rect.Width()>>1), -(rect.Height()>>1)); + + m_pDragWnd->SetWindowPos( + &wndTop, + pt.x, pt.y, + 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE + ); + + HDHITTESTINFO hdhti; + hdhti.pt.x = point.x; + hdhti.pt.y = point.y; + + INT iHotOrder = -1; + INT iHotIndex = SendMessage(HDM_HITTEST, 0, (LPARAM)(&hdhti)); + if(iHotIndex >= 0) + { + HDITEM hditem; + hditem.mask = HDI_ORDER; + VERIFY(GetItem(iHotIndex, &hditem)); + iHotOrder = hditem.iOrder; + + CRect rectItem; + VERIFY(GetItemRect(iHotIndex, rectItem)); + if(hdhti.pt.x > rectItem.CenterPoint().x) + iHotOrder++; + + SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); + m_iDropResult = 0; + } + else + { + pt = point; + ClientToScreen(&pt); + + if(!(m_hDropTarget && m_rcDropTarget.PtInRect(pt))) + { + if(m_nDontDropCursor) + SetCursor(AfxGetApp()->LoadCursor(m_nDontDropCursor)); + else + SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO)); + + m_iDropResult = -1; + } + else + { + SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); + m_iDropResult = 1; + } + } + + if(iHotOrder == m_iHotOrder || iHotOrder == m_iHotOrder+1) + iHotOrder = -1; + + if(iHotOrder != m_iHotDivider) + OnSetHotDivider(FALSE, iHotOrder); + } + + return; + } + else if(GetStyle()&HDS_DRAGDROP) + { + INT iDragCX = GetSystemMetrics(SM_CXDRAG); + INT iDragCY = GetSystemMetrics(SM_CYDRAG); + CRect rectDrag( + m_ptClickPoint.x-iDragCX, m_ptClickPoint.y-iDragCY, + m_ptClickPoint.x+iDragCX, m_ptClickPoint.y+iDragCY + ); + + if(!rectDrag.PtInRect(point)) + { + NMHEADER nmhdr; + nmhdr.hdr.hwndFrom = m_hWnd; + nmhdr.hdr.idFrom = GetDlgCtrlID(); + nmhdr.hdr.code = HDN_BEGINDRAG; + nmhdr.iItem = m_iHotIndex; + nmhdr.iButton = 1; + nmhdr.pitem = &m_hdiHotItem; + + BOOL bBeginDrag = TRUE; + CWnd* pWnd = GetParent(); + if(pWnd != NULL) + bBeginDrag = pWnd->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmhdr)==FALSE ? TRUE:FALSE; + + if(bBeginDrag) + { + ASSERT(m_pDragWnd == NULL); + m_pDragWnd = new CFHDragWnd; + if(m_pDragWnd) + { + CRect rectItem; + VERIFY(GetItemRect(m_iHotIndex, rectItem)); + ClientToScreen(&rectItem); + + m_pDragWnd->Create(rectItem, this, m_iHotIndex, &m_hdiHotItem); + } + + BOOL bVisible = FALSE; + if(m_hDropTarget != NULL) + { + bVisible = ::GetWindowLong(m_hDropTarget, GWL_STYLE)&WS_VISIBLE ? TRUE:FALSE; + + HWND hParent = ::GetParent(m_hDropTarget); + if(hParent) + bVisible = ::GetWindowLong(hParent, GWL_STYLE)&WS_VISIBLE ? TRUE:FALSE; + } + + if(m_hDropTarget != NULL && bVisible) + VERIFY(::GetWindowRect(m_hDropTarget, m_rcDropTarget)); + else + m_rcDropTarget.SetRectEmpty(); + } + + SetCapture(); + m_bDragging = TRUE; + } + } + } + } +} + +void CFlatHeaderCtrl::OnCancelMode() +{ + CWnd::OnCancelMode(); + + if(m_bDragging) + { + m_nClickFlags = 0; + + if(m_pDragWnd != NULL) + { + m_pDragWnd->DestroyWindow(); + m_pDragWnd = NULL; + } + + if (GetCapture()->GetSafeHwnd() == GetSafeHwnd()) + ReleaseCapture(); + + m_bDragging = FALSE; + OnSetHotDivider(FALSE, -1); + + Invalidate(); + } +} + +int CFlatHeaderCtrl::GetHotColumn() +{ + return m_iHotOrder; +} + +int CFlatHeaderCtrl::GetHotIndex() +{ + return m_iHotIndex; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.h new file mode 100644 index 0000000..f43f05e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/FlatHeaderCtrl.h @@ -0,0 +1,279 @@ +//////////////////////////////////////////////////////////////////////////// +// File: CFlatHeaderCtrl.h +// Version: 1.0.4 +// +// Author: Maarten Hoeben +// E-mail: hoeben@nwn.com +// +// Specification of the CFlatHeaderCtrl and associated classes. +// +// This code may be used in compiled form in any way you desire. This +// file may be redistributed unmodified by any means PROVIDING it is +// not sold for profit without the authors written consent, and +// providing that this notice and the authors name and all copyright +// notices remains intact. +// +// An email letting me know how you are using it would be nice as well. +// +// This file is provided "as is" with no expressed or implied warranty. +// The author accepts no liability for any damage/loss of business that +// this product may cause. +// +//////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_FLATHEADERCTRL_H__2162BEB4_A882_11D2_B18A_B294B34D6940__INCLUDED_) +#define AFX_FLATHEADERCTRL_H__2162BEB4_A882_11D2_B18A_B294B34D6940__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// FlatHeaderCtrl.h : header file +// + +#include +#include + +#define FLATHEADER_TEXT_MAX 80 +#define FLATHEADER_TT_MAGIC -13111971 + +///////////////////////////////////////////////////////////////////////////// +// CFlatHeaderCtrl window + +class CFlatHeaderCtrl; +class CFHDragWnd; +class CFHDropWnd; + +#define FH_PROPERTY_SPACING 1 +#define FH_PROPERTY_ARROW 2 +#define FH_PROPERTY_STATICBORDER 3 +#define FH_PROPERTY_DONTDROPCURSOR 4 +#define FH_PROPERTY_DROPTARGET 5 +#define FH_PROPERTY_ENABLETOOLTIPS 6 + +#define HDF_EX_AUTOWIDTH 0x0001 +#define HDF_EX_INCLUDESORT 0x0002 +#define HDF_EX_FIXEDWIDTH 0x0004 +#define HDF_EX_TOOLTIP 0x0008 + +typedef struct _HDITEMEX +{ + UINT nStyle; + INT iMinWidth; + INT iMaxWidth; + CString strToolTip; + + _HDITEMEX() : nStyle(0), iMinWidth(0), iMaxWidth(-1) {}; + +} HDITEMEX, FAR* LPHDITEMEX; + +class CFlatHeaderCtrl : public CHeaderCtrl +{ + friend class CFHDragWnd; + + DECLARE_DYNCREATE(CFlatHeaderCtrl) + +// Construction +public: + CFlatHeaderCtrl(); + +// Attributes +public: + BOOL ModifyProperty(WPARAM wParam, LPARAM lParam); + + BOOL GetItemEx(INT iPos, HDITEMEX* phditemex) const; + BOOL SetItemEx(INT iPos, HDITEMEX* phditemex); + + INT GetItemWidth(LPHDITEM lphdi, BOOL bIncludeSort = FALSE); + + void SetSortColumn(INT iPos, BOOL bSortAscending); + INT GetSortColumn(BOOL* pbSortAscending = NULL); + + INT GetDropResult(); + +// Overrides +public: + int GetHotIndex(); + int GetHotColumn(); + TCHAR m_szHotItemText[FLATHEADER_TEXT_MAX]; + + virtual ~CFlatHeaderCtrl(); + + virtual void DrawItem(LPDRAWITEMSTRUCT); + virtual void DrawItem(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bSort, BOOL bSortAscending); + + virtual int OnToolHitTest(CPoint point, TOOLINFO* pTI) const; + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFlatHeaderCtrl) + //}}AFX_VIRTUAL + +// Implementation +protected: + BOOL m_bDoubleBuffer; + INT m_iSpacing; + SIZE m_sizeImage; + SIZE m_sizeArrow; + BOOL m_bStaticBorder; + UINT m_nDontDropCursor; + HWND m_hDropTarget; + CRect m_rcDropTarget; + INT m_iDropResult; + + INT m_iHotIndex; + INT m_iHotOrder; + BOOL m_bHotItemResizable; + HDHITTESTINFO m_hdhtiHotItem; + HDITEM m_hdiHotItem; +// TCHAR m_szHotItemText[FLATHEADER_TEXT_MAX]; + + BOOL m_bResizing; + + INT m_iHotDivider; + COLORREF m_crHotDivider; + CFHDropWnd* m_pDropWnd; + + BOOL m_bDragging; + CFHDragWnd* m_pDragWnd; + + UINT m_nClickFlags; + CPoint m_ptClickPoint; + + BOOL m_bSortAscending; + INT m_iSortColumn; + CArray m_arrayHdrItemEx; + + COLORREF m_cr3DHighLight; + COLORREF m_cr3DShadow; + COLORREF m_cr3DFace; + COLORREF m_crText; + + void DrawCtrl(CDC* pDC); + INT DrawImage(CDC* pDC, CRect rect, LPHDITEM hdi, BOOL bRight); + INT DrawBitmap(CDC* pDC, CRect rect, LPHDITEM hdi, CBitmap* pBitmap, BITMAP* pBitmapInfo, BOOL bRight); + INT DrawText (CDC* pDC, CRect rect, LPHDITEM lphdi); + INT DrawArrow(CDC* pDC, CRect rect, BOOL bSortAscending, BOOL bRight); + +// Generated message map functions +protected: + //{{AFX_MSG(CFlatHeaderCtrl) + afx_msg LRESULT OnInsertItem(WPARAM wparam, LPARAM lparam); + afx_msg LRESULT OnDeleteItem(WPARAM wparam, LPARAM lparam); + afx_msg LRESULT OnSetImageList(WPARAM wparam, LPARAM lparam); + afx_msg LRESULT OnSetHotDivider(WPARAM wparam, LPARAM lparam); + afx_msg LRESULT OnLayout(WPARAM wparam, LPARAM lparam); + afx_msg UINT OnNcHitTest(CPoint point); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnPaint(); + afx_msg void OnSysColorChange(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnCancelMode(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + BOOL OnToolTipNotify(UINT nId, NMHDR *pNMHDR, LRESULT *pResult); +}; + +///////////////////////////////////////////////////////////////////////////// +// CFHDragWnd window + +#define FHDRAGWND_CLASSNAME _T("MFCFHDragWnd") + +class CFHDragWnd : public CWnd +{ +// Construction +public: + CFHDragWnd(); + +// Attributes +public: + +// Operations +public: + +// Overrrides +protected: + // Drawing + virtual void OnDraw(CDC* pDC); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFHDragWnd) + protected: + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFHDragWnd(); + virtual BOOL Create(CRect rect, CFlatHeaderCtrl* pFlatHeaderCtrl, INT iItem, LPHDITEM lphdiItem); + +protected: + CFlatHeaderCtrl* m_pFlatHeaderCtrl; + INT m_iItem; + LPHDITEM m_lphdiItem; + + // Generated message map functions +protected: + //{{AFX_MSG(CFHDragWnd) + afx_msg void OnPaint(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +// CFHDropWnd window + +#define FHDROPWND_CLASSNAME _T("MFCFHDropWnd") + +class CFHDropWnd : public CWnd +{ +// Construction +public: + CFHDropWnd(COLORREF crColor); + +// Attributes +public: + +// Operations +public: + void SetWindowPos(INT x, INT y); + +// Overrrides +protected: + // Drawing + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFHDropWnd) + protected: + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CFHDropWnd(); + virtual BOOL Create(INT iHeight); + +protected: + CBrush m_brush; + CRgn m_rgn; + + INT m_iHeight; + + // Generated message map functions +protected: + //{{AFX_MSG(CFHDropWnd) + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FLATHEADERCTRL_H__2162BEB4_A882_11D2_B18A_B294B34D6940__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.cpp new file mode 100644 index 0000000..2b0a872 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.cpp @@ -0,0 +1,395 @@ +// GZK.cpp: implementation of the GZK class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" + + +#include "GZK.h" + +#include "c:\data\projects\crypto31\config.h" +#include "c:\data\projects\crypto31\twofish.h" +#include "c:\data\projects\crypto31\base64.h" +#include "c:\data\projects\crypto31\cbc.h" +#include "c:\data\projects\crypto31\hex.h" + + + + + +USING_NAMESPACE(CryptoPP) + + + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +//this is an index into the key table. The key used will be the 16 bytes +//that can be found starting at the following index location in the key table +#define PRODUCT_UNIQUE_KEY_VALUE 235 + + + +BYTE GZ_KEY_TABLE[]={ + 187,71,225,207,126,247,40,49,245,248,41,95,30,172,209,92, + 251,217,54,171,87,33,139,104,51,154,59,77,234,128,157,33, + 44,189,42,240,43,191,100,190,134,158,53,70,74,133,43,163, + 118,13,181,228,137,246,201,106,241,18,187,16,205,83,181,40, + 39,237,51,11,56,132,87,36,153,151,179,142,28,11,170,241, + 80,113,176,121,56,163,149,150,191,169,237,145,7,115,245,131, + 103,232,19,249,190,241,6,48,51,149,89,189,53,208,34,51, + 235,201,39,149,103,137,140,183,74,69,106,40,22,200,111,173, + 2,67,130,43,176,142,218,184,132,219,215,80,80,4,1,44, + 172,81,50,146,21,148,53,99,83,4,157,61,204,199,12,15, + 160,145,26,226,16,228,127,208,43,36,78,250,39,2,128,69, + 136,40,109,159,177,113,134,181,136,224,154,150,211,117,185,220, + 30,176,248,143,42,52,180,194,156,244,105,3,252,172,242,143, + 180,41,215,27,18,221,148,143,242,181,213,173,49,121,82,38, + 216,73,206,46,240,240,72,176,223,6,167,249,14,157,185,114, + 179,55,141,89,57,184,12,14,195,94,141,117,13,74,183,108, + 238,214,187,168,186,235,84,148,21,195,81,78,26,95,192,120, + 110,208,98,248,1,117,159,251,7,111,202,108,29,59,125,80, + 73,176,108,212,123,217,241,131,244,31,79,34,49,91,6,253, + 239,214,174,240,125,210,17,14,158,68,125,193,208,3,128,61, + 69,213,186,179,126,240,80,121,216,25,109,161,36,50,118,208, + 239,226,107,27,225,246,171,36,167,66,52,141,160,244,128,179, + 132,98,53,227,20,195,34,42,84,2,164,45,246,92,15,187, + 222,68,188,201,239,131,227,228,38,135,41,96,17,235,202,81, + 85,137,239,34,13,185,153,188,185,123,55,113,46,169,82,122, + 78,177,69,188,106,23,31,73,182,159,127,123,101,255,86,83,0,0,0,0}; + + + + + + + + + +//Constructor, the key sets here +GZK::GZK() +{ + Key = new BYTE[16];//= GZ_KEY_TABLE; + memcpy(Key,GZ_KEY_TABLE+PRODUCT_UNIQUE_KEY_VALUE,16); + +} + + +GZK::~GZK() +{ + //destructor: since the decryption is done on an object passed in there is no wiping necessary? + delete Key; +} + + + +void GZK::GZEncrypt(CString *src,bool hex) +{ + char* instr; + unsigned int c=src->GetLength(); + instr=new char[c+1]; + lstrcpy(instr,*src); + char* outstr; + char* retstr; + TwofishEncryption* e; + CBCPaddedEncryptor* enc; + e=new TwofishEncryption(Key); + enc=new CBCPaddedEncryptor(*e,Key); + + enc->Put((byte *)instr, c); + enc->Close(); + + c = enc->MaxRetrieveable(); + outstr = new char[c+1]; + enc->Get((byte *)outstr, c); + outstr[c] = 0; + + if(hex==false) + { + Base64Encoder e64; + e64.Put((byte*)outstr,c); + e64.Close(); + c=e64.MaxRetrieveable(); + retstr = new char[c+1]; + e64.Get((byte *)retstr,c); + retstr[c]=0; + retstr[c-1]=0; + //b64str[c-2]=0; + //b64str[c-3]=0; + src->Format("%s",retstr); + } + else + { + HexEncoder he; + he.Put((byte*)outstr,c); + he.Close(); + c=he.MaxRetrieveable(); + retstr = new char[c+1]; + he.Get((byte *)retstr,c); + retstr[c]=0; + //retstr[c-1]=0; + //b64str[c-2]=0; + //b64str[c-3]=0; + src->Format("%s",retstr); + + } + delete instr; + delete e; + delete enc; + delete outstr; + delete retstr; + +} + +void GZK::GZDecrypt(CString *src, bool hex) +{ char* instr; + unsigned int c=src->GetLength(); + instr=new char[c+1]; + lstrcpy(instr,*src); + char* outstr; + char* str; + TwofishDecryption* d ; + CBCPaddedDecryptor* dec; + d=new TwofishDecryption(Key); + dec=new CBCPaddedDecryptor(*d,Key); + + + + if(hex==false) + { + Base64Decoder d64; + d64.Put((byte*)instr,c); + d64.Close(); + c=d64.MaxRetrieveable(); + str = new char[c]; + d64.Get((byte *)str,c); + } + else + { + HexDecoder hd; + hd.Put((byte*)instr,c); + hd.Close(); + c=hd.MaxRetrieveable(); + str = new char[c]; + hd.Get((byte *)str,c); + + } + + + + + dec->Put((byte *)str, c); + dec->Close(); + c =dec->MaxRetrieveable(); + outstr = new char[c+1]; + dec->Get((byte *)outstr, c); + outstr[c] = 0; + + + src->Format("%s",outstr); + + //wipe the memory contents before it goes out of scope + memset(outstr,'\0',c); + + delete d; + delete dec; + delete str; + delete outstr; + delete instr; +} + + + +//************* take an encrypted string and +//************* display a decrypted version in a messagebox +//display is a smokescreen, if less than 128 will not display message +void GZK::gzMsgBox(char *cryptmsg,int display) +{ + + CString msg; + msg.Format("%s",cryptmsg); + GZDecrypt(&msg,false); + msg.Replace("~","\r\n"); + if(displayGetLength(); + + unsigned char *str = new unsigned char[x]; + + + lstrcpy((char*)str, *src); + + unsigned long hash = 5381; + int c; + while (c = *str++) + hash = ((hash << 5) + hash) + c; // hash * 33 + c + + src->Format("%u",hash); + + //_CrtDumpMemoryLeaks(); +} +*/ +//******************* make a djb2 hash ********************* +//takes a string of at most 200 bytes!!! +//and changes it to the hash of the original string. +//http://www.cs.yorku.ca/~oz/hash.html +void GZK::GZHash(CString* src) +{ +ASSERT(src->GetLength()< 190);//we can always increase it later +//note:hash is performed on user first/last name and company name + //company is max 75, user first and last is max 100+11others so + //200 is assumed to be a very safe fixed amount +//this function should be modified as before, but if less than +//a certain amount then pads to avoid overwriting other memory. + unsigned char *str = new unsigned char[200]; +unsigned char* placeholder=str; + + lstrcpy((char*)str, *src); + + unsigned long hash = 5381; + int c; + while (c = *str++) + hash = ((hash << 5) + hash) + c; // hash * 33 + c + + src->Format("%u",hash); + delete placeholder; + + //_CrtDumpMemoryLeaks(); +} + + +//takes a pointer to two cstring objects, one contains the encrypted key +//the other the plaintext client name +//returns: a string of random characters whose total count of characters equals the +//feature code enabled. On failure returns a random string of characters of a count that +//is not equal to a known feature code. +//================== + +//decrypts the key and gets a string formatted like this: +//Hash of clients name---->2345345345345,255<--feature code, one byte +//separates the feature code +//from the hash of the clients name, +//hashes the clients name passed in, +//compares the hash from key with the clients name hash +//if hash ok then starts a loop from 1 to x where +//x = the feature code byte value. Inserts a random +//character into the keytag string each loop + +void GZK::ValidateKey(CString *keytag,CString* custname,bool hex) +{ + CString hash,features,hash2; + int comma; + //decrypt the key + GZDecrypt(keytag,hex); + + //split the key + hash=keytag->SpanExcluding(","); + comma=keytag->ReverseFind(','); + features=keytag->Right(keytag->GetLength()-comma-1); + comma=atoi(features.GetBuffer(999)); + + hash2.Format("%s",*custname); + GZHash(&hash2); + if(hash2==hash)//ok key + { + hex=false;//smoke + custname->Format("%s","sadifjaskdfi");//and mirrors + hash=""; + for(int x=0;xFormat("%s","ibmisdlmbir");//and mirrors + hash=""; + for(int x=0;xFormat("%s",hash); + + +} + +CString GZK::InLineDecrypt(char *str) +{ + + CString text=str; + GZDecrypt(&text,false);//always b64 for inline + + + return text; +} + + +//set a unique offset value to work with +//this avoids using the built in key for uses +//where you don't want exposure (known plain and cypher for example) +void GZK::GZSetUniqueKey(int nOffset) +{ + ASSERT(nOffset<400); +memcpy(Key,GZ_KEY_TABLE+nOffset,16); + +} + + +//encode a passed memory block into b64 text +//need this for saving memory blocks to database +//as text items (i.e. printer DEVMODE structure) +CString GZK::EncodeB64(char *input, int size) +{ + + + CString retString; + unsigned int c=size; + char* retstr; + + Base64Encoder e64; + e64.Put((byte*)input,c); + e64.Close(); + c=e64.MaxRetrieveable(); + retstr = new char[c+1]; + e64.Get((byte *)retstr,c); + retstr[c]=0; + retstr[c-1]=0; + + retString.Format("%s",retstr); + delete retstr; + return retString; +} + +void GZK::DecodeB64(CString* input, char* retblock) +{ + + char* instr; + unsigned int c=input->GetLength(); + instr=new char[c+1]; + lstrcpy(instr,*input); + + Base64Decoder d64; + d64.Put((byte*)instr,c); + d64.Close(); + c=d64.MaxRetrieveable(); + d64.Get((byte *)retblock,c); + delete instr; + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.h new file mode 100644 index 0000000..21dee35 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZK.h @@ -0,0 +1,62 @@ +// GZK.h: interface for the GZK class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_GZK_H__5EE92AC5_D7E8_11D3_964F_00C0F02C4B69__INCLUDED_) +#define AFX_GZK_H__5EE92AC5_D7E8_11D3_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + + +/* +#define GZ_KEY2 {44,189,42,240,43,191,100,190,134,158,53,70,74,133,43,163} +#define GZ_KEY3 {118,13,181,228,137,246,201,106,241,18,187,16,205,83,181,40} +#define GZ_KEY4 {39,237,51,11,56,132,87,36,153,151,179,142,28,11,170,241} +#define GZ_KEY5 {80,113,176,121,56,163,149,150,191,169,237,145,7,115,245,131} +#define GZ_KEY6 {103,232,19,249,190,241,6,48,51,149,89,189,53,208,34,51} +#define GZ_KEY7 {235,201,39,149,103,137,140,183,74,69,106,40,22,200,111,173} +#define GZ_KEY8 {2,67,130,43,176,142,218,184,132,219,215,80,80,4,1,44} +#define GZ_KEY9 {172,81,50,146,21,148,53,99,83,4,157,61,204,199,12,15} +#define GZ_KEY10 {160,145,26,226,16,228,127,208,43,36,78,250,39,2,128,69} +#define GZ_KEY11 {136,40,109,159,177,113,134,181,136,224,154,150,211,117,185,220} +#define GZ_KEY12 {30,176,248,143,42,52,180,194,156,244,105,3,252,172,242,143} +#define GZ_KEY13 {180,41,215,27,18,221,148,143,242,181,213,173,49,121,82,38} +#define GZ_KEY14 {216,73,206,46,240,240,72,176,223,6,167,249,14,157,185,114} +#define GZ_KEY15 {179,55,141,89,57,184,12,14,195,94,141,117,13,74,183,108} +#define GZ_KEY16 {238,214,187,168,186,235,84,148,21,195,81,78,26,95,192,120} +#define GZ_KEY17 {110,208,98,248,1,117,159,251,7,111,202,108,29,59,125,80} +#define GZ_KEY18 {73,176,108,212,123,217,241,131,244,31,79,34,49,91,6,253} +#define GZ_KEY19 {239,214,174,240,125,210,17,14,158,68,125,193,208,3,128,61} +#define GZ_KEY20 {69,213,186,179,126,240,80,121,216,25,109,161,36,50,118,208} +#define GZ_KEY21 {239,226,107,27,225,246,171,36,167,66,52,141,160,244,128,179} +#define GZ_KEY22 {132,98,53,227,20,195,34,42,84,2,164,45,246,92,15,187} +#define GZ_KEY23 {222,68,188,201,239,131,227,228,38,135,41,96,17,235,202,81} +#define GZ_KEY24 {85,137,239,34,13,185,153,188,185,123,55,113,46,169,82,122} +#define GZ_KEY25 {78,177,69,188,106,23,31,73,182,159,127,123,101,255,86,83} + +*/ + + +class GZK +{ +public: + void DecodeB64(CString* input, char* retblock); + CString EncodeB64(char * input,int size); + void GZSetUniqueKey(int nOffset); + CString InLineDecrypt(char* str); + void ValidateKey(CString *keytag,CString* custname, bool hex); + void GZHash(CString *src); + void gzMsgBox(char * cryptmsg,int display); + void GZDecrypt(CString *src, bool hex); + void GZEncrypt(CString * src, bool hex); + GZK(); + virtual ~GZK(); +BYTE* Key; +private: + +}; + +#endif // !defined(AFX_GZK_H__5EE92AC5_D7E8_11D3_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.cpp new file mode 100644 index 0000000..b15737e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.cpp @@ -0,0 +1,2220 @@ +// GZRset.cpp: implementation of the GZRset class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "sp.h" +#include "GZRset.h" +#include +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +GZRset::GZRset(CString strErr) +{ +#ifdef _RSTRACE_ + log=new CLogTrace(); + log->SetFileName("dblog.txt"); + log->m_strAppName="AyaNova"; + log->OnStartup(true,true); + + //log->WriteLine(">>>>Opening: %s\r\n",strErr); +#endif + + m_bUseTransactions=false; + m_bInUse=true; + m_bPrinting=false; + m_bRSPRINT=false; + CString copyright="AyaNova Classic Edition Copyright 2000-2004 Ground Zero Tech-Works"; + + _ASSERT(!strErr.IsEmpty()); + //set error message so that if various _ASSERTions fail + //the user can be alerted with something meaningful to write + //down and in turn tell us during a tech support call. + //because this class will be used all over the place + m_strErrMsg=strErr; + m_bForwardOnly=false; + //by default not an exclusive connection + m_bExclusiveConnection=false; + //set to null as a default + m_pRecordSet=NULL; + + try{ + + // instantiate the recordset defined in the header + m_pRecordSet.CreateInstance(__uuidof(Recordset)); + + //m_pRecordSet->PutCacheSize(500); + + m_pRecordSet->CursorLocation=adUseServer; + m_bOpen = false;// signify no recordset + m_strLastError.Empty(); + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + m_strLastError.Format("%s",(LPCTSTR) bstrDescription); + if(m_pRecordSet==NULL) + { + + AfxMessageBox( + "Problem: It appears that you do not have the required \r\n" + "Microsoft Data Access Components installed.\r\n\r\n" + + "They should have been installed automatically with AyaNova\r\n" + "but are not present. Please contact tech support at:\r\n" + "support@ayanova.com or ... \r\n\r\n" + + "The following page on our website gives instructions on installing\r\n" + "the missing database driver files:\r\n" + "http://www.ayanova.com/mdac.htm"); + + if(AfxMessageBox("Do you want to be taken to this page on our website now?\r\n(requires internet ability)",MB_YESNO)==IDYES) + HINSTANCE h = ShellExecute(NULL, "open", "http://www.ayanova.com/mdac.htm", NULL, NULL, SW_SHOWNORMAL); + + } + else + AfxMessageBox(cstrErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + + } + +} + + + +GZRset::GZRset(CString strErr, bool bUseClientCursor) +{ + m_bUseTransactions=false; +#ifdef _RSTRACE_ + log=new CLogTrace(); + log->SetFileName("dblog.txt"); + log->m_strAppName="AyaNova"; + log->OnStartup(true,true); + //log->WriteLine(">>>>Opening: %s\r\n",strErr); +#endif + m_bInUse=true; + + + +#ifdef _WTF_ + + //AfxMessageBox(strErr); +#endif + _ASSERT(!strErr.IsEmpty()); + //set error message so that if various _ASSERTions fail + //the user can be alerted with something meaningful to write + //down and in turn tell us during a tech support call. + //because this class will be used all over the place + m_strErrMsg=strErr; + + // instantiate the recordset defined in the header + m_pRecordSet.CreateInstance(__uuidof(Recordset)); + //changed this July 1st for performance, + //not sure why it was client before + if(bUseClientCursor) + m_pRecordSet->CursorLocation=adUseClient; + else + m_pRecordSet->CursorLocation=adUseServer; + m_bOpen = false;// signify no recordset + + m_strLastError.Empty(); + +} + +GZRset::~GZRset() +{ + + +#ifdef _RSTRACE_ + //log->WriteLine("CLOSING: %s<<<<*\r\n",m_strErrMsg); + delete log; +#endif + + + if(m_pRecordSet->GetState()==adStateOpen) + m_pRecordSet->Close(); + + //releases on it's own despite this and causes error + //lesson: don't release unless you call addref first + //m_pRecordSet->Release(); + +} + + + +_RecordsetPtr GZRset::RecordSetPointer() +{ + return m_pRecordSet; +} +/* +bool GZRset::Open() +{ + + AfxMessageBox("OBSOLETE:\r\nbool GZRset::Open()"); + //for confirming if recordset is open or not. + return m_bOpen; +} +*/ + +/* +//Open forward only +bool GZRset::OpenForwardOnly(CString strQuery) +{ + + + AfxMessageBox("OBSOLETE:\r\nbool GZRset::OpenForwardOnly(CString strQuery)"); + m_bForwardOnly=true; + _ASSERT(!strQuery.IsEmpty()); + + _ASSERT(!m_strConnect.IsEmpty()); + + try + { + //if the recordset is already open, close it first. + //because open is also requery + if(m_bOpen) + { + m_pRecordSet->Close(); + + m_bOpen=false; + } + + + //no records at this point + m_bNoRecords=true; + //convert query to a variant + _variant_t vQuery(strQuery); + + //convert connection string to a binary string + _bstr_t bstrConn(m_strConnect); + + //open the forward only recordset based on the passed query + m_pRecordSet->Open(vQuery, bstrConn, adOpenForwardOnly, adLockOptimistic, adCmdUnknown); + + //check for empty recordset + if (m_pRecordSet->GetadoEOF()) + m_bNoRecords = true;// no records found + else + m_bNoRecords = false;//there are records + + //open must be true or an exception would have happened before now + + m_bOpen=true; + } + + + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("at: OLD OpenForwardOnly\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,strQuery); + m_strLastError.Format("%s",(LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + + } + + + return m_bOpen; + +} + + +*/ + +//QUERY: replacement for openforwardonly +//December 7th 2000 +bool GZRset::Query(CString strQuery) +{ + + #ifdef _RSTRACE_ + //don't log nulltable queries + log->WriteLine("Query: %s\r\n",strQuery); + #endif + m_strLastQuery=strQuery; + m_bForwardOnly=true; + _ASSERT(!strQuery.IsEmpty()); + + _ASSERT(!m_strConnect.IsEmpty()); +// long cs=m_pRecordSet->GetCacheSize(); + try + { + //if the recordset is already open, close it first. + //because open is also requery + if(m_bOpen && m_bExclusiveConnection==false) + { + //sometimes, the recordset is actually + //closed even though we don't know it + //this is a 3am "I don't ***** understand why, but this fixes it" Hack + if(m_pRecordSet->GetState()==adStateOpen) + m_pRecordSet->Close(); + m_pRecordSet->CursorLocation=adUseServer; + if(m_bRSPRINT) + m_pRecordSet->CursorLocation=adUseClient; + m_bOpen=false; + } + /*EXCLUSIVE should mean this is no longer necessary + //exclusivity is set in the pool now by GoExclusive() + if(m_bIsClosed)//was it closed + { + m_strConnect=m_strLiveConnectString; + if(m_bExclusiveConnection) + m_strConnect=m_strLiveConnectStringExclusive; + m_bIsClosed=false; + + + } + */ + + //no records at this point + m_bNoRecords=true; + + + //convert query to a variant + _variant_t vQuery(strQuery); + + //convert connection string to a binary string + _bstr_t bstrConn(m_strConnect); + + //open the forward only recordset based on the passed query + //m_pRecordSet->Open(vQuery, bstrConn, adOpenForwardOnly, adLockOptimistic, adCmdUnknown); + + + m_pRecordSet->Open(vQuery, _variant_t((IDispatch *)pTheConnection,true), adOpenForwardOnly, adLockOptimistic, adCmdUnknown); + + + + //check for empty recordset + m_bNoRecords = false;//there are records + if (m_pRecordSet->GetadoEOF()) + m_bNoRecords = true;// no records found + + + + //open must be true or an exception would have happened before now + + m_bOpen=true; + //Added just now while swilling wine and + //eating pizza + m_bInUse=true; + } + + + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,strQuery); + m_strLastError.Format("%s",(LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + + } + + + return m_bOpen; + +} + + + +//QUERY: replacement for openforwardonly +//December 7th 2000 +bool GZRset::QueryReadOnly(CString strQuery) +{ + + #ifdef _RSTRACE_ + //don't log nulltable queries + log->WriteLine("Query: %s\r\n",strQuery); + #endif + m_strLastQuery=strQuery; + m_bForwardOnly=true; + _ASSERT(!strQuery.IsEmpty()); + + _ASSERT(!m_strConnect.IsEmpty()); + //long cs=m_pRecordSet->GetCacheSize(); + try + { + //if the recordset is already open, close it first. + //because open is also requery + if(m_bOpen) + { + //sometimes, the recordset is actually + //closed even though we don't know it + //this is a 3am - "I don't understand + //why, but this fixes it" Hack + if(m_pRecordSet->GetState()==adStateOpen) + m_pRecordSet->Close(); + m_pRecordSet->CursorLocation=adUseServer; + if(m_bRSPRINT) + m_pRecordSet->CursorLocation=adUseClient; + m_bOpen=false; + } + + /*//SET IN rspool go exclusive function now + if(m_bIsClosed)//was it closed + { + m_strConnect=m_strLiveConnectString; + if(m_bExclusiveConnection) + m_strConnect=m_strLiveConnectStringExclusive; + m_bIsClosed=false; + + + } + + */ + //no records at this point + m_bNoRecords=true; + + + //convert query to a variant + _variant_t vQuery(strQuery); + + //convert connection string to a binary string + _bstr_t bstrConn(m_strConnect); + + //open the forward only recordset based on the passed query + //THIS IS THE ONLY DIFFERENCE IN A READ ONLY RECORDSET + //m_pRecordSet->Open(vQuery, bstrConn, adOpenForwardOnly, adLockReadOnly, adCmdUnknown); + + //TEST TEST TEST TEST adLockReadOnly adLockOptimistic adCmdUnknown adCmdText + m_pRecordSet->Open(vQuery, _variant_t((IDispatch *)pTheConnection,true), + adOpenForwardOnly,adLockReadOnly , adCmdText ); + + + //check for empty recordset + m_bNoRecords = false;//there are records + if (m_pRecordSet->GetadoEOF()) + m_bNoRecords = true;// no records found + + + + //open must be true or an exception would have happened before now + + m_bOpen=true; + //Added just now while swilling wine and + //eating pizza + m_bInUse=true; + } + + + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,strQuery); + m_strLastError.Format("%s",(LPCTSTR) bstrDescription); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + + } + + + return m_bOpen; + +} + + + + +/* +//Open dynaset +bool GZRset::Open(CString strQuery) +{ + + AfxMessageBox("OBSOLETE:\r\nbool GZRset::Open(CString strQuery)"); + m_bForwardOnly=false; + _ASSERT(!strQuery.IsEmpty()); + + _ASSERT(!m_strConnect.IsEmpty()); + + try + { + //if the recordset is already open, close it first. + //because open is also requery + if(m_bOpen) + { + m_pRecordSet->Close(); + + m_bOpen=false; + } + + + if(m_bIsClosed)//was it closed + { + if(m_bExclusiveConnection) + m_strConnect=m_strLiveConnectStringExclusive; + else + m_strConnect=m_strLiveConnectString; + + m_bIsClosed=false; + + } + + //no records at this point + m_bNoRecords=true; + //convert query to a variant + _variant_t vQuery(strQuery); + + //convert connection string to a binary string + _bstr_t bstrConn(m_strConnect); + + //open the recordset based on the passed query + m_pRecordSet->Open(vQuery, bstrConn, adOpenDynamic, adLockOptimistic, adCmdUnknown); + + //check for empty recordset + if (m_pRecordSet->GetadoEOF()) + m_bNoRecords = true;// no records found + else + m_bNoRecords = false;//there are records + + //open must be true or an exception would have happened before now + //or so the theory goes + m_bOpen=true; + } + + + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + + } + + + return m_bOpen; + +} + + +*/ + + + + + + + +void GZRset::SetConnect(CString str) +{ + + _ASSERT(!str.IsEmpty()); + + //set connection string + m_strConnect=str; + + +} + + +//returns lValue records +//-1 on error. CAUTION:moves bookmark +//Modified to do it manually as the cursor +//type in use does not support record count +long GZRset::FetchRecordCount() +{ + + m_lRecordCount=0; + if(MoveFirst()) + { + do{ + m_lRecordCount++; + }while(MoveForward()); + m_pRecordSet->MoveFirst(); + + } + return m_lRecordCount; + + +} + +//returns all text type fields in record as one string +//ignores non text field types +//Added v1.9.4.6 09-May-2005 to fix problem with indexing +bool GZRset::FetchAllTextFieldsAsOneString( CString *strValue) +{ + //Since this function appends instead of setting + //must ensure passed in string is empty as expected + strValue->Empty(); + try{ + _variant_t vItem; + long lFieldCount=m_pRecordSet->GetFields()->Count; + for(long x=0;xGetCollect(x); + + if ( vItem.vt==VT_BSTR) + { + *strValue+=vItem.bstrVal; + *strValue+=" "; + } + + } + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At FetchAllTextFieldsAsOneString:\r\n%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + + +bool GZRset::FetchAnyFieldAsString(CString fld, CString *strValue) +{ + //takes a field name and sets the passed cstring contents + //to that field in the current record + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + + if (vItem.vt == VT_NULL) + strValue->Empty(); + else if(vItem.vt==VT_BOOL) + { + if(vItem.boolVal==-1) + *strValue="1"; + else + *strValue="0"; + } + else + { + vItem.ChangeType(VT_BSTR,NULL); + *strValue=vItem.bstrVal; + } + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At CString FetchField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + + + + + + +bool GZRset::FetchField(CString fld, CString *strValue) +{ + //takes a field name and sets the passed cstring contents + //to that field in the current record + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + + + + + //to catch those little !@#$ups! + _ASSERT(vItem.vt==VT_BSTR || vItem.vt==VT_NULL); + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + strValue->Empty(); + else + *strValue=vItem.bstrVal; + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At CString FetchField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + + + + + +bool GZRset::FetchField(CString fld, bool *bValue) +{ + //same as string field but for a bool item instead + //_ASSERTs on invalid field name or type + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + //to catch those little !@#$ups! + _ASSERT(vItem.vt==VT_BOOL || vItem.vt==VT_NULL); + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + { + *bValue=false; + return true; + } + + *bValue=(bool)vItem; + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + // cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At BOOL FetchField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + + return true; +} + + + + +//************************************************ +bool GZRset::FetchField(CString fld, long *lValue) +{ + //same as string field but for a long variable instead + //_ASSERTs on invalid field name or type + //same as string field but for a bool item instead + //_ASSERTs on invalid field name or type + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + //to catch those little !@#$ups! + _ASSERT(vItem.vt==VT_I4 || vItem.vt==VT_NULL); + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + { + *lValue=0; + return true; + } + + *lValue=vItem.lVal; + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At LONG FetchField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + + + + +//************************************************ +bool GZRset::FetchField(CString fld, float *fValue) +{ + //same as string field but for a long variable instead + //_ASSERTs on invalid field name or type + //same as string field but for a bool item instead + //_ASSERTs on invalid field name or type + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + //to catch those little !@#$ups! + _ASSERT(vItem.vt==VT_R4 || vItem.vt==VT_NULL); + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + { + *fValue=0; + return true; + } + + *fValue=vItem.fltVal; + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At Float FetchField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + +//******************************************** +bool GZRset::IsEmpty() +{ + + return m_bNoRecords; +} + + +bool GZRset::MoveFirst() +{ + //ASSERT(m_bForwardOnly==false); + if(m_bNoRecords==true || m_bOpen==false) return false; + + HRESULT hr; + hr=m_pRecordSet->MoveFirst(); + if(FAILED(hr)) return false; + return true; +} + +bool GZRset::MoveLast() +{ + if(m_bNoRecords==true || m_bOpen==false) return false; + + HRESULT hr; + hr=m_pRecordSet->MoveLast(); + if(FAILED(hr)) return false; + return true; +} + +bool GZRset::MoveForward() +{ + if(m_bNoRecords==true || m_bOpen==false) return false; + HRESULT hr; + try{ + hr=m_pRecordSet->MoveNext(); + if(FAILED(hr)) return false; + if(m_pRecordSet->GetadoEOF()) return false; + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("At MoveForward:\r\n%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + +bool GZRset::MoveBack() +{ + ASSERT(m_bForwardOnly==false); + + if(m_bNoRecords==true || m_bOpen==false) return false; + HRESULT hr; + hr=m_pRecordSet->MovePrevious(); + if(FAILED(hr)) return false; + if(m_pRecordSet->GetBOF()) return false; + return true; + +} + + + +//DATE AND TIME VERSION - Boo-ya! +bool GZRset::FetchField(CString fld, COleDateTime *dtValue) +{ + + //Fetch a date time field + //_ASSERTs on invalid field name or type + //same as string field but for a bool item instead + //_ASSERTs on invalid field name or type + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + //to catch those little !@#$ups! + _ASSERT(vItem.vt==VT_DATE || vItem.vt==VT_NULL); + + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + { + return false; + } + + *dtValue=vItem.date; + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At DT fetchfield:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + + + + +//CURRENCY VERSION - Boo-ya! +bool GZRset::FetchField(CString fld, COleCurrency *crValue) +{ + + //Fetch a date time field + //_ASSERTs on invalid field name or type + //same as string field but for a bool item instead + //_ASSERTs on invalid field name or type + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + //to catch those little !@#$ups! + _ASSERT(vItem.vt==VT_CY || vItem.vt==VT_NULL); + + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + { + return false; + } + + *crValue=vItem.cyVal; + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At $$ fetchfield:\r\n%s: %s,\r\n%s\r\nField:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + +//************************************************ +//Fetch unsigned char 0-255 BYTE value in database +bool GZRset::FetchField(CString fld, unsigned char *byteValue) +{ + + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + //to catch those little !@#$ups! + //_ASSERT(vItem.vt==VT_UI1 || vItem.vt==VT_NULL); + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + { + *byteValue=0; + return true; + } + + *byteValue=vItem.bVal; + + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At BYTE FetchField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + //Added 08/03/2001 to hide errors on update + if(!m_bSupressErrors) + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + + + +//***************************************************8 +//byte value 0-255 +bool GZRset::UpdateField(CString fld, unsigned char* byteValue) +{ + try + { + _variant_t vItem(*byteValue); + _bstr_t bsfld(fld); + m_pRecordSet->Fields->GetItem(bsfld)->Value=vItem; + + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At BYTE UpdateField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + + + return true; +} + + + + + + + + + + + +//***************************************************8 +bool GZRset::UpdateField(CString fld, long* lValue) +{ + try + { + _variant_t vItem(*lValue); + _bstr_t bsfld(fld); + m_pRecordSet->Fields->GetItem(bsfld)->Value=vItem; + + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At LONG UpdateField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + + + return true; +} + +//***************************************************8 +//FLOAT or SINGLE type + +bool GZRset::UpdateField(CString fld, float* fValue) +{ + try + { + _variant_t vItem(*fValue); + _bstr_t bsfld(fld); + m_pRecordSet->Fields->GetItem(bsfld)->Value=vItem; + + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At float updatefield:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + + + return true; +} + +//********************************************************* +bool GZRset::UpdateField(CString fld, bool* bValue) +{ + try + { + _variant_t vItem(*bValue); + _bstr_t bsfld(fld); + m_pRecordSet->Fields->GetItem(bsfld)->Value=vItem; + + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At bool updatefield:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + +bool GZRset::UpdateField(CString fld, CString *strValue) +{ + try + { + _variant_t vItem(*strValue); + if(strValue->IsEmpty()) + vItem.vt=VT_NULL; + _bstr_t bsfld(fld); + m_pRecordSet->Fields->GetItem(bsfld)->Value=vItem; + + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + // cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At CString UpdateField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; + +} + + +//******************************************************** +bool GZRset::UpdateField(CString fld, COleDateTime *dtValue) +{ + + try + { + _variant_t vItem(*dtValue); + _bstr_t bsfld(fld); + m_pRecordSet->Fields->GetItem(bsfld)->Value=vItem; + + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At DT UpdateField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; + +} + + +//CURRENCY: +//******************************************************** +bool GZRset::UpdateField(CString fld, COleCurrency *crValue) +{ + + try + { + _variant_t vItem(*crValue); + _bstr_t bsfld(fld); + m_pRecordSet->Fields->GetItem(bsfld)->Value=vItem; + + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At $$ UpdateField:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; + +} + + +//*********************************************************** +bool GZRset::AddNewRecord() +{ + + try{m_pRecordSet->AddNew(vtMissing, vtMissing);} + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return true; +} + + + + + + + + + + + + +bool GZRset::SaveRecord() +{ + + + try{ + + + m_pRecordSet->Update(); + + + } + + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + } + return true; +} + + +//New close routine, no more stupid extra database calls +//booya! +//This function is really a refresh method +//used to ensure that data is completely updated +//before another query that requires it immediately following +bool GZRset::Close() +{ + ASSERT(!m_bSQLServer); + + try{ + + +//changed may 21 2001 moved inside of check + //IJetEnginePtr jet(__uuidof(JetEngine)); + //jet->RefreshCache(pTheConnection); + + if(m_pRecordSet->GetState()==adStateOpen) + { + + if(!m_bSQLServer) + { + IJetEnginePtr jet(__uuidof(JetEngine)); + jet->RefreshCache(pTheConnection); + } + m_pRecordSet->Close(); + + } + + m_bOpen=false; + m_bIsClosed=true; + m_bInUse=false; + } + + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + } + return true; +} + + +//returns last error message +//added 9/25/00 +//returns last exception error message +CString GZRset::GetLastError() +{ + return m_strLastError; +} + + + +//valid recordset? +bool GZRset::Valid() +{ + + if(m_pRecordSet==NULL) + return false; + else + return true; + +} + + + +//used to set a definable error message +//that will be displayed on any kind +//of recordset error when thrown +//this is set by each calling function +//so that the area where the error is occuring +//can be easily determined +void GZRset::SetErrorMsg(CString strError) +{ + m_strErrMsg=strError; +} + +void GZRset::Initialize(CString strError) +{ + + if(m_bInUse) + { + CString XX; + XX.Format("Error:Recordset\r\n %s\r\nIs trying to be taken over by\r\n" + "Recordset\r\n %s\r\nWhile still in use.",m_strErrMsg,strError); + AfxMessageBox(XX); + return; + } + else + m_bInUse=true; + m_strErrMsg=strError; +} + + + + + + + +//Execute an SQL statement independant of recordset +//supersedes Execute (dec 7 2000) +bool GZRset::Ex(CString strQuery) +{ + //TRACE(strQuery); +//#ifdef _DEBUG +// CString q; +// q.Format("Transactions are:%s\r\n%s",m_bUseTransactions?"ON":"OFF",strQuery); +// AfxMessageBox(q); +//#endif + + bool status=true; + //this function takes a sql statement and runs and execute + //query using a connection object. It returns true if successful + //False if not + + if(m_bExclusiveConnection) + m_strConnect=m_strLiveConnectStringExclusive; + else + m_strConnect=m_strLiveConnectString; + + try + { + + //convert the string to a bstr + _bstr_t strSQL(strQuery); + /* if(m_bUseTransactions) + pTheConnection->BeginTrans(); + //convert the string to a bstr + _bstr_t strSQL(strQuery); + pTheConnection->Execute(strSQL, NULL, adExecuteNoRecords); + if(m_bUseTransactions) + pTheConnection->CommitTrans(); +*/ + + if(m_bUseTransactions) + pTheConnection->BeginTrans(); + + pTheConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + if(m_bUseTransactions) + pTheConnection->CommitTrans(); + + + } + + catch (_com_error &e) + { + if(m_bUseTransactions) + pTheConnection->RollbackTrans(); + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("at EX standard:\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,strQuery); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return status; +} + + + + + + + + + +//Execute and set Identity return +//New version 12/7/2000 +bool GZRset::Ex(CString strQuery, long* lIdentity) +{ + bool status=true; + _variant_t vQuery; + + m_bForwardOnly=true; +//#ifdef _DEBUG +// CString q; +// q.Format("Transactions are:%s\r\n%s",m_bUseTransactions?"ON":"OFF",strQuery); +// AfxMessageBox(q); +//#endif + + try + { + + //if the recordset is already open, close it first. + //because open is also requery + if(m_bOpen) + { + m_pRecordSet->Close(); + + m_bOpen=false; + } + + if(m_bExclusiveConnection) + m_strConnect=m_strLiveConnectStringExclusive; + else + m_strConnect=m_strLiveConnectString; + + //RUN THE EXECUTE QUERY PART + + //convert the string to a bstr + _bstr_t strSQL(strQuery); + + //new method using already open connection + if(m_bUseTransactions) + pTheConnection->BeginTrans(); + + pTheConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + if(m_bUseTransactions) + pTheConnection->CommitTrans(); + //GET THE IDENTITY PART + vQuery="SELECT @@Identity;"; + m_pRecordSet->Open(vQuery, _variant_t((IDispatch *)pTheConnection,true), adOpenForwardOnly, adLockOptimistic, adCmdUnknown); + + //open must be true or an exception would have happened before now + m_bOpen=true; + + _variant_t vItem; + vItem = m_pRecordSet->Fields->GetItem( _variant_t( 0L ) )->Value; + //to catch those little !@#$ups! + _ASSERT(vItem.vt==VT_I4 || vItem.vt==VT_NULL); + + // clean out nasty nulls + if (vItem.vt == VT_NULL) + { + AfxMessageBox("Error at: GZRset::Execute Identity = NULL"); + *lIdentity=0; + return false; + } + + *lIdentity=vItem.lVal; + + + + } + + catch (_com_error &e) + { + if(m_bUseTransactions) + pTheConnection->RollbackTrans(); + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("at EX(identity)\r\n%s: %s,\r\n%s\r\nQuery:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,strQuery); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + + return status; +} + +//Added Dec 8th 2000 with new pooling class +//this is required as it's no longer kosher +//to set this in the constructor +bool GZRset::SetToPrint(bool bPrinting) +{ + + if(bPrinting) + { + m_pRecordSet->CursorLocation=adUseClient; + m_bPrinting=true; + } + else + { + m_pRecordSet->CursorLocation=adUseServer; + m_bPrinting=false; + } + return true; +} + +CString GZRset::GetRSInfo() +{ + CString strTemp; + strTemp.Format("RS#%i\r\nErr String ID:%s",m_nID,m_strErrMsg); + + return strTemp; + +} + + +//used to set the error message/id string of a recordset +//when it's re-used. +void GZRset::SetErrMsg(CString strErrorID) +{ +m_strErrMsg=strErrorID; + +} + + +//required because query based recordsets don't +//come across as memos and so crystal thinks +//they are regular text 255 char size only +//and truncates +CString GZRset::SetFieldToMemo(CString fld) +{ + + int x; + long lActualSize; + long lDefinedSize; + int nMySize; + CString strData; + _variant_t vItem; + _variant_t vData; + _variant_t vFld(fld); + long lCount=m_pRecordSet->Fields->GetCount(); + for(long lx=0;lxFields->GetItem(lx)->Type; + vItem=m_pRecordSet->Fields->GetItem(lx)->Name; + x = m_pRecordSet->Fields->GetItem(lx)->Type; + lActualSize=m_pRecordSet->Fields->GetItem(lx)->GetActualSize(); + lDefinedSize=m_pRecordSet->Fields->GetItem(lx)->GetDefinedSize(); + vData=m_pRecordSet->Fields->GetItem(lx)->GetUnderlyingValue(); + + + if(vItem==vFld) + { + strData=vData.bstrVal; + nMySize=strData.GetLength(); + break; + } + + + } + + + return strData; + + +} + + +//given a field name return an int that indicates what +//type it is +int GZRset::FetchFieldType(CString fld) +{ + //-1=unknown,0=text,1=long int,2=datetime,3=currency,4=float,5=bool; + int nType=-1; + //_ASSERTs on invalid field name + try{ + _variant_t vItem; + _bstr_t bsfld(fld); + vItem = m_pRecordSet->GetCollect(bsfld); + + switch(vItem.vt) + { + case (VT_BOOL): + nType=5; + break; + case (VT_BSTR): + nType=0; + break; + case (VT_I4): + nType=1; + break; + case (VT_CY): + nType=3; + break; + case (VT_DATE): + nType=2; + break; + case (VT_R4): + nType=4; + break; + default: + nType=-1; + break; + } + + return nType; + }//end try block + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + // cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + cstrErrMsg.Format("At FetchFieldType:\r\n%s: %s,\r\n%s\r\nField:%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription,fld); + AfxMessageBox(cstrErrMsg); + return -1; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return -1; + + } + + + return true; + +} + +//*******************USEFUL INFORMATION ******************* + +/* +//test of createable recordset and saving to disk +bool CAyabaseDlg::test() +{ + GZRset rs("test in memory",true); + _bstr_t bsName("TEST"); + _variant_t vt(_bstr_t("c:\\temp\\test.xml")); + _variant_t vtTEST(_bstr_t("mangoes, mangoes everywhere!")); + COleDateTime dtNow=COleDateTime::GetCurrentTime(); + _variant_t vtDate(dtNow); + + try{ + + + +_RecordsetPtr pRS; + pRS.CreateInstance( __uuidof(Recordset)); + pRS->CursorLocation = adUseClient; + pRS->CursorType = adOpenStatic; + pRS->LockType = adLockBatchOptimistic; + // append fields + pRS->Fields->Append(_bstr_t("charfield"), adVarChar, 99,adFldFixed); + pRS->Fields->Append(_bstr_t("boolfield"), adBoolean, 0,adFldFixed); + pRS->Fields->Append(_bstr_t("currencyfield"), adCurrency, 0,adFldFixed); + pRS->Fields->Append(_bstr_t("datefield"), adDate, 0,adFldFixed); + pRS->Open(vtMissing, vtMissing, adOpenStatic,adLockBatchOptimistic,-1); + pRS->AddNew(vtMissing, vtMissing); + pRS->Fields->Item["charfield"]->Value = vtTEST; + pRS->Fields->Item["datefield"]->Value = vtDate; + + pRS->Update(); + pRS->Save(vt,adPersistXML); + + + + + + + + + //rs.RecordSetPointer()->Fields->Append(bsName,adVarChar,25,adFldUnspecified,vt); + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("at in created rset\r\n: %s,\r\n%s\r\n", e.ErrorMessage(), (LPCTSTR) bstrDescription); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + AfxMessageBox("Created rset - unhandled exception"); + //PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + //rs.RecordSetPointer()->Fields->"TEST",adVarChar,20 + return true; + + +} +*/ +//************************************************************************* diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.h new file mode 100644 index 0000000..2cfa04a --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRset.h @@ -0,0 +1,135 @@ +// GZRset.h: interface for the CGZRset class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_GZRSET_H__31F5EB01_0F99_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_GZRSET_H__31F5EB01_0F99_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +//NOTE: Un comment this to log database calls to disk + + +//#define _RSTRACE_ 1 + + + +#ifdef _RSTRACE_ +#include "logtrace.h" +#endif + + +class GZRset +{ +public: + //Added 08/03/2001 + bool m_bSupressErrors; + bool m_bSQLServer; + int FetchFieldType(CString fld); + _ConnectionPtr pTheConnection; + CString SetFieldToMemo(CString fld); + void SetErrMsg(CString strErrorID); + CString m_strLastQuery; + CString GetRSInfo(); + bool m_bRSPRINT; + bool m_bPrinting; + int m_nID; + bool m_bReserved; + bool SetToPrint(bool bPrinting); + bool m_bInUse; + bool m_bExclusiveConnection; + CString m_strCloseQuery; + void SetErrorMsg(CString strError); + void Initialize(CString strError); + CString m_strLiveConnectString; + CString m_strLiveConnectStringExclusive ; + CString m_strDeadConnectString; + bool m_bIsClosed; + bool Valid(); + CString GetLastError(); + + bool Query(CString strQuery); + bool QueryReadOnly(CString strQuery); + bool m_bForwardOnly; + + bool Close(); + + _RecordsetPtr RecordSetPointer(); + + bool SaveRecord(); + bool AddNewRecord(); + + //old execute queries, should be removed + //once no longer used anywhere else + //bool Execute(CString strQuery); + //bool Execute(CString strQuery, long* lIdentity); + + //New execute queries + bool Ex(CString strQuery); + bool Ex(CString strQuery, long* lIdentity); + + bool MoveBack(); + bool MoveForward(); + bool MoveLast(); + bool MoveFirst(); + + + + bool IsEmpty(); + bool FetchAllTextFieldsAsOneString( CString *strValue); + bool FetchAnyFieldAsString(CString fld, CString* strValue); + bool FetchField(CString fld, long* lValue); + bool FetchField(CString fld, float* fValue); + bool FetchField(CString fld, bool* bValue); + bool FetchField(CString fld, CString *strValue); + bool FetchField(CString fld, COleDateTime *dtValue); + bool FetchField(CString fld, COleCurrency *crValue); + //Byte type defined as 0-255 + bool FetchField(CString fld, unsigned char* byteValue); + + bool UpdateField(CString fld, long* lValue); + bool UpdateField(CString fld, float* fValue); + bool UpdateField(CString fld, bool* bValue); + bool UpdateField(CString fld, CString *strValue); + bool UpdateField(CString fld, COleDateTime *dtValue); + bool UpdateField(CString fld, COleCurrency *crValue); + //byte value defined as 0-255 + bool UpdateField(CString fld, unsigned char* byteValue); + + long FetchRecordCount(); + void SetConnect(CString str); + + //OBSOLETE + /* + bool OpenForwardOnly(CString strQuery); + bool Open(CString strQuery); + bool Open(); + bool ChangeCursorLocation(bool bUseClient); + bool Flush(_ConnectionPtr pConnection); + */ + //======================== + GZRset(CString strErr); + GZRset(CString strErr,bool bUseClientCursor); + virtual ~GZRset(); +private: +#ifdef _RSTRACE_ + CLogTrace* log; +#endif + _ConnectionPtr pConnection; + CString m_strErrMsg; + CString m_strLastError;//last error string + //string because it seems to be the only reliable + //error message you get with ADO + bool m_bNoRecords; + long m_lRecordCount; + _RecordsetPtr m_pRecordSet; + bool m_bOpen; + long m_lCurrentRecord; + CString m_strConnect; +public: + // Forces updates within transactions for immediate write purposes only (not for it's intended purpose) + bool m_bUseTransactions; +}; + +#endif // !defined(AFX_GZRSET_H__31F5EB01_0F99_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.cpp new file mode 100644 index 0000000..9aee58e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.cpp @@ -0,0 +1,867 @@ +// GZRsetPool.cpp: implementation of the CGZRsetPool class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "sp.h" +#include "GZRsetPool.h" +#include "TED.H" +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CGZRsetPool::CGZRsetPool() +{ + + //IMPORTANT: to avoid memory fragmentation set this + //value to something higher than the highest amount used + //pool.SetSize(10); + + //used to track how many were allocated + //in order to set the pool size adequately + m_nTotalAllocated=0; + + //default is JET + m_bSQLServer=false; + + //Added 08/03/2001 to hide errors on update + m_bSupressErrors=false; + + m_bUseTransactions=false; + + //TEST TEST TEST + pConnection=NULL; +} + +CGZRsetPool::~CGZRsetPool() +{ + //dump any allocated recordsets if any + Empty(); + +} + +//return a free recordset +//sets nRSID to the unique serial number of this rs +//for identification when closing later +GZRset * CGZRsetPool::GetRS(CString strCallerInfo) +{ + GZRset* rs; + int x; + x=GetFreeRecordsetID(false); + rs=(GZRset*)pool.GetAt(x); + ASSERT(rs!=NULL); + rs->Close(); + rs->m_bExclusiveConnection=false; + + TRACE("\r\n*******************************\r\n" + "[ %i ] - total recordsets in the pool.\r\n" + "*******************************\r\n" + ,m_nTotalAllocated); + + rs->m_bRSPRINT=false; + + //added Sept 30th 2002 + //ensures on a change of use transactions + //that previously allocated rs's are set correctly + //when first accessed + rs->m_bUseTransactions=m_bUseTransactions; + + rs->SetErrMsg(strCallerInfo); + return rs; + +} + +//return a free recordset +//sets nRSID to the unique serial number of this rs +//for identification when closing later +GZRset * CGZRsetPool::GetRSPrint(CString strCallerInfo) +{ + GZRset* rs; + int x; + x=GetFreeRecordsetID(true); + rs=(GZRset*)pool.GetAt(x); + ASSERT(rs!=NULL); + rs->Close(); + rs->m_bExclusiveConnection=false; + + TRACE("\r\n*******************************\r\n" + "[ %i ] - total recordsets in the pool.\r\n" + "*******************************\r\n" + ,m_nTotalAllocated); + + rs->m_bRSPRINT=true; + rs->SetErrMsg(strCallerInfo); + return rs; + +} + + + + +//flag recordset nRSID as available +bool CGZRsetPool::ReleaseRS(int* nID) +{ + + GZRset* rs; + rs=(GZRset*)pool.GetAt(*nID); + ASSERT(rs!=NULL); + //close it up just in case, + //safe to call this repeatedly, + //it just returns if already closed + + rs->Close(); + + //Throw the RS back in the pool + rs->m_bReserved=false; + return true; + +} + +//empty the pool +//(delete all recordset objects) +void CGZRsetPool::Empty() +{ + int x; + GZRset* rs; + + if(m_nTotalAllocated>0) + { + for(x=0;xClose(); + delete rs; + + } + + m_nTotalAllocated=0; + } + + //added March 22 2001 on a whim + pool.RemoveAll(); +} + + +//RETURNS the pool objarray index value of a free +//recordset, also sets the recordset as in use +int CGZRsetPool::GetFreeRecordsetID(bool bPrint) +{ + + int x; + + if(m_nTotalAllocated==0)//none made yet + { + + rsGENERIC = new GZRset("Allocated First"); + InitializeNewRS(rsGENERIC,bPrint); + + x=pool.Add((CObject*)rsGENERIC); + + //set this recordset's ID value + rsGENERIC->m_nID=x; + + //Increment the recordsets allocated counter + m_nTotalAllocated++; + return x; + } + + //there are some allocated, see if any are free + for(int y=0; ym_bReserved==false)//is it free for use? + { + rsGENERIC->m_bReserved=true; + return y; + } + } + + //There are none free so we have to add one now + rsGENERIC = new GZRset("Allocated"); + InitializeNewRS(rsGENERIC, bPrint); + x=pool.Add((CObject*)rsGENERIC); + + //set this recordset's ID value + rsGENERIC->m_nID=x; + + m_nTotalAllocated++; + + //arbitrary test value + ASSERT(m_nTotalAllocated<50); + + return x; + + + + +} + +bool CGZRsetPool::InitializeNewRS(GZRset *rs,bool bPrint) +{ + ASSERT(rs!=NULL); + + //TEST TEST TEST + ASSERT(pConnection!=NULL); + rs->pTheConnection=pConnection; + //set initial connection strings here + rs->SetConnect(strConnectString); + + //Set standard connection string here + rs->m_strLiveConnectString=m_strLiveConnectString; + + //Set exclusive connection string here + rs->m_strLiveConnectStringExclusive=m_strLiveConnectStringExclusive; + + //Set DEAD connect string: point to the empty database file + rs->m_strDeadConnectString=m_strDeadConnectString; + + //query to execute against the empty database file + //to ensure the original connection gets closed + //to the live database file + rs->m_strCloseQuery=m_strCloseQuery; + + //Take it out of the pool + rs->m_bReserved=true; + + //Added May21 2001 SQL server stuff + rs->m_bSQLServer=m_bSQLServer; + + //Added 08/03/2001 + rs->m_bSupressErrors=m_bSupressErrors; + + //added 09/30/2002 + rs->m_bUseTransactions=m_bUseTransactions; + + //This is now the first database call as of + //December 8 2000 + rs->Close(); + return true; + +} + +//Diagnostic routine +void CGZRsetPool::ShowAllOpenRS() +{ + int x; + GZRset* rs; + CString strMsg; + if(m_nTotalAllocated>0) + { + strMsg.Format("Total recordsets allocated:%i\r\n",m_nTotalAllocated); + for(x=0;xm_bInUse ? "** RS IS ACTIVE **":".. RS NOT ACTIVE .."; + strMsg=strMsg+rs->GetRSInfo()+"\r\n"+rs->m_strLastQuery+"\r\n"; + strMsg+="\r\n---------------------------------\r\n"; + + + } + CTED d; + d.m_strText=strMsg; + d.DoModal(); + + } + else + AfxMessageBox("No recordsets in use"); + +} + +void CGZRsetPool::StartConnection() +{ + //create a pointer to a connection + //_ConnectionPtr pConnection = NULL; + try{ + //instantiate it: + pConnection.CreateInstance(__uuidof(Connection)); + + //get connect string + _bstr_t strCnn(m_strLiveConnectString); + + //open the connection + //this will THROW if the database is corrupted + pConnection->Open (strCnn, "", "", adConnectUnspecified); + + + + DisplayProperties(); +} +catch (_com_error &e) + { + + + CString cstrErrMsg,strEx;HRESULT hr=e.Error(); + int nReason=0; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + CString str((BSTR)bstrDescription); + //Decode error message from JET (hope it's in english) + //because Microsoft doesn't pass through the original jet error + //only the MDAC general error 80004005 + if(str.Find("File Already in Use")!=-1) + nReason=1;//locked exclusive / no rights\ + + if(str.Find("The Microsoft Jet database engine cannot open the file '(unknown)'")!=-1) + nReason=1;//locked exclusive / no rights\ + + if(str.Find("Name Not Found")!=-1) + nReason=2;//file not found + + if(str.Find("Unrecognized database format")!=-1) + nReason=3;//corrupt or not a database. + + + switch(nReason) + { + case 0://unknown error + strEx=""; + break; + + case 1://exclusive or no rights + strEx="Common causes for this error:\r\n" + "1) Insufficient rights to the database folder and file\r\n" + "(check that you have full access rights to the database folder)\r\n" + "\r\n" + "2) Database file is already open in exclusive only mode by another user or program.\r\n" + "(check if another program has the database open such as Access\r\n" + "in exclusive only mode)\r\n\r\n"; + break; + + case 2://file not found + strEx="Common causes for this error:\r\n" + "1) The wrong location has been specified for the database\r\n" + "2) The database file has been deleted\r\n" + "3) The database file has been renamed\r\n\r\n"; + break; + + case 3://corrupt / not a database + strEx="Common causes for this error:\r\n" + "1) The database file is not actually a database file\r\n" + "(someone renamed a non-database file to a database file name)\r\n" + "\r\n" + "2) The database file is damaged and needs to be repaired.\r\n" + "(See the AyaNova manual reference section:\r\n" + "\"Repairing the AyaNova Database\"\r\n" + "which has complete instructions on repairing\r\n" + "the database, the causes of database corruption\r\n" + "and how to prevent the problem from happening\r\n" + "again in future.)\r\n\r\n"; + break; + + } + + + cstrErrMsg.Format( + "AyaNova could not open the database file:\r\n" + "\r\n" + "%s\\scdata.sc\r\n" + "\r\n" + "The database driver gave the following reason:\r\n" + "%s\r\n" + "\r\n" + "%s" + "This program will now close...",m_strDBPATH,str,strEx); + + + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %08x\n", hr); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); +#ifdef AYQB + cstrErrMsg.Format( + "AyaNova could not open the database file:\r\n\r\n" + + "%sqbtrial.aya\r\n\r\n" + + "This database file does not appear to be a AyaNova QBI trial edition\r\n" + "compatible database.\r\n\r\n" + + + + "AyaNova will now close...",m_strDBPATH); + +#endif + AfxMessageBox(cstrErrMsg); + + + + + PostQuitMessage(-1);//exit now before anything worse happens + return ; + + + + + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + //AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return ; + + } + + +} + + + + + + + + + + + +//**************************************************** +// compact the database through a jro object +//********************************************** +bool CGZRsetPool::Compact(bool bKeepOld) +{ + bool status=true; + CString src,dest,tempfile; + CFileStatus fstat; + CWaitCursor wait; + + + //delete old one if exists + tempfile.Format("%sscdata.tmp",m_strDBPATH); + if(CFile::GetStatus(tempfile,fstat)==TRUE)//file exists + { + TRY + { + CFile::Remove( tempfile ); + } + CATCH( CFileException, e ) + { + status=false; + CString cstrErrMsg; + cstrErrMsg.Format("Error in Compact: %s cannot be removed",tempfile); + AfxMessageBox(cstrErrMsg); + } + END_CATCH + } + + if(status==true) + { + + + + src.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sscdata.sc;Jet OLEDB:Engine Type=5;", + m_strDBPATH); + + dest.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sscdata.tmp;Jet OLEDB:Engine Type=5;", + m_strDBPATH); + + + _bstr_t bstsrc(src); + _bstr_t bstdest(dest); + + try + { + IJetEnginePtr jet(__uuidof(JetEngine)); + + jet->CompactDatabase(bstsrc, bstdest); + } + catch(_com_error &e) + { + status=false; + CString cstrErrMsg; + //get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE( "*************************************************\n"); + TRACE( "Exception thrown for classes generated by #import\n"); + TRACE( "\tCode = %081x\n", e.Error); + TRACE( "\tCode Meaning = %s\n",e.ErrorMessage()); + TRACE( "\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE( "Description = %s\n", (LPCTSTR) bstrDescription); + TRACE( "*************************************************\n"); + cstrErrMsg.Format("Error in Compact: %s,\r\n%s",e.ErrorMessage(),(LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + + } + catch(...) + { + status=false; + TRACE( "*** Unhandled exception ***" ); + AfxMessageBox("Unhandled Error in Compact"); + PostQuitMessage(-1);//exit now before anything worse happens + + } + + + } + + //Added. indexing can leave a 100+mb old file + //this way can delete it + if(bKeepOld) + { + //copy mdb over old + src.Format("%sscdata.sc",m_strDBPATH); + dest.Format("%sscdata.old",m_strDBPATH); + status=CopyFile(src.GetBuffer(100),dest.GetBuffer(100)); + } + + + + if(status==true) + { + + + src.Format("%sscdata.tmp",m_strDBPATH); + dest.Format("%sscdata.sc",m_strDBPATH); + status=CopyFile(src.GetBuffer(100),dest.GetBuffer(100)); + + + }//if status==true + + //delete gz1 + tempfile.Format("%sscdata.tmp",m_strDBPATH); + if(CFile::GetStatus(tempfile,fstat)==TRUE)//file exists + { + TRY + { + CFile::Remove( tempfile ); + } + CATCH( CFileException, e ) + { + status=false; + CString cstrErrMsg; + cstrErrMsg.Format("Error at end of Compact: %s cannot be removed\r\nOtherwise compact OK",tempfile); + AfxMessageBox(cstrErrMsg); + } + END_CATCH + } + + + return status; +} + +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + + + + + + + +//******************************************* +//copy a file, overwrite dest if exists +bool CGZRsetPool::CopyFile(char *src, char *dest) +{ + + CFile sourceFile; + CFile destFile; + CFileException ex; + CString tempfile; + + + + // open the source file for reading + + if (!sourceFile.Open(src, + CFile::modeRead | CFile::shareDenyWrite, &ex)) + { + // complain if an error happened + // no need to delete the ex object + + TCHAR szError[1024]; + ex.GetErrorMessage(szError, 1024); + CString errormsg; + errormsg.Format("Error copying file %s to %s\r\n The error was: %s",src,dest,szError); + AfxMessageBox(errormsg); + return false; + } + else + { + if (!destFile.Open(dest, CFile::modeWrite | + CFile::shareExclusive | CFile::modeCreate, &ex)) + { + TCHAR szError[1024]; + ex.GetErrorMessage(szError, 1024); + CString errormsg; + errormsg.Format("Error copying file %s to %s\r\n The error was: %s",src,dest,szError); + AfxMessageBox(errormsg); + sourceFile.Close(); + return false; + } + + BYTE buffer[4096]; + DWORD dwRead; + + // Read in 4096-byte blocks, + // remember how many bytes were actually read, + // and try to write that many out. This loop ends + // when there are no more bytes to read. + + do + { + dwRead = sourceFile.Read(buffer, 4096); + destFile.Write(buffer, dwRead); + } + while (dwRead > 0); + + // Close both files + + destFile.Close(); + sourceFile.Close(); + } + + return true; + +} + + + + + + + + + + + +bool CGZRsetPool::GoExclusive() +{ + try{ + if(pConnection->GetState()==adStateOpen) + pConnection->Close(); + + //get connect string + _bstr_t strCnn(m_strLiveConnectStringExclusive); + + //open the connection + pConnection->Open (strCnn, "", "", adConnectUnspecified); + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("At GoExclusive access (all other users out)\r\n %s,\r\n%s", e.ErrorMessage(), (LPCTSTR) bstrDescription); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + //AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + return true; +} + + + +bool CGZRsetPool::GoShared() +{ + try{ + + if(pConnection->GetState()==adStateOpen) + pConnection->Close(); + + + //get connect string + _bstr_t strCnn(m_strLiveConnectString); + + //open the connection + pConnection->Open (strCnn, "", "", adConnectUnspecified); + } + catch (_com_error &e) + { + + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("At GoShared()\r\n%s,\r\n%s\r\n", e.ErrorMessage(), (LPCTSTR) bstrDescription); + //cstrErrMsg.Format("%s: %s,\r\n%s",m_strErrMsg, e.ErrorMessage(), (LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + return false; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + //AfxMessageBox(m_strErrMsg); + PostQuitMessage(-1);//exit now before anything worse happens + return false; + + } + return true; +} + +void CGZRsetPool::Disconnect() +{ +if(pConnection->GetState()==adStateOpen) + pConnection->Close(); +} + + +//DIAGNOSIS Class for messing about with +//connection and other properties +//not actually used by the program +void CGZRsetPool::DisplayProperties() +{ +PropertiesPtr pPrpLoop = NULL; + _variant_t vtIndex; + _variant_t propValue; + vtIndex.vt = VT_I2; + _variant_t vtOne; + vtOne.vt=VT_I4; + vtOne.lVal=1; + CString strName; + pPrpLoop=pConnection->GetProperties(); + + + //pConnection->GetProperties()->GetItem()->Value=(_variant_t)1; + +for (int intProperties = 0; intProperties < (int)pPrpLoop-> + GetCount(); intProperties++) + { + vtIndex.iVal = intProperties; + propValue = pPrpLoop->GetItem(vtIndex)->Value; + strName=(LPCSTR) pPrpLoop->GetItem(vtIndex)->GetName(); + if(strName=="Jet OLEDB:Transaction Commit Mode") + { + pPrpLoop->GetItem(vtIndex)->Value=vtOne; + break; + } + + } +/* +#ifdef _DEBUG +propValue = pPrpLoop->GetItem(vtIndex)->Value; +ASSERT(propValue.iVal==1); +#endif +*/ + +} + + +//Get datbase properties for tech support +//displayed under help->About->Support info... +void CGZRsetPool::GetDBProps() +{ + try{ + if(pConnection->GetState()!=adStateOpen) + return; + //SET All version variables + m_strADOVersion = (LPCSTR) pConnection->Version; + + m_strDBMSName = (LPCSTR) (_bstr_t) + pConnection->Properties->GetItem("DBMS Name")->Value; + + m_strDBMSVersion= (LPCSTR) (_bstr_t) pConnection-> + Properties->GetItem("DBMS Version")->Value; + + m_strOLEDbVersion=(LPCSTR) (_bstr_t) + pConnection->Properties->GetItem("OLE DB Version")->Value; + + m_strProviderName=(LPCSTR) (_bstr_t) + pConnection->Properties->GetItem("Provider Name")->Value; + + m_strProviderVersion=(LPCSTR) (_bstr_t) + pConnection->Properties->GetItem("Provider Version")->Value; + +/* m_strDriverVersion=(LPCSTR) (_bstr_t) + pConnection->Properties->GetItem("Driver Name")->Value; + + m_strDriverName=(LPCSTR) (_bstr_t) + pConnection->Properties->GetItem("Driver Version")->Value; + + m_strDriverODBCVersion=(LPCSTR) (_bstr_t) + pConnection->Properties->GetItem("Driver ODBC Version")->Value; +*/ +} +catch (_com_error &e) + { + CString cstrErrMsg; + // get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + cstrErrMsg.Format("Error: Can't fetch database driver information.\r\n\r\nExact error is:\r\n%s", (LPCTSTR) bstrDescription); + + + return ; + } + catch (...) + { + + TRACE("*** Unhandled exception ***"); + //AfxMessageBox(m_strErrMsg); + + return ; + + } + + +} + + +//Added 08/03/2001 to selective turn off error +//warnings in gzrset to accomodate updates +//so users don't freak out +void CGZRsetPool::SupressErrors(bool bNoErrors) +{ + m_bSupressErrors=bNoErrors; +int x; + GZRset* rs; + if(m_nTotalAllocated>0) + { + + for(x=0;xm_bSupressErrors=m_bSupressErrors; + + } + + } + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.h new file mode 100644 index 0000000..4db856e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GZRsetPool.h @@ -0,0 +1,67 @@ +// GZRsetPool.h: interface for the CGZRsetPool class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_GZRSETPOOL_H__CDF9C9E1_CCEA_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_GZRSETPOOL_H__CDF9C9E1_CCEA_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include "gzrset.h" +#include + +class CGZRsetPool +{ +public: + void SupressErrors(bool bNoErrors); + //Added 08/03/2001 to hide errors on update + bool m_bSupressErrors; + void GetDBProps(); + CString m_strADOVersion; + CString m_strDBMSName; + CString m_strDBMSVersion; + CString m_strOLEDbVersion; + CString m_strProviderName; + CString m_strProviderVersion; + CString m_strDriverVersion; + CString m_strDriverName; + CString m_strDriverODBCVersion; + + bool m_bSQLServer; + bool Compact(bool bKeepOld); + bool CopyFile(char *src, char *dest); + void DisplayProperties(); + void Disconnect(); + CString cstrErrMsg; + bool GoShared(); + bool GoExclusive(); + + _ConnectionPtr pConnection; + void StartConnection(); + void ShowAllOpenRS(); + GZRset* rsGENERIC; + bool InitializeNewRS(GZRset* rs, bool bPrint); + CString m_strCloseQuery; + CString m_strDeadConnectString; + CString m_strLiveConnectStringExclusive; + CString m_strLiveConnectString; + CString strConnectString; + CString m_strDBPATH; + int GetFreeRecordsetID(bool bPrint); + int m_nTotalAllocated; + GZRset* GetRS(CString strCallerInfo); + GZRset* GetRSPrint(CString strCallerInfo); + + void Empty(); + bool ReleaseRS(int* nRSID); + + virtual ~CGZRsetPool(); + + CGZRsetPool(); + CObArray pool; + // if true will force all updates within transactions which ensures immediate write out as were not so much concerned with data integrity here but immediacy + bool m_bUseTransactions; +}; + +#endif // !defined(AFX_GZRSETPOOL_H__CDF9C9E1_CCEA_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.cpp new file mode 100644 index 0000000..2375820 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.cpp @@ -0,0 +1,103 @@ +// GenericPopupList.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "GenericPopupList.h" +#include "StringParser.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGenericPopupList dialog + + +CGenericPopupList::CGenericPopupList(CWnd* pParent /*=NULL*/) + : CDialog(CGenericPopupList::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGenericPopupList) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CGenericPopupList::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGenericPopupList) + DDX_Control(pDX, IDC_BTNOPEN, m_btnOpen); + DDX_Control(pDX, IDC_BTNEXIT, m_btnExit); + DDX_Control(pDX, IDC_LSTNBRECS, m_lb); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGenericPopupList, CDialog) + //{{AFX_MSG_MAP(CGenericPopupList) + ON_LBN_DBLCLK(IDC_LSTNBRECS, OnDblclkLstnbrecs) + ON_BN_CLICKED(IDC_BTNEXIT, OnBtnexit) + ON_BN_CLICKED(IDC_BTNOPEN, OnBtnopen) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGenericPopupList message handlers + +void CGenericPopupList::OnDblclkLstnbrecs() +{ + CString strSelected; + strSelected=m_lb.GetSelectedItem(0); + m_pSelectedID->Format("%s",strSelected); + CDialog::OnOK(); + +} + +void CGenericPopupList::OnBtnopen() +{ +OnDblclkLstnbrecs(); +} + + +void CGenericPopupList::OnBtnexit() +{ + m_pSelectedID->Empty(); + CDialog::OnOK(); +} + + +void CGenericPopupList::OnOK() +{} + + +BOOL CGenericPopupList::OnInitDialog() +{ + CDialog::OnInitDialog(); + CString strData,strIndex; + +//Fill list box from m_LbData + CStringParser sp(m_strLbData,','); + int nCount=sp.GetCount(); + + + if (nCount > 0) + { + + for (int i = 1; i <= nCount; i+=2) + { + strData = sp.GetField(i); + strIndex=sp.GetField(i+1); + m_lb.AddRow(strData,strIndex); + + + } + + + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.h new file mode 100644 index 0000000..9bb72cb --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GenericPopupList.h @@ -0,0 +1,54 @@ +#if !defined(AFX_GENERICPOPUPLIST_H__0F1CCD67_9840_4BBA_A211_3BECB748D921__INCLUDED_) +#define AFX_GENERICPOPUPLIST_H__0F1CCD67_9840_4BBA_A211_3BECB748D921__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GenericPopupList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGenericPopupList dialog +#include "gzlistbox.h" +class CGenericPopupList : public CDialog +{ +// Construction +public: + CString m_strLbData; + CString * m_pSelectedID; + CGenericPopupList(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CGenericPopupList) + enum { IDD = IDD_GENERIC_LISTBOX }; + CButton m_btnOpen; + CButton m_btnExit; + CgzListBox m_lb; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGenericPopupList) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGenericPopupList) + afx_msg void OnDblclkLstnbrecs(); + virtual void OnOK(); + afx_msg void OnBtnexit(); + afx_msg void OnBtnopen(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GENERICPOPUPLIST_H__0F1CCD67_9840_4BBA_A211_3BECB748D921__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.cpp new file mode 100644 index 0000000..da8be83 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.cpp @@ -0,0 +1,82 @@ +// GetAllOrXValue.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "GetAllOrXValue.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGetAllOrXValue dialog + + +CGetAllOrXValue::CGetAllOrXValue(CWnd* pParent /*=NULL*/) + : CDialog(CGetAllOrXValue::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGetAllOrXValue) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_plValueReturn=NULL; +} + + +void CGetAllOrXValue::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGetAllOrXValue) + DDX_Control(pDX, IDC_LBLPROMPT, m_lblPrompt); + DDX_Control(pDX, IDC_EDX, m_edX); + DDX_Control(pDX, IDC_CKALL, m_ckALL); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGetAllOrXValue, CDialog) + //{{AFX_MSG_MAP(CGetAllOrXValue) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGetAllOrXValue message handlers + +void CGetAllOrXValue::OnOK() +{ + CString str; + if(m_ckALL.GetCheck()==TRUE) + *m_plValueReturn=-1; + else + { + m_edX.GetWindowText(str); + if(str.IsEmpty()) + *m_plValueReturn=0; + else + *m_plValueReturn=atol(str); + + } + + CDialog::OnOK(); +} + +void CGetAllOrXValue::OnCancel() +{ + + *m_plValueReturn=0;//indicates cancelled + CDialog::OnCancel(); +} + +BOOL CGetAllOrXValue::OnInitDialog() +{ + CDialog::OnInitDialog(); + ASSERT(m_plValueReturn!=NULL); + + if(!m_strPrompt.IsEmpty()) + m_lblPrompt.SetWindowText(m_strPrompt); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.h new file mode 100644 index 0000000..8e2f07a --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetAllOrXValue.h @@ -0,0 +1,52 @@ +#if !defined(AFX_GETALLORXVALUE_H__F43183C1_3F7B_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_GETALLORXVALUE_H__F43183C1_3F7B_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GetAllOrXValue.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGetAllOrXValue dialog + +class CGetAllOrXValue : public CDialog +{ +// Construction +public: + long * m_plValueReturn; + CString m_strPrompt; + CGetAllOrXValue(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CGetAllOrXValue) + enum { IDD = IDD_GETALLORXRECORDS }; + CStatic m_lblPrompt; + CEdit m_edX; + CButton m_ckALL; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGetAllOrXValue) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGetAllOrXValue) + virtual void OnOK(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GETALLORXVALUE_H__F43183C1_3F7B_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.cpp new file mode 100644 index 0000000..dc03b6d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.cpp @@ -0,0 +1,94 @@ +// GetStringDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "GetStringDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CGetStringDlg dialog + + +CGetStringDlg::CGetStringDlg(CWnd* pParent /*=NULL*/) + : CDialog(CGetStringDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGetStringDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CGetStringDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGetStringDlg) + DDX_Control(pDX, IDC_LBLPROMPT, m_lblPrompt); + DDX_Control(pDX, IDC_EDSTRING, m_edString); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGetStringDlg, CDialog) + //{{AFX_MSG_MAP(CGetStringDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGetStringDlg message handlers + +//Prompt=prompting string, pstrReturn=default and return string +void CGetStringDlg::Setup(CString prompt, CString *pstrReturn) +{ + if(prompt.IsEmpty()) + m_strPrompt="Enter text:"; + else + m_strPrompt=prompt; + + m_pstrReturn=pstrReturn; + + +} + + +//************************************** +BOOL CGetStringDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_lblPrompt.SetWindowText(m_strPrompt); + m_edString.SetWindowText(*m_pstrReturn); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + + +//************************************* +void CGetStringDlg::OnCancel() +{ + + CDialog::OnCancel(); +} + + +//************************************* +void CGetStringDlg::OnOK() +{ + CString str; + str.Empty(); + m_edString.GetWindowText(str); + if(str.IsEmpty()) + CDialog::OnCancel(); + else + { + *m_pstrReturn=str; + CDialog::OnOK(); + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.h new file mode 100644 index 0000000..41c9269 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GetStringDlg.h @@ -0,0 +1,52 @@ +#if !defined(AFX_GETSTRINGDLG_H__483F7621_37D4_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_GETSTRINGDLG_H__483F7621_37D4_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GetStringDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGetStringDlg dialog + +class CGetStringDlg : public CDialog +{ +// Construction +public: + CString * m_pstrReturn; + CString m_strPrompt; + void Setup(CString prompt, CString* pstrReturn); + CGetStringDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CGetStringDlg) + enum { IDD = IDD_GETSTRING }; + CStatic m_lblPrompt; + CEdit m_edString; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGetStringDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGetStringDlg) + virtual BOOL OnInitDialog(); + virtual void OnCancel(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GETSTRINGDLG_H__483F7621_37D4_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.cpp new file mode 100644 index 0000000..e83feaa --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.cpp @@ -0,0 +1,803 @@ +// GroupsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "GroupsDlg.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +///////////////////////////////////////////////////////////////////////////// +// CGroupsDlg dialog + + +CGroupsDlg::CGroupsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CGroupsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGroupsDlg) + //}}AFX_DATA_INIT + k=new GZK; + m_pApp= (CSpApp*)AfxGetApp(); + + /* + rs=new GZRset("Group rights dialog error:"); + rs->SetConnect(m_pApp->strConnectString); + lbrs=new GZRset("Group rights dialog reports listbox recordset error:"); + lbrs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + +rs=m_pApp->rsPool->GetRS("CGroupsDlg (RS)"); +lbrs=m_pApp->rsPool->GetRS("CGroupsDlg (LBRS)"); + + m_strGroupsReports.Empty(); +} + +CGroupsDlg::~CGroupsDlg() +{ + delete k; + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&lbrs->m_nID); +} + +void CGroupsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGroupsDlg) + DDX_Control(pDX, IDC_26, m_26); + DDX_Control(pDX, IDC_25, m_25); + DDX_Control(pDX, IDC_24, m_24); + DDX_Control(pDX, IDC_23, m_23); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_LBRPTPOOL, m_lbReportsPool); + DDX_Control(pDX, IDC_LBRPTGROUP, m_lbReportsGroup); + DDX_Control(pDX, IDC_9, m_9); + DDX_Control(pDX, IDC_8, m_8); + DDX_Control(pDX, IDC_21, m_21); + DDX_Control(pDX, IDC_22, m_22); + DDX_Control(pDX, IDC_20, m_20); + DDX_Control(pDX, IDC_19, m_19); + DDX_Control(pDX, IDC_18, m_18); + DDX_Control(pDX, IDC_17, m_17); + DDX_Control(pDX, IDC_16, m_16); + DDX_Control(pDX, IDC_15, m_15); + DDX_Control(pDX, IDC_14, m_14); + DDX_Control(pDX, IDC_13, m_13); + DDX_Control(pDX, IDC_12, m_12); + DDX_Control(pDX, IDC_11, m_11); + DDX_Control(pDX, IDC_10, m_10); + DDX_Control(pDX, IDC_7, m_7); + DDX_Control(pDX, IDC_6, m_6); + DDX_Control(pDX, IDC_5, m_5); + DDX_Control(pDX, IDC_4, m_4); + DDX_Control(pDX, IDC_3, m_3); + DDX_Control(pDX, IDC_2, m_2); + DDX_Control(pDX, IDC_1, m_1); + DDX_Control(pDX, IDC_0, m_0); + DDX_Control(pDX, IDC_GROUPNAME, m_edName); + DDX_Control(pDX, IDC_GROUP_LIST_LABEL, m_lblGroupList); + DDX_Control(pDX, IDC_GROUP_COMBO, m_cbGroup); + DDX_Control(pDX, IDC_DELETE, m_btnDelete); + DDX_Control(pDX, IDC_ADD, m_btnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGroupsDlg, CDialog) +//{{AFX_MSG_MAP(CGroupsDlg) +ON_BN_CLICKED(IDC_ADD, OnAdd) +ON_BN_CLICKED(IDC_DELETE, OnDelete) +ON_CBN_CLOSEUP(IDC_GROUP_COMBO, OnCloseupGroupCombo) +ON_BN_CLICKED(IDOK, OnOk) +ON_EN_KILLFOCUS(IDC_GROUPNAME, OnKillfocusGroupname) +ON_WM_RBUTTONDBLCLK() + ON_BN_CLICKED(IDC_BTNREMOVERPT, OnBtnremoverpt) + ON_BN_CLICKED(IDC_BTNADDRPT, OnBtnaddrpt) + ON_LBN_DBLCLK(IDC_LBRPTGROUP, OnDblclkLbrptgroup) + ON_LBN_DBLCLK(IDC_LBRPTPOOL, OnDblclkLbrptpool) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGroupsDlg message handlers + + +void CGroupsDlg::FillListBox() +{ + //fill list box with different groups + CString strData; + CString strIndex; + long lData; + m_cbGroup.Clear(); + + + + rs->Query("SELECT groups.* FROM groups;"); + if(!rs->IsEmpty()) + { + //fill combo box with available zones + rs->MoveFirst(); + rs->FetchField("a",&strData); + + //decrypt the name + k->GZDecrypt(&strData,false); + + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbGroup.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("a",&strData); + //decrypt the name + k->GZDecrypt(&strData,false); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbGroup.AddRow(strData,strIndex); + } + + } + + //pretend user has selected so that other fields get filled in + if(m_strSelectedGroup.IsEmpty()) //first time in + { + m_cbGroup.Select(1); + //set last selected because were probably + //here due to a delete and so whatever it was set + //to is now invalid and will cause havoc on the + //next save call. + m_strLastComboID=m_cbGroup.GetCurrentRowID(); + + } + else//something valid was selected before so stick with it + m_cbGroup.Select(m_strSelectedGroup); + + + SetFields(); + + + +} + +void CGroupsDlg::SetFields() +{ + //user has made a selection, update the visible list + CString q; + CString strName; + CString strRights; + CString strHash; + BOOL enable=TRUE; + //save current selection so that updates and changes + //will still show what was last selected + m_strSelectedGroup=m_cbGroup.GetCurrentRowID(); + if(m_strSelectedGroup=="1" || m_bReadOnly) enable= FALSE; + long lID; + q.Format("SELECT groups.* FROM groups WHERE (((groups.id)=%s));",m_strSelectedGroup); + rs->Query(q); + if(!rs->IsEmpty()) + { + m_strGroupsReports.Empty(); + + rs->FetchField("id",&lID);//id number + rs->FetchField("a",&strName);//name string + rs->FetchField("b",&strRights);//rights string + rs->FetchField("c",&strHash);//checksum/hash + rs->FetchField("d",&m_strGroupsReports); + //decrypt if there is something there + if(!m_strGroupsReports.IsEmpty()) + k->GZDecrypt(&m_strGroupsReports,false); + + //used by save routine to see if user has made + //report selection changes + m_strGroupsReportsInitialValue=m_strGroupsReports; + //stuff em all together and compare the hash value + //to make sure no one has been screwing with the security + //settings + q.Format("%u%s%s",lID,strName,strRights); + k->GZHash(&q); + if(q.Compare(strHash)!=0 && m_bMasterMode==false) + { + AfxMessageBox("Security breach!\r\nGroup rights corrupted."); + //PostQuitMessage(WM_QUIT); + return; + } + + //take the rightmost numrights characters and set the rights buttons + //accordingly + k->GZDecrypt(&strRights,false); + q=strRights.Right(NUMRIGHTS); + } + //initialize the rights buttons + for(int x=0;xSet(strRights,true); + m_pRight[x]->EnableWindow(enable); + + } + + //display the list name + k->GZDecrypt(&strName,false); + m_edName.SetWindowText(strName); + m_edName.EnableWindow(enable); + m_btnDelete.ShowWindow(enable); + m_lbReportsGroup.EnableWindow(enable); + m_lbReportsPool.EnableWindow(enable); + if(enable) + DisplayReportLists(); + +} + +//************************************ +void CGroupsDlg::OnAdd() +{ + CString str; + if(m_bAddMode)//user is requesting to save + { + m_edName.GetWindowText(str); + if(str.IsEmpty()) + { + AfxMessageBox("You must enter a group name"); + return; + } + + //bugbug: sometimes it complains about + //adding a duplicate record when + //not doing that. Could be add mode is + //not resetting so it thinks it's adding + //rather than updating. + + //Seems to happen when you add a new record + //edit then add a second. + //seems to have started since adding code + //to select newly added record automatically. + + //Also is not clearing old values on add new properly. + + m_bAddMode=false; + m_cbGroup.ShowWindow(TRUE); + m_lblGroupList.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + m_btnDone.ShowWindow(TRUE); + //save the new record + Save(false); + FillListBox(); + } + else//not add mode + { + Save(true); + //DO: set default values of controls. + m_edName.EnableWindow(TRUE); + m_btnDelete.ShowWindow(TRUE); + m_cbGroup.ShowWindow(FALSE); + m_lblGroupList.ShowWindow(FALSE); + m_btnAdd.SetWindowText("SAVE"); + m_btnDelete.SetWindowText("Cancel"); + m_btnDone.ShowWindow(FALSE); + m_edName.SetWindowText(""); + m_edName.SetFocus(); + m_bAddMode=true; + } +} + + +//******************************************* +void CGroupsDlg::OnDelete() +{ + CString strGroupID; + if(m_bAddMode==true)//then this is the cancel button + { + m_bAddMode=false; + m_cbGroup.ShowWindow(TRUE); + m_lblGroupList.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + m_btnDone.ShowWindow(TRUE); + FillListBox(); + return; + } + + //otherwise, delete the record + + strGroupID=m_cbGroup.GetCurrentRowID(); + if(strGroupID=="1" && m_bMasterMode==false) + { + //AfxMessageBox("To protect your access the group can not be deleted."); + return; + } + CString q,strData; + q.Format("SELECT [first] & \" \" & [last] AS name " + "FROM users WHERE (((users.c)=%s));",strGroupID); + + + + + + rs->Query(q); + if(rs->IsEmpty())//no clients in that zone + { + + q.Format("DELETE groups.*, groups.id " + "FROM groups WHERE (((groups.id)=%s));",m_cbGroup.GetCurrentRowID()); + + if(AfxMessageBox("Delete this group?",MB_YESNO)==IDYES) + { + rs->Ex(q); + //a deleted zone can't be selected + m_strSelectedGroup=""; + + } + } + else + { + q="DATA INTEGRITY PROTECTION:\r\nYou cannot delete this security group because\r\nthe following users are set to it:\r\n"; + + //fill combo box with available zones + rs->MoveFirst(); + rs->FetchField("name",&strData); + q=q+strData+"\r\n"; + + + while(rs->MoveForward()) + { + rs->FetchField("name",&strData); + q=q+strData+"\r\n"; + } + AfxMessageBox(q); + } + FillListBox(); + + + +} + + + + + + +//**************************************************** +BOOL CGroupsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + ShowWindow(SW_SHOWMAXIMIZED); + m_bAddMode=false; + + + + m_pRight[0]=&m_0; + m_pRight[1]=&m_1; + m_pRight[2]=&m_2; + m_pRight[3]=&m_3; + m_pRight[4]=&m_4; + m_pRight[5]=&m_5; + m_pRight[6]=&m_6; + m_pRight[7]=&m_7; + m_pRight[8]=&m_8; + m_pRight[9]=&m_9; + m_pRight[10]=&m_10; + m_pRight[11]=&m_11; + m_pRight[12]=&m_12; + m_pRight[13]=&m_13; + m_pRight[14]=&m_14; + m_pRight[15]=&m_15; + m_pRight[16]=&m_16; + m_pRight[17]=&m_17; + m_pRight[18]=&m_18; + m_pRight[19]=&m_19; + m_pRight[20]=&m_20; + m_pRight[21]=&m_21; + m_pRight[22]=&m_22; + m_pRight[23]=&m_23; + m_pRight[24]=&m_24; + m_pRight[25]=&m_25; + m_pRight[26]=&m_26; + + //ASSUMPTION: can only get here from the main + //menu bar, so either you can't get here at all + //or you have read only access, so onlyt + //have to set readonly here not check for + //no access since that's taken care of in the + //CspApp->switchview function + if(m_pApp->Allowed(RSECURITY,true)==2)//read only? + m_bReadOnly=true; + else + m_bReadOnly=false; + + FillListBox(); + m_strLastComboID=m_cbGroup.GetCurrentRowID(); + + // m_lblHead1.SetFontName("Arial").SetFontSize(12).SetFontBold(TRUE).SetFontUnderline(TRUE).SetTextColor(RGB(0,0,0)); + // m_lblHead2.SetFontName("Arial").SetFontSize(12).SetFontBold(TRUE).SetFontUnderline(TRUE).SetTextColor(RGB(0,0,0)); + + m_bMasterMode=false; + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + + //DisplayReportLists(); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CGroupsDlg::OnCloseupGroupCombo() +{ + + //call save + if(m_strLastComboID!="1") + Save(true); + //set to current selection + //when save is called before this line + //it will be able to see if the combo has changed + //and can use the last combo ID value instead + //during the save + m_strLastComboID=m_cbGroup.GetCurrentRowID(); + SetFields(); + +} + + +//******************************************** +//if update==true then update existing record +//else create new record +void CGroupsDlg::Save(bool Update/*or new*/) +{ + CString q; + CString strItem; + CString strName; + CString strRights; + CString strHash; + CString strGroupID; + CString strReports; + bool HereFromCBCloseup=false; + long lID; + int x; + bool ThereAreChanges=false; + + + if(Update) + { + //check the rights buttons + for(x=0;xIsChanged()) + { + ThereAreChanges=true; + break; + } + } + + //check the group name box + if(m_edName.GetModify()==TRUE) + ThereAreChanges=true; + + //check reports + if(m_strGroupsReports!=m_strGroupsReportsInitialValue) + ThereAreChanges=true; + + //no changes? then exit routine + if(ThereAreChanges==false) + return; + + } + + //save changes + m_edName.GetWindowText(strName); + if(strName.IsEmpty()) + { + AfxMessageBox("You must enter a group name"); + return; + } + + strRights=strName; + for(x=0;xGet(&strItem); + //tell the controls that they are now + //at their default value + //since they are, this prevents + //later updates from thinking a save is + //necessary + m_pRight[x]->Set(strItem,true); + strRights=strRights+strItem; + } + + //encrypt + k->GZEncrypt(&strName,false); + k->GZEncrypt(&strRights,false); + strReports=m_strGroupsReports; + + if(!strReports.IsEmpty()) + k->GZEncrypt(&strReports,false); + + if(Update) + { + //Get the hash + strGroupID=m_cbGroup.GetCurrentRowID(); + + //get id, or previous id if combo is in the + //middle of changing + if(strGroupID.Compare(m_strLastComboID)!=0) + { + strGroupID=m_strLastComboID; + //flag so filllistbox doesn't get called later + HereFromCBCloseup=true; + } + + if(strGroupID=="1" && m_bMasterMode==false) + { + //AfxMessageBox("To protect your access the group can not be modified."); + return; + } + + //check if attempting to use the same group name + //as another record users + q.Format("SELECT groups.id, groups.a FROM groups " + "WHERE (((groups.id)<>%s) AND ((groups.a)=\"%s\"));",strGroupID,strName); + + rs->Query(q); + if(!rs->IsEmpty())//group name already exists + { + AfxMessageBox("That group name is already in use!"); + return; + + } + + + strHash=strGroupID; + strHash=strHash+strName+strRights; + k->GZHash(&strHash); + //make up the execute query string + q.Format("UPDATE groups SET groups.a = \"%s\", groups.b = \"%s\", " + "groups.c = \"%s\", groups.d = \"%s\" WHERE (((groups.id)=%s));" + ,strName,strRights,strHash,strReports, strGroupID); + //run the execute query + rs->Ex(q); + + + if(!HereFromCBCloseup) + FillListBox(); + //bail + return; + } + else//it's a wholesale new record + { + //see if another record is already using + //this name... + q.Format("SELECT groups.* FROM groups " + "WHERE (((groups.a)=\"%s\"));",strName); + rs->Query(q); + if(!rs->IsEmpty())//group name already exists + { + AfxMessageBox("That group name is already in use!"); + return; + + } + + rs->AddNewRecord(); + rs->UpdateField("a",&strName); + rs->UpdateField("b",&strRights); + rs->UpdateField("d",&strReports); + if(!rs->SaveRecord()) + CDialog::OnCancel(); + + //now get the autonumber id assigned to this record + q.Format("SELECT groups.* FROM groups WHERE (((groups.a)=\"%s\"));",strName); + rs->Query(q); + rs->FetchField("id",&lID); + strHash.Format("%u",lID); + //this is so after adding new group + //list centers on it + m_strSelectedGroup=strHash; + + strHash=strHash+strName+strRights; + k->GZHash(&strHash); + //now save the hash + rs->UpdateField("c",&strHash); + if(!rs->SaveRecord()) + { + AfxMessageBox("If you just received an error about creating a duplicate\r\n" + "You were probably trying to use the same group name twice.\r\n" + "Each group name must be unique"); + //pretend user pressed cancel + m_bAddMode=true; + OnDelete(); + } + + //reset this bad boy + m_strGroupsReportsInitialValue=m_strGroupsReports; + //bob's your uncle + return; + + } + +} + + +//********************************************* +void CGroupsDlg::OnOk() +{}//do nothing + + +//**************************************** +void CGroupsDlg::OnKillfocusGroupname() +{ + if(!m_bAddMode) + Save(true); +} + +//*********************************** +bool CGroupsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + return true; +} + + + +void CGroupsDlg::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + /* + return; + + if(m_pApp->m_lusrID!=1) return;//only the manager! + CKD d; + d.DoModal(); + // TODO: Add your message handler code here and/or call default + m_bMasterMode=!m_bMasterMode; + if(m_bMasterMode) + SetWindowText("User groups - Edit / Add."); + else + SetWindowText("User groups - Edit / Add"); + //CDialog::OnRButtonDblClk(nFlags, point); + */ +} + +//********************************************** +void CGroupsDlg::OnBtnremoverpt() +{ + CString fname,vname; + int nFound=0; + m_lbReportsGroup.RebuildIndex(); + int x=m_lbReportsGroup.SelectionCount(); + if(x<1) return; + + for(int y=0;yQuery("SELECT rptsmaster.virtualname, rptsmaster.filename " + "FROM rptsmaster WHERE (((rptsmaster.x)=True)) ORDER BY rptsmaster.virtualname;"); + + ASSERT(!lbrs->IsEmpty()); + if(lbrs->IsEmpty()) return; + + lbrs->MoveFirst(); + + do + { + lbrs->FetchField("virtualname",&vname); + lbrs->FetchField("filename",&fname); + //see if it's in the group if so put in group list + if(!GroupHasReports) + {//just put into the pool list + m_lbReportsPool.AddRow(vname,fname); + } + else + {//see where it goes and put it in the right list + if(m_strGroupsReports.Find(fname,0)==-1)//not found + m_lbReportsPool.AddRow(vname,fname);//into the pool + else + m_lbReportsGroup.AddRow(vname,fname);//into the group + + + } + + + + + }while(lbrs->MoveForward()); + + + +} + +void CGroupsDlg::OnBtndone() +{ +Save(true); +CDialog::OnOK(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.h new file mode 100644 index 0000000..86dde97 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/GroupsDlg.h @@ -0,0 +1,153 @@ +#if !defined(AFX_GROUPSDLG_H__159836E3_1460_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_GROUPSDLG_H__159836E3_1460_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GroupsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGroupsDlg dialog +#include "gzrightsbutton.h" +#include "gzk.h" +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +#include "gzListBox.h" + + +//**************************************************** +//SECURITY RIGHTS +#define NUMRIGHTS 27 +#define RIGHTS_WORKORDERSTAT 0 //workorder status screen +#define RIGHTS_WORKORDER 1 //workorder entry screen +#define RIGHTS_SHIPPING 2 // shipping and receiving +#define RIGHTS_MAIL 3 //use the mail system (no read only here) +#define RIGHTS_DBASEUTILS 4 // use the database utilities +#define RIGHTS_SECURITYGROUPS 5 // rights to create edit GROUPS +#define RIGHTS_SEARCH 6 // access to the search screen +#define RIGHTS_REPORTS 7 // access to the reporting screen not workorder printing +#define RIGHTS_PRINTING 8 //able to change printing setup +#define RIGHTS_CLIENTS 9 //CLIENTS SCREEN +#define RIGHTS_RATES 10 //RATES SCREEN +#define RIGHTS_ZONES 11 +#define RIGHTS_UNITS 12 +#define RIGHTS_MODELS 13 +#define RIGHTS_PARTS 14 +#define RIGHTS_TASKS 15 +#define RIGHTS_PROJECTS 16 +#define RIGHTS_WOTYPES 17 //BLAH +#define RIGHTS_ADDRESSBOOKS 18 //MODIFY ADDRESS BOOKS +#define RIGHTS_USERS 19 //RIGHT TO EDIT USERS AND PLACE IN GROUPS +#define RIGHTS_PM 20 //preventative maintenance screen +#define RIGHTS_LOANERS 21 //loaner equipment screen +#define RIGHTS_SCHEDULE 22//scheduling screen +#define RIGHTS_SCHED_GROUPS 23//schedule groups screen +#define RIGHTS_SCHED_MARKERS 24//schedule groups screen +#define RIGHTS_USERPREFS 25//user preferences +#define RIGHTS_ARAS_REQUESTS 26//ARAS service requests + +//********************************************************** + + + +class CGroupsDlg : public CDialog +{ +// Construction +public: + bool m_bReadOnly; + + CString m_strGroupsReports; + CString m_strGroupsReportsInitialValue; + void DisplayReportLists(); + ~CGroupsDlg(); + bool m_bMasterMode; + CString m_strLastComboID; + void Save(bool Update/*or new*/); + void SetFields(); + bool SaveField(CEdit *edControl,CString fldname,bool AllowEmpty); + + void FillListBox(); + CGroupsDlg(CWnd* pParent = NULL); // standard constructor + GZK* k; + CSpApp* m_pApp; + bool m_bAddMode; + CgzRightsButton* m_pRight[NUMRIGHTS]; + CString m_strSelectedGroup; + +// Dialog Data + //{{AFX_DATA(CGroupsDlg) + enum { IDD = IDD_GROUPS }; + CgzRightsButton m_26; + CgzRightsButton m_25; + CgzRightsButton m_24; + CgzRightsButton m_23; + CButton m_btnDone; + CgzListBox m_lbReportsPool; + CgzListBox m_lbReportsGroup; + CgzRightsButton m_9; + CgzRightsButton m_8; + CgzRightsButton m_21; + CgzRightsButton m_22; + CgzRightsButton m_20; + CgzRightsButton m_19; + CgzRightsButton m_18; + CgzRightsButton m_17; + CgzRightsButton m_16; + CgzRightsButton m_15; + CgzRightsButton m_14; + CgzRightsButton m_13; + CgzRightsButton m_12; + CgzRightsButton m_11; + CgzRightsButton m_10; + CgzRightsButton m_7; + CgzRightsButton m_6; + CgzRightsButton m_5; + CgzRightsButton m_4; + CgzRightsButton m_3; + CgzRightsButton m_2; + CgzRightsButton m_1; + CgzRightsButton m_0; + CEdit m_edName; + CStatic m_lblGroupList; + CgzCombo m_cbGroup; + CButton m_btnDelete; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGroupsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL +private: + GZRset* rs; + GZRset* lbrs; +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGroupsDlg) + afx_msg void OnAdd(); + afx_msg void OnDelete(); + virtual BOOL OnInitDialog(); + afx_msg void OnCloseupGroupCombo(); + afx_msg void OnOk(); + afx_msg void OnKillfocusGroupname(); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnBtnremoverpt(); + afx_msg void OnBtnaddrpt(); + afx_msg void OnDblclkLbrptgroup(); + afx_msg void OnDblclkLbrptpool(); + afx_msg void OnBtndone(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GROUPSDLG_H__159836E3_1460_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.cpp new file mode 100644 index 0000000..1a4641d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.cpp @@ -0,0 +1,226 @@ +// KD.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "KD.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CKD dialog + + +CKD::CKD(CWnd* pParent /*=NULL*/) +: CDialog(CKD::IDD, pParent) +{ + //{{AFX_DATA_INIT(CKD) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error 69 - email tech support"); + rs->SetConnect(m_pApp->strConnectString); +*/ + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CKD"); + k=new GZK; +} + + +void CKD::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CKD) + DDX_Control(pDX, IDC_LBLK, m_lblK); + DDX_Control(pDX, IDC_LBLINFO, m_lblInfo); + DDX_Control(pDX, IDC_LBLC, m_lblC); + DDX_Control(pDX, IDC_EDK, m_edK); + DDX_Control(pDX, IDC_EDC, m_edC); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CKD, CDialog) +//{{AFX_MSG_MAP(CKD) +ON_BN_CLICKED(IDC_BTNSAVE, OnBtnsave) +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CKD message handlers + +void CKD::OnBtnsave() +{ + + CString key,keyvalue; + CString comp,company; + + CString kCompHash; + CString temp,q; + int firstcomma,secondcomma,thirdcomma; + + m_edC.GetWindowText(company); + m_edK.GetWindowText(keyvalue); + comp=company; + key=keyvalue; + +// COMPARE AGAINST ZAP LIST + + k->GZHash(&comp); + k->GZDecrypt(&key,false); + firstcomma=key.Find(',',0); + secondcomma=key.Find(',',firstcomma+1); + thirdcomma=key.Find(',',secondcomma+1); + if(firstcomma==-1 || secondcomma==-1 || thirdcomma==-1) + { + AfxMessageBox(k->InLineDecrypt("gE8Brl9JYwu9G+0BoCLatUpt2Ug5YXYs+1lBHILkRHB7hcyeWE6o3q8ztyj+9wTPP9+OzYAj" +"ejaF8zlelDCG1Pz34nBTyKwSovUmpyTTNzQ")); + /*Key or registered name is not valid. +Please check your entries and try again.*/ + return; + } + + kCompHash=key.Left(firstcomma); + + if(kCompHash!=comp) + { + AfxMessageBox(k->InLineDecrypt("gE8Brl9JYwu9G+0BoCLatUpt2Ug5YXYs+1lBHILkRHB7hcyeWE6o3q8ztyj+9wTPP9+OzYAj" +"ejaF8zlelDCG1Pz34nBTyKwSovUmpyTTNzQ")); + /*Key or registered name is not valid. +Please check your entries and try again.*/ + return; + + } + + //v1.9.4.5 TEAM ESD IMMEDIATE KEY CHECK + if(kCompHash=="1575153704")//TEAM ESD + { + AfxMessageBox(k->InLineDecrypt("gE8Brl9JYwu9G+0BoCLatUpt2Ug5YXYs+1lBHILkRHB7hcyeWE6o3q8ztyj+9wTPP9+OzYAj" +"ejaF8zlelDCG1Pz34nBTyKwSovUmpyTTNzQ")); + /*Key or registered name is not valid. +Please check your entries and try again.*/ + return; + } + + + + + + //*************v1.9.4.5 changes*********************************************** + //v1.9.4.5 add expiry date check as in the spDoc validate function that is + //run at each login against the key code + //expiry date? + temp=key.Right(key.GetLength()-thirdcomma-1); + if(temp==k->InLineDecrypt("Md2gXbFO5Vu4MqQpfyEWdw"/*15 eval key*/) + || temp==k->InLineDecrypt("hm0s/6NFOzjXMUUd/HaGEA") /*69 licensed key*/ + || temp==k->InLineDecrypt("o2jDhqik1/EKD7zT1MBbJQ") /*5 eval key*/) + { + temp="";//do nothing, it's got a valid code number at the end, no worries + //this is just a way to avoid re-writing the borrowed code above + + } + else//the date portion at the end isn't a code number, it should be a date + //verify it's a valid date + { + //If we are here, then this key has an expiry date, check if expired and announce time left? + COleDateTime dtData; + COleDateTime dtNow=COleDateTime::GetCurrentTime(); + COleDateTimeSpan dtSpan; + dtData.ParseDateTime(temp); + CString m_strExpiryDays; + CString strTemp; + temp.Empty();//don't leave it floating around in memory + if(dtData.GetStatus()!=0)//couldn't parse the date and time + { + AfxMessageBox(k->InLineDecrypt("gE8Brl9JYwu9G+0BoCLatUpt2Ug5YXYs+1lBHILkRHB7hcyeWE6o3q8ztyj+9wTPP9+OzYAj" +"ejaF8zlelDCG1Pz34nBTyKwSovUmpyTTNzQ")); + /*Key or registered name is not valid. +Please check your entries and try again.*/ + return; + + } + + + } + + +//**********END V1.9.4.5 changes***************************************** + + + + + + q.Format("UPDATE defaults SET defaults.regto = \"%s\", defaults.[key] = \"%s\";",company,keyvalue); + if(!rs->Ex(q)) + { + AfxMessageBox("Error saving information"); + return; + } + else + { + AfxMessageBox(k->InLineDecrypt("ASRkzgxvjiV1EvBmxwtBVDVZ8mV1DqMqb6LMrZSb1PvJqc6eiDW1eIzpxeqgGH07O63CorO9" +"+pnHKPzq2fOIWnO7cnQUX0ptXc+WVZbNvOMHOAxiTJ3TYzdkdDlaGCON")); + + /*AyaNova unlocked successfully! + +Restart AyaNova at all computers +for changes to take effect.*/ + rs->Close(); + + if(k!=NULL) + { + delete k; + k=NULL; + } + + CDialog::OnOK(); + } +} + +BOOL CKD::OnInitDialog() +{ + CDialog::OnInitDialog(); + CString s; + s="QWCsICmK0VAp3QHZkVXA6zD5n8y6eFWhlrv9f3tN7iI"; + /*Enter registration key*/ + k->GZDecrypt(&s,false); + + SetWindowText(s); + + m_lblInfo.SetWindowText(k->InLineDecrypt("sqFcTepw4hTfxfEcWmBEnVoqtOQdRplq7YTuO15bhbpGHizIoQxNjPsvveG/VPqTr9cRA1gV" +"KtUz5WpV8cUdKtAopAVu/6fo8t3P8bAeRwOdaPRYwMnj6Tnal8xZGiC5ltQDIudvV2hUK+b1" +"IkF/JnIEcODBNqJrPO1eHaGc0HE=")); + + /*Thank you for registering AyaNova! + +Enter your registered company name +and keycode in the text boxes provided below. +*/ + + m_lblC.SetWindowText(k->InLineDecrypt("7/dnsYwUjm7Bg8gxlE7K4eFK4UxUsu+Hha4OI04vLRs"));//registered to + m_lblK.SetWindowText(k->InLineDecrypt("VIXCLaT+N2aEpijLHKeTUw"));//keycode + + rs->Query("SELECT defaults.regto, defaults.key FROM defaults;"); + rs->FetchField("regto",&s); + m_edC.SetWindowText(s); + rs->FetchField("key",&s); + m_edK.SetWindowText(s); + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +CKD::~CKD() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + + if(k!=NULL) delete k; +} + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.h new file mode 100644 index 0000000..a5b36b2 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/KD.h @@ -0,0 +1,56 @@ +#if !defined(AFX_KD_H__C319C5CF_5D50_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_KD_H__C319C5CF_5D50_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// KD.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CKD dialog +#include "gzk.h" +#include "gzrset.h" +class CKD : public CDialog +{ +// Construction +public: + + ~CKD(); + CKD(CWnd* pParent = NULL); // standard constructor +CSpApp* m_pApp; + GZK* k; + GZRset* rs; +// Dialog Data + //{{AFX_DATA(CKD) + enum { IDD = IDD_KD }; + CStatic m_lblK; + CStatic m_lblInfo; + CStatic m_lblC; + CEdit m_edK; + CEdit m_edC; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CKD) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CKD) + afx_msg void OnBtnsave(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_KD_H__C319C5CF_5D50_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.cpp new file mode 100644 index 0000000..bdba0c5 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.cpp @@ -0,0 +1,276 @@ +// Label.cpp : implementation file +// + +#include "stdafx.h" +#include "Resource.h" +#include "Label.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLabel + +CLabel::CLabel() +{ + m_crText = GetSysColor(COLOR_WINDOWTEXT); + m_hBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE)); + + ::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT),sizeof(m_lf),&m_lf); + + m_font.CreateFontIndirect(&m_lf); + m_bTimer = FALSE; + m_bState = FALSE; + m_bLink = TRUE; + m_hCursor = NULL; + m_Type = None; + + m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE)); +} + + +CLabel::~CLabel() +{ + m_font.DeleteObject(); + ::DeleteObject(m_hBrush); +} + +CLabel& CLabel::SetText(const CString& strText) +{ + SetWindowText(strText); + return *this; +} + +CLabel& CLabel::SetTextColor(COLORREF crText) +{ + m_crText = crText; + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetFontBold(BOOL bBold) +{ + m_lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL; + ReconstructFont(); + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetFontUnderline(BOOL bSet) +{ + m_lf.lfUnderline = bSet; + ReconstructFont(); + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetFontItalic(BOOL bSet) +{ + m_lf.lfItalic = bSet; + ReconstructFont(); + RedrawWindow(); + return *this; +} + +CLabel& CLabel::SetSunken(BOOL bSet) +{ + if (!bSet) + ModifyStyleEx(WS_EX_STATICEDGE,0,SWP_DRAWFRAME); + else + ModifyStyleEx(0,WS_EX_STATICEDGE,SWP_DRAWFRAME); + + return *this; +} + +CLabel& CLabel::SetBorder(BOOL bSet) +{ + if (!bSet) + ModifyStyle(WS_BORDER,0,SWP_DRAWFRAME); + else + ModifyStyle(0,WS_BORDER,SWP_DRAWFRAME); + + return *this; +} + +CLabel& CLabel::SetFontSize(int nSize) +{ + nSize*=-1; + m_lf.lfHeight = nSize; + ReconstructFont(); + RedrawWindow(); + return *this; +} + + +CLabel& CLabel::SetBkColor(COLORREF crBkgnd) +{ + if (m_hBrush) + ::DeleteObject(m_hBrush); + + m_hBrush = ::CreateSolidBrush(crBkgnd); + return *this; +} + +CLabel& CLabel::SetFontName(const CString& strFont) +{ + strcpy(m_lf.lfFaceName,strFont); + ReconstructFont(); + RedrawWindow(); + return *this; +} + + +BEGIN_MESSAGE_MAP(CLabel, CStatic) + //{{AFX_MSG_MAP(CLabel) + ON_WM_CTLCOLOR_REFLECT() + ON_WM_TIMER() + ON_WM_LBUTTONDOWN() + ON_WM_SETCURSOR() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLabel message handlers + +HBRUSH CLabel::CtlColor(CDC* pDC, UINT nCtlColor) +{ + // TODO: Change any attributes of the DC here + + // TODO: Return a non-NULL brush if the parent's handler should not be called + + if (CTLCOLOR_STATIC == nCtlColor) + { + pDC->SelectObject(&m_font); + pDC->SetTextColor(m_crText); + pDC->SetBkMode(TRANSPARENT); + } + + + if (m_Type == Background) + { + if (!m_bState) + return m_hwndBrush; + } + + return m_hBrush; +} + +void CLabel::ReconstructFont() +{ + m_font.DeleteObject(); + BOOL bCreated = m_font.CreateFontIndirect(&m_lf); + + ASSERT(bCreated); +} + + +CLabel& CLabel::FlashText(BOOL bActivate) +{ + if (m_bTimer) + { + SetWindowText(m_strText); + KillTimer(1); + } + + if (bActivate) + { + GetWindowText(m_strText); + m_bState = FALSE; + + m_bTimer = TRUE; + SetTimer(1,500,NULL); + m_Type = Text; + } + + return *this; +} + +CLabel& CLabel::FlashBackground(BOOL bActivate) +{ + + if (m_bTimer) + KillTimer(1); + + if (bActivate) + { + m_bState = FALSE; + + m_bTimer = TRUE; + SetTimer(1,500,NULL); + + m_Type = Background; + } + + return *this; +} + + +void CLabel::OnTimer(UINT nIDEvent) +{ + m_bState = !m_bState; + + switch (m_Type) + { + case Text: + if (m_bState) + SetWindowText(""); + else + SetWindowText(m_strText); + break; + + case Background: + InvalidateRect(NULL,FALSE); + UpdateWindow(); + break; + } + + CStatic::OnTimer(nIDEvent); +} + +CLabel& CLabel::SetLink(BOOL bLink) +{ + m_bLink = bLink; + + if (bLink) + ModifyStyle(0,SS_NOTIFY); + else + ModifyStyle(SS_NOTIFY,0); + + return *this; +} + +void CLabel::OnLButtonDown(UINT nFlags, CPoint point) +{ + + if(!m_strURL.IsEmpty())//do this only if there was an url + ShellExecute(NULL,"open",m_strURL,NULL,NULL,SW_SHOWNORMAL); + + //otherwise it's probably a button for something internal + CStatic::OnLButtonDown(nFlags, point); +} + +BOOL CLabel::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + if (m_hCursor) + { + ::SetCursor(m_hCursor); + return TRUE; + } + + return CStatic::OnSetCursor(pWnd, nHitTest, message); +} + +CLabel& CLabel::SetLinkCursor(HCURSOR hCursor) +{ + m_hCursor = hCursor; + return *this; +} + +CLabel& CLabel::SetLinkURL(const CString& strText) +{ + m_strURL.Format("%s",strText); + return *this; +} \ No newline at end of file diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.h new file mode 100644 index 0000000..69e188f --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Label.h @@ -0,0 +1,79 @@ +#if !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_) +#define AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// Label.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLabel window +enum FlashType {None, Text, Background }; + +class CLabel : public CStatic +{ +// Construction +public: + CLabel(); + CLabel& SetBkColor(COLORREF crBkgnd); + CLabel& SetTextColor(COLORREF crText); + CLabel& SetText(const CString& strText); + CLabel& SetFontBold(BOOL bBold); + CLabel& SetFontName(const CString& strFont); + CLabel& SetFontUnderline(BOOL bSet); + CLabel& SetFontItalic(BOOL bSet); + CLabel& SetFontSize(int nSize); + CLabel& SetSunken(BOOL bSet); + CLabel& SetBorder(BOOL bSet); + CLabel& FlashText(BOOL bActivate); + CLabel& FlashBackground(BOOL bActivate); + CLabel& SetLink(BOOL bLink); + CLabel& SetLinkCursor(HCURSOR hCursor); + CLabel& SetLinkURL(const CString& strText); + +// Attributes +public: +protected: + void ReconstructFont(); + COLORREF m_crText; + HBRUSH m_hBrush; + HBRUSH m_hwndBrush; + LOGFONT m_lf; + CFont m_font; + CString m_strText; + CString m_strURL;//added to use separate url + BOOL m_bState; + BOOL m_bTimer; + BOOL m_bLink; + FlashType m_Type; + HCURSOR m_hCursor; + // Operations +public: +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLabel) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CLabel(); + + // Generated message map functions +protected: + //{{AFX_MSG(CLabel) + afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.cpp new file mode 100644 index 0000000..fe3d360 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.cpp @@ -0,0 +1,823 @@ +// LoanersDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "LoanersDlg.h" +#include "loanerseditdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLoanersDlg dialog + + +CLoanersDlg::CLoanersDlg(CWnd* pParent /*=NULL*/) +: CDialog(CLoanersDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLoanersDlg) + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + + rsPrint=m_pApp->rsPool->GetRSPrint("CLoanersDlg rsPrint"); + + + rs=m_pApp->rsPool->GetRS("CLoanersDlg"); + + m_strCriteria=" WHERE (((rentals.returned)=False))"; + m_nDateCriteriaX=0; + //show rented out items only when startup + m_nTypeCriteriaX=2; +} + +CLoanersDlg::~CLoanersDlg() +{ + m_pApp->rsPool->ReleaseRS(&rsPrint->m_nID); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CLoanersDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLoanersDlg) + DDX_Control(pDX, IDC_CKRECEIVEDDATE, m_ckReceivedDate); + DDX_Control(pDX, IDC_CKDUEDATE, m_ckDueDate); + DDX_Control(pDX, IDC_CKANYDATE, m_ckAnyDate); + DDX_Control(pDX, IDC_CKSENTDATE, m_ckSentDate); + DDX_Control(pDX, IDC_CKSHOWRETURNED, m_ckShowReturned); + DDX_Control(pDX, IDC_CKSHOWOUT, m_ckShowOut); + DDX_Control(pDX, IDC_CKSHOWALLITEMS, m_ckShowAll); + DDX_Control(pDX, IDC_REPORT, m_rc); + DDX_Control(pDX, IDC_lblTo, m_lblTo); + DDX_Control(pDX, IDC_DTTO, m_dtTo); + DDX_Control(pDX, IDC_DTFROM, m_dtFrom); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_LBL_SHOW, m_lblShow); +} + + +BEGIN_MESSAGE_MAP(CLoanersDlg, CDialog) +//{{AFX_MSG_MAP(CLoanersDlg) +ON_BN_CLICKED(IDC_CKANYDATE, OnCkanydate) +ON_BN_CLICKED(IDC_CKSENTDATE, OnCksentdate) +ON_BN_CLICKED(IDC_CKDUEDATE, OnCkduedate) +ON_BN_CLICKED(IDC_CKRECEIVEDDATE, OnCkreceiveddate) +ON_BN_CLICKED(IDC_CKSHOWRETURNED, OnCkshowreturned) +ON_BN_CLICKED(IDC_CKSHOWOUT, OnCkshowout) +ON_BN_CLICKED(IDC_CKSHOWALLITEMS, OnCkshowallitems) +ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTTO, OnDatetimechangeDtto) +ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTFROM, OnDatetimechangeDtfrom) +ON_NOTIFY(RVN_ITEMDBCLICK, IDC_REPORT, OnRvnItemDbClick) +ON_NOTIFY(RVN_COLUMNCLICK, IDC_REPORT, OnColumnClick) +ON_BN_CLICKED(IDC_BTNPRINT, OnBtnprint) +//}}AFX_MSG_MAP +ON_COMMAND(ID_NEW, OnNew) +ON_COMMAND(ID_DELETE, OnDelete) +ON_COMMAND(ID_CLOSE_LOANERS_AND_RENTALS, OnCloseThisScreen) +ON_COMMAND(ID_HELPONLOANERS, OnHelponloaners) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLoanersDlg message handlers +void CLoanersDlg::OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + CLoanersEditDlg d; + CString item=m_rc.GetItemText(lpnmrv->iItem,6); + d.SetRentalID(&item); + if(d.DoModal()==IDOK) + FillView(); + + + + } + + *pResult = FALSE; +} + +BOOL CLoanersDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + m_resize.Create( this ); + ShowWindow(SW_HIDE); + Security(); + CWaitCursor wait; + //defaults + m_ckShowOut.SetCheck(TRUE); + m_ckAnyDate.SetCheck(TRUE); + + CString profile,q; + q.Format("SELECT users.rentalprofile " + "FROM users WHERE (((users.id)=%u));",m_pApp->m_lusrID); + rs->Query(q); + rs->FetchField("rentalprofile",&profile); + + + + m_ilReport.Create(IDB_BM2, 16, 1, RGB(255,0,255)); + m_rc.SetImageList(&m_ilReport); + + //ShowWindow(SW_MAXIMIZE); + + m_rc.InsertColor(0, 0x00C0D8C0); + m_rc.InsertColor(1, ::GetSysColor(COLOR_GRAYTEXT)); + m_rc.InsertColor(2, 0x00D0C0C0); + m_rc.InsertColor(3, 0x00804000); + + + RVCOLUMN rvc; + + rvc.nFormat = RVCF_TEXT|RVCF_EX_AUTOWIDTH|RVCF_EX_FIXEDWIDTH|RVCF_SUBITEM_IMAGE; + rvc.iImage = 1; + rvc.lpszText = _T("Status"); + rvc.iWidth = 60; + m_rc.DefineColumn(0, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Item"; + rvc.iWidth = 60; + m_rc.DefineColumn(1, &rvc); + + rvc.lpszText = "At"; + rvc.iWidth = 60; + m_rc.DefineColumn(2, &rvc); + + rvc.lpszText = "Out"; + rvc.iWidth = 60; + m_rc.DefineColumn(3, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Due"; + rvc.iWidth = 60; + m_rc.DefineColumn(4, &rvc); + + rvc.lpszText = "Rcvd."; + rvc.iWidth = 60; + m_rc.DefineColumn(5, &rvc); + + rvc.nFormat = RVCF_TEXT | RVCF_EX_FIXEDWIDTH; + rvc.lpszText = "id"; + rvc.iWidth = 0; + m_rc.DefineColumn(6, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Ref"; + rvc.iWidth = 60; + m_rc.DefineColumn(7, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Desc."; + rvc.iWidth = 60; + m_rc.DefineColumn(8, &rvc); + + //setup according to users preferences + if(!profile.IsEmpty()) + m_rc.GetProfile(&profile); + else + { + + //not needed when setting by pref + //but if there are no preferences then you would need it + + m_rc.ActivateColumn(0, 0); + m_rc.ActivateColumn(1, 1); + m_rc.ActivateColumn(2, 2); + m_rc.ActivateColumn(3, 3); + m_rc.ActivateColumn(4, 4); + m_rc.ActivateColumn(5, 5); + m_rc.ActivateColumn(6, 6); + m_rc.ActivateColumn(7, 7); + m_rc.ActivateColumn(8, 8); + + + } + + + + m_rc.ModifyStyle(0, RVS_SINGLESELECT); + //m_rc.ModifyStyle(0, RVS_SHOWCOLORALTERNATE); + + + //turn off the grids + m_rc.ModifyStyle(RVS_SHOWVGRID, 0); + m_rc.ModifyStyle(RVS_SHOWHGRID, 0); + + + + //retrieve the loaner items and display them + FillView(); + Layout(); + + //Use the current width and height as the minimum size + m_resize.SetMinimumTrackingSize(); + + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + + + //ShowWindow(SW_MAXIMIZE); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CLoanersDlg::FillView() +{ + CString q; + COleDateTime dtDefault; + dtDefault.SetDate(1968,03,12); + int x=0; + q.Format("SELECT rentals.id, rentals.ref, IIf(IsNull([sn]),[rentals].[description] & [parts].[description],[company_person] & " + "\" \" & [unitmodels].[description] & \" \" & [unitmodels].[model]) AS [desc], [rentals]![description] & " + "IIf(IsNull([parts]![partnumber]),\"\",\"part:\" & [parts]![partnumber]) & " + "IIf(IsNull([units]![sn]),\"\",\"unit:\" & [units]![sn]) AS item, [loanedto] & " + "IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) " + "AS rentor, Format([dateout],\"Short Date\") AS outdate, IIf([datedue]=#%s#,\"na\",Format([datedue], " + "\"Short Date\")) AS duedate, IIf([datereturn]=#%s#,\"Out\",Format([datereturn],\"Short Date\")) " + "AS retdate, rentals.returned, DateDiff(\"d\",Now(),[datedue]) AS duedays " + "FROM ((((rentals LEFT JOIN clients ON rentals.clientlink = clients.id) LEFT JOIN " + "units ON rentals.unitlink = units.id) LEFT JOIN parts ON rentals.partlink = parts.id) " + "LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "%s %s;",dtDefault.Format(_T("%m/%d/%Y")), + dtDefault.Format(_T("%m/%d/%Y")),m_strCriteria,m_strOrderBy); + /* + q.Format("SELECT rentals.id, rentals.ref, [rentals]![description] " + "& IIf(IsNull([parts]![partnumber]),\"\"," + "\"part:\" & [parts]![partnumber] ) & " + "IIf(IsNull([units]![sn]),\"\",\"unit:\" & " + "[units]![sn]) AS item, [loanedto] & " + "IIf(IsNull([clients]![company]), " + "[clients]![first] & \" \" & [clients]![last], " + "[clients]![company]) AS rentor, Format([dateout], " + "\"Short Date\") AS outdate, IIf([datedue]=#%s# " + ",\"na\",Format([datedue],\"Short Date\")) AS " + "duedate, IIf([datereturn]=#%s#,\"Out\", " + "Format([datereturn],\"Short Date\")) AS retdate, " + "rentals.returned, DateDiff(\"d\",Now(),[datedue]) AS duedays " + "FROM ((rentals LEFT JOIN clients ON " + "rentals.clientlink = clients.id) LEFT JOIN units " + "ON rentals.unitlink = units.id) LEFT JOIN parts " + "ON rentals.partlink = parts.id %s %s;",dtDefault.Format(_T("%m/%d/%Y")), + dtDefault.Format(_T("%m/%d/%Y")),m_strCriteria,m_strOrderBy); + */ + + //"WHERE ( ((rentals.datereturn) Between #06/01/2000# And #06/30/2000#) AND ((rentals.returned)=False));"); + // "WHERE ( ((rentals.returned)=True) AND ((rentals.dateout) Between #1/1/1990# And #1/1/2000#));"); + + + //WHERE (((rentals.returned)=True) AND ((rentals.dateout) Between #1/1/1990# And #1/1/2001#)) + //rs->Query("SELECT rentals.* FROM rentals WHERE (((rentals.id)=0));"); + + rs->Query(q); + //m_pApp->ShowStuff(q); + m_rc.DeleteAllItems(); + + + if(rs->IsEmpty()) + return; + + + + + CString strData,strItem,strRentor,strOutdate,strDueDays,strDuedate,strRetdate,strID,strRef,strDesc; + COleDateTime dtDate; + long lData; + long lDueDays; + bool bReturned; + int nDueDays; + rs->MoveFirst(); + + + do + { + + rs->FetchField("item",&strItem); + //avoid the underline in the report control + //for a single & + strItem.Replace("&","&&"); + + + rs->FetchField("rentor",&strRentor); + strRentor.Replace("&","&&"); + + rs->FetchField("outdate",&strOutdate); + + rs->FetchField("duedate",&strDuedate); + + rs->FetchField("retdate",&strRetdate); + + rs->FetchField("duedays",&lDueDays); + nDueDays=lDueDays;//atoi(strDueDays); + + rs->FetchField("id",&lData); + strID.Format("%u",lData); + + rs->FetchField("returned",&bReturned); + + rs->FetchField("ref",&strRef); + + rs->FetchField("desc",&strDesc); + + + + + + //Set the look of the row and insert it + + //LATE! + RVITEM rvi; + rvi.iItem = x; + rvi.iSubItem = 0; + rvi.nMask = RVIM_IMAGE|RVIM_PREVIEW|RVIM_STATE|RVIM_LPARAM; + rvi.nState = 0; + rvi.nPreview = 0;//no preview necessary + if(bReturned) + rvi.iImage=3;//blank + else + { + rvi.iImage=0;//green light - default + + if(nDueDays<0)//overdue + rvi.iImage=2;//redlight + + if(nDueDays==0)//due today + rvi.iImage=1;//orange light + + } + + rvi.lParam = x; + m_rc.InsertItem(&rvi); + + + //ITEM + rvi.iSubItem = 1; + rvi.nMask = RVIM_TEXT; + rvi.lpszText = strItem.GetBuffer(strItem.GetLength()); + m_rc.SetItem(&rvi); + + //AT + rvi.iSubItem = 2; + rvi.lpszText = strRentor.GetBuffer(strRentor.GetLength()); + m_rc.SetItem(&rvi); + + //OUT + rvi.iSubItem = 3; + rvi.lpszText = strOutdate.GetBuffer(strOutdate.GetLength()); + m_rc.SetItem(&rvi); + + //DUE + rvi.iSubItem = 4; + rvi.lpszText = strDuedate.GetBuffer(strDuedate.GetLength()); + m_rc.SetItem(&rvi); + + //BACK + rvi.iSubItem = 5; + if(bReturned==false) + rvi.lpszText=" "; + else + rvi.lpszText = strRetdate.GetBuffer(strRetdate.GetLength()); + m_rc.SetItem(&rvi); + + + //ID + rvi.iSubItem = 6; + rvi.lpszText = strID.GetBuffer(strID.GetLength()); + m_rc.SetItem(&rvi); + + //ref + rvi.iSubItem = 7; + rvi.lpszText = strRef.GetBuffer(strRef.GetLength()); + m_rc.SetItem(&rvi); + + //description + rvi.iSubItem = 8; + rvi.lpszText = strDesc.GetBuffer(strDesc.GetLength()); + m_rc.SetItem(&rvi); + + x++; + + }while(rs->MoveForward()); + + +} + + + + + +//SET CRITERIA FOR QUERY: +//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +void CLoanersDlg::OnCkanydate() +{ + m_nDateCriteriaX=0; + ShowDateFields(false); + Criteria(); +} + +void CLoanersDlg::OnCksentdate() +{/* + if(m_nDateCriteriaX==0)//were not dates showing before + { + //so just show dates and exit + m_ckAnyDate.SetCheck(FALSE); + ShowDateFields(true); + m_nDateCriteriaX=(1); + return; + } + */ + ShowDateFields(true); + m_nDateCriteriaX=(1); + Criteria(); +} + +void CLoanersDlg::OnCkduedate() +{/* + if(m_nDateCriteriaX==0)//were not dates showing before + { + //so just show dates and exit + m_ckAnyDate.SetCheck(FALSE); + ShowDateFields(true); + m_nDateCriteriaX=(2); + return; +}*/ + ShowDateFields(true); + m_nDateCriteriaX=(2); + Criteria(); +} + +void CLoanersDlg::OnCkreceiveddate() +{ +/* +if(m_nDateCriteriaX==0)//were not dates showing before +{ +//so just show dates and exit +m_ckAnyDate.SetCheck(FALSE); +ShowDateFields(true); +m_nDateCriteriaX=(3); +return; +}*/ + ShowDateFields(true); + m_nDateCriteriaX=(3); + Criteria(); + +} + +void CLoanersDlg::OnDatetimechangeDtto(NMHDR* pNMHDR, LRESULT* pResult) +{ + + Criteria(); + *pResult = 0; +} + +void CLoanersDlg::OnDatetimechangeDtfrom(NMHDR* pNMHDR, LRESULT* pResult) +{ + + Criteria(); + *pResult = 0; +} + +void CLoanersDlg::OnCkshowreturned() +{ + m_nTypeCriteriaX=1; + Criteria(); + +} + +void CLoanersDlg::OnCkshowout() +{ + m_nTypeCriteriaX=2; + Criteria(); +} + +void CLoanersDlg::OnCkshowallitems() +{ + m_nTypeCriteriaX=0; + Criteria(); +} + + +//set date and type criteria and rebuild list +void CLoanersDlg::Criteria() +{ + CString strFrom,strTo,strDatePart,strTypePart; + COleDateTime dtData; + m_ckAnyDate.SetCheck(FALSE); + m_ckDueDate.SetCheck(FALSE); + m_ckSentDate.SetCheck(FALSE); + m_ckShowAll.SetCheck(FALSE); + m_ckShowOut.SetCheck(FALSE); + m_ckShowReturned.SetCheck(FALSE); + m_ckReceivedDate.SetCheck(FALSE); + + m_dtFrom.GetTime(dtData); + strFrom=dtData.Format(_T("%m/%d/%Y")); + + m_dtTo.GetTime(dtData); + strTo=dtData.Format(_T("%m/%d/%Y")); + + m_strCriteria.Empty(); + + switch(m_nDateCriteriaX) + { + + case 1://sent date + m_ckSentDate.SetCheck(TRUE); + strDatePart.Format("((rentals.dateout) Between #%s# And #%s#)",strFrom,strTo); + break; + + case 2://due date + m_ckDueDate.SetCheck(TRUE); + strDatePart.Format("((rentals.datedue) Between #%s# And #%s#)",strFrom,strTo); + break; + + case 3://received date + m_ckReceivedDate.SetCheck(TRUE); + strDatePart.Format("((rentals.datereturn) Between #%s# And #%s#) AND ((rentals.returned)=True)",strFrom,strTo); + break; + + default://any date + strDatePart.Empty(); + m_ckAnyDate.SetCheck(TRUE); + break; + } + + + switch(m_nTypeCriteriaX) + { + + case 1://returned + strTypePart=" ((rentals.returned)=True)"; + + m_ckShowReturned.SetCheck(TRUE); + break; + + case 2://out + + m_ckShowOut.SetCheck(TRUE); + strTypePart=" ((rentals.returned)=False)"; + break; + + default://all + m_ckShowAll.SetCheck(TRUE); + strTypePart.Empty(); + break; + + } + + + + //No criteria + if(strDatePart.IsEmpty() && strTypePart.IsEmpty()) + { + m_strCriteria.Empty(); + FillView(); + return; + } + + //both criteria + if(!strDatePart.IsEmpty() && !strTypePart.IsEmpty() ) + { + + m_strCriteria=" WHERE (" + strTypePart + " AND " + strDatePart + ")"; + FillView(); + return; + } + + //only one criteria + if(!strTypePart.IsEmpty()) + { + m_strCriteria = " WHERE (" + strTypePart+ ")"; + FillView(); + return; + } + else + { + m_strCriteria=" WHERE (" + strDatePart+ ")"; + FillView(); + return; + } + + + + + +} + + +void CLoanersDlg::ShowDateFields(bool bShow) +{ + m_dtFrom.ShowWindow(bShow ? TRUE : FALSE); + m_dtTo.ShowWindow(bShow ? TRUE : FALSE); + m_lblTo.ShowWindow(bShow ? TRUE : FALSE); +} + + +void CLoanersDlg::Security() +{ + int x=m_pApp->Allowed(RLOANERS,true); + + if(x==2)//read only + { + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + + } + + + if(x==0) + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } +} + + + +//SET ORDER BY CLAUSE DEPENDING ON CLICK HERE +void CLoanersDlg::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + int x; + CString str; + CFlatHeaderCtrl* header; + header=m_rc.GetHeaderCtrl(); + + + //FIND CLICKED COLUMN + + str=header->m_szHotItemText; + + if(str=="Status"){x=0;goto OUTTAHERE;} + if(str=="Item"){x=1;goto OUTTAHERE;} + if(str=="At"){x=2;goto OUTTAHERE;} + if(str=="Out"){x=3;goto OUTTAHERE;} + if(str=="Due"){x=4;goto OUTTAHERE;} + if(str=="Rcvd."){x=5;goto OUTTAHERE;} + if(str=="Ref"){x=7;goto OUTTAHERE;} + if(str=="Desc."){x=8;goto OUTTAHERE;} + + +OUTTAHERE: + + + bColumnSortAsc[x]=!bColumnSortAsc[x]; + switch(x) + {//DESC + case 0://duedays + m_strOrderBy="ORDER BY [datedue]"; + break; + case 1://item + m_strOrderBy="ORDER BY [rentals]![description] & IIf(IsNull([parts]![partnumber]),\"\",\"part:\" & [parts]![partnumber]) & IIf(IsNull([units]![sn]),\"\",\"unit:\" & [units]![sn])"; + break; + case 2://RENTOR + m_strOrderBy="ORDER BY [loanedto] & IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company])"; + break; + case 3://OUTDATE + m_strOrderBy="ORDER BY [dateout]"; + break; + + case 4://DUEDATE + m_strOrderBy="ORDER BY [datedue]"; + break; + + case 5://backdate/returned + m_strOrderBy="ORDER BY rentals.returned,[datereturn]"; + break; + + //case 6: is id number so not sortable + + case 7://reference number/text + m_strOrderBy="ORDER BY rentals.ref"; + break; + + case 8://Description + m_strOrderBy="ORDER BY IIf(IsNull([sn]),[rentals].[description] & [parts].[description],[company_person] & \" \" & [unitmodels].[description] & \" \" & [unitmodels].[model])"; + break; + + + } + + if(!bColumnSortAsc[x]) + m_strOrderBy+=" DESC"; + + + header->SetSortColumn(header->GetHotIndex(),bColumnSortAsc[x]); + + *pResult = TRUE;//TRUE means we handled it here thanks anyway + FillView(); +} + + +void CLoanersDlg::OnBtnprint() +{ + CString q; + COleDateTime dtDefault; + dtDefault.SetDate(1968,03,12); + q.Format("SELECT rentals.*, IIf(IsNull([sn]),[rentals].[description] & [parts].[description],[company_person] & " + "\" \" & [unitmodels].[description] & \" \" & [unitmodels].[model]) AS [desc], [rentals]![description] & " + "IIf(IsNull([parts]![partnumber]),\"\",\"part:\" & [parts]![partnumber]) & " + "IIf(IsNull([units]![sn]),\"\",\"unit:\" & [units]![sn]) AS item, [loanedto] & " + "IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) " + "AS rentor, Format([dateout],\"Short Date\") AS outdate, IIf([datedue]=#%s#,\"na\",Format([datedue], " + "\"Short Date\")) AS duedate, IIf([datereturn]=#%s#,\"Out\",Format([datereturn],\"Short Date\")) " + "AS retdate, DateDiff(\"d\",Now(),[datedue]) AS duedays " + "FROM ((((rentals LEFT JOIN clients ON rentals.clientlink = clients.id) LEFT JOIN " + "units ON rentals.unitlink = units.id) LEFT JOIN parts ON rentals.partlink = parts.id) " + "LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "%s %s;",dtDefault.Format(_T("%m/%d/%Y")), + dtDefault.Format(_T("%m/%d/%Y")),m_strCriteria,m_strOrderBy); + + rsPrint->QueryReadOnly(q); + if(rsPrint->IsEmpty()) + { + AfxMessageBox("Nothing to print!"); + return; + } + + + //m_pApp->CreateTTX("loaners.ttx",rsPrint->RecordSetPointer()); + m_pApp->PrintCMReportRDC("loaners",rsPrint->RecordSetPointer()); + + +} + +void CLoanersDlg::OnNew() +{ + CLoanersEditDlg d; + if(d.DoModal()==IDOK) + FillView(); +} + +void CLoanersDlg::OnDelete() +{ + int x; + CString q,strID; + x=m_rc.GetFirstSelectedItem(); + if(x<0) return;//no selection + if(AfxMessageBox("Delete the highlighted item? Are you sure?",MB_YESNO)==IDNO) + return; + + strID=m_rc.GetItemText(x,6); + + q.Format("DELETE rentals.* FROM rentals WHERE (((rentals.id)=%s));",strID); + rs->Ex(q); + FillView(); +} + +void CLoanersDlg::OnCloseThisScreen() +{ + CString profile,q; + //save to user prefs. + m_rc.WriteProfile(&profile); + q.Format("UPDATE users SET users.rentalprofile = \"%s\" " + "WHERE (((users.id)=%u));",profile,m_pApp->m_lusrID); + rs->Ex(q); + CDialog::OnOK(); +} + +void CLoanersDlg::OnHelponloaners() +{ + WinHelp(0x200A8); + // +} + +void CLoanersDlg::Layout(void) +{ + int nVertFactor;//used to scale vertically + int nDelta=0;//change in vertical height + nVertFactor=0; + nDelta=5; + + + m_resize.Add(IDC_LBL_SHOW,0,100,0,0); + m_resize.Add(IDC_CKSHOWRETURNED,0,100,0,0); + + m_resize.Add(IDC_CKSHOWOUT,0,100,0,0); + m_resize.Add(IDC_CKSHOWALLITEMS,0,100,0,0); + m_resize.Add(IDC_CKANYDATE,0,100,0,0); + m_resize.Add(IDC_CKSENTDATE,0,100,0,0); + m_resize.Add(IDC_CKDUEDATE,0,100,0,0); + m_resize.Add(IDC_CKRECEIVEDDATE,0,100,0,0); + m_resize.Add(IDC_DTFROM,0,100,0,0); + m_resize.Add(IDC_lblTo,0,100,0,0); + m_resize.Add(IDC_DTTO,0,100,0,0); + m_resize.Add(IDC_REPORT,0,0,100,100); + + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.h new file mode 100644 index 0000000..e0cb1ec --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersDlg.h @@ -0,0 +1,94 @@ +#if !defined(AFX_LOANERSDLG_H__AC027B41_4377_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_LOANERSDLG_H__AC027B41_4377_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LoanersDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLoanersDlg dialog +#include "ReportCtrl.h" +#include "gzrset.h" +#include "ResizeCtrl.h" +#include "afxwin.h" +class CLoanersDlg : public CDialog +{ +// Construction +public: + CResizeCtrl m_resize; + BOOL bColumnSortAsc[9];//<---COLUMN COUNT HERE MUST BE UPDATED WHEN NEW ONES ADDED + CString m_strOrderBy; + void Security(); + ~CLoanersDlg(); + void ShowDateFields(bool bShow); + int m_nDateCriteriaX; + int m_nTypeCriteriaX; + CString m_strCriteria; + void Criteria(); + void FillView(); + CLoanersDlg(CWnd* pParent = NULL); // standard constructor +GZRset* rs; +GZRset* rsPrint; + CSpApp* m_pApp; + void OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult); +// Dialog Data + //{{AFX_DATA(CLoanersDlg) + enum { IDD = IDD_LOANERS }; + CButton m_btnPrint; + CButton m_btnDelete; + CButton m_btnAdd; + CButton m_ckReceivedDate; + CButton m_ckDueDate; + CButton m_ckAnyDate; + CButton m_ckSentDate; + CButton m_ckShowReturned; + CButton m_ckShowOut; + CButton m_ckShowAll; + CReportCtrl m_rc; + CStatic m_lblTo; + CDateTimeCtrl m_dtTo; + CDateTimeCtrl m_dtFrom; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLoanersDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: +CImageList m_ilReport; + // Generated message map functions + //{{AFX_MSG(CLoanersDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnCkanydate(); + afx_msg void OnCksentdate(); + afx_msg void OnCkduedate(); + afx_msg void OnCkreceiveddate(); + afx_msg void OnCkshowreturned(); + afx_msg void OnCkshowout(); + afx_msg void OnCkshowallitems(); + afx_msg void OnDatetimechangeDtto(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDatetimechangeDtfrom(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnBtnprint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnNew(); + afx_msg void OnDelete(); + afx_msg void OnCloseThisScreen(); + afx_msg void OnHelponloaners(); + void Layout(void); + CStatic m_lblShow; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LOANERSDLG_H__AC027B41_4377_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.cpp new file mode 100644 index 0000000..967ec8b --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.cpp @@ -0,0 +1,476 @@ +// LoanersEditDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "LoanersEditDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLoanersEditDlg dialog + + +CLoanersEditDlg::CLoanersEditDlg(CWnd* pParent /*=NULL*/) +: CDialog(CLoanersEditDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLoanersEditDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + //Initialize recordset pointer + rs=m_pApp->rsPool->GetRS("CLoanersEditDlg"); + rs2=m_pApp->rsPool->GetRS("CLoanersEditDlg rs2"); + + cfm = new CgzCurrencyFormatter; + m_strRentalID.Empty(); + m_strSelClient="0"; + m_strSelUnit="0"; + m_strSelPart="0"; +} + +CLoanersEditDlg::~CLoanersEditDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs2->m_nID); + + delete cfm; + +} + +void CLoanersEditDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLoanersEditDlg) + DDX_Control(pDX, IDC_EDREF, m_edRef); + DDX_Control(pDX, IDC_BTNCANCEL, m_btnCancel); + DDX_Control(pDX, IDC_DTDATEDUE, m_dtDateDue); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_EDLOANEDTO, m_edLoanedTo); + DDX_Control(pDX, IDC_EDDESCRIPTION, m_edDescription); + DDX_Control(pDX, IDC_EDCHARGES, m_edCharges); + DDX_Control(pDX, IDC_DTDATERETURN, m_dtDateReturn); + DDX_Control(pDX, IDC_DTDATEOUT, m_dtDateOut); + DDX_Control(pDX, IDC_CKRETURNED, m_ckReturned); + DDX_Control(pDX, IDC_CBUNIT, m_cbUnits); + DDX_Control(pDX, IDC_CBPART, m_cbParts); + DDX_Control(pDX, IDC_CBCLIENT, m_cbClient); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLoanersEditDlg, CDialog) +//{{AFX_MSG_MAP(CLoanersEditDlg) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_EN_KILLFOCUS(IDC_EDCHARGES, OnKillfocusEdcharges) +ON_CBN_CLOSEUP(IDC_CBPART, OnCloseupCbpart) +ON_CBN_CLOSEUP(IDC_CBUNIT, OnCloseupCbunit) +ON_EN_KILLFOCUS(IDC_EDDESCRIPTION, OnKillfocusEddescription) +ON_BN_CLICKED(IDC_BTNCANCEL, OnBtncancel) +ON_BN_CLICKED(IDC_CKRETURNED, OnCkreturned) +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLoanersEditDlg message handlers + +BOOL CLoanersEditDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + FillListBoxes(); + FillFields(); + m_edRef.SetLimitText(80); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +//pass in rental id to indicate editing: +void CLoanersEditDlg::SetRentalID(CString *strRentalID) +{ + if(strRentalID!=NULL) + m_strRentalID=*strRentalID; +} + + + +void CLoanersEditDlg::FillFields() +{ + COleCurrency crCharges; + COleDateTime dtOut,dtDue,dtReturned; + bool bReturned; + long lPart,lUnit,lClient; + CString q,strData,strDescription,strLoanedTo,strNotes,strRef; + + if(m_strRentalID.IsEmpty()) return; + + q.Format("SELECT rentals.* FROM rentals " + "WHERE (((rentals.id)=%s));",m_strRentalID); + rs->Query(q); + + + //Fetch the fields: + rs->FetchField("partlink",&lPart); + rs->FetchField("unitlink",&lUnit); + rs->FetchField("clientlink",&lClient); + rs->FetchField("loanedto",&strLoanedTo); + rs->FetchField("description",&strDescription); + rs->FetchField("dateout",&dtOut); + rs->FetchField("datedue",&dtDue); + rs->FetchField("datereturn",&dtReturned); + rs->FetchField("charges",&crCharges); + rs->FetchField("returned",&bReturned); + rs->FetchField("notes",&strNotes); + rs->FetchField("ref",&strRef); + + + //CHARGES + m_edCharges.SetWindowText(cfm->Format(crCharges)); + + //CLIENT + m_cbClient.Select(lClient); + + //LOANED TO + m_edLoanedTo.SetWindowText(strLoanedTo); + + //UNIT + m_cbUnits.Select(lUnit); + + //PART + m_cbParts.Select(lPart); + + //ITEM DESCRIPTION + m_edDescription.SetWindowText(strDescription); + + //OUT DATE + m_dtDateOut.SetTime(dtOut); + + //DUE DATE + m_dtDateDue.SetTime(dtDue); + + //RETURNED DATE + m_dtDateReturn.SetTime(dtReturned); + + //RETURNED FLAG + m_ckReturned.SetCheck(bReturned ? TRUE : FALSE); + m_dtDateReturn.EnableWindow(bReturned ? TRUE : FALSE); + + //REFERENCE + m_edRef.SetWindowText(strRef); + + //NOTES + m_edNotes.SetWindowText(strNotes); + + +} + +void CLoanersEditDlg::FillListBoxes() +{ + CString strData; + CString strIndex; + CString q; + + long lData; + m_cbParts.Clear(); + m_cbParts.AddRow(" ","0"); + + rs->QueryReadOnly("SELECT parts.id, [partnumber] & \" - \" " + "& [description] AS name FROM parts " + "WHERE (((parts.active)=True)) ORDER BY parts.partnumber;"); + if(!rs->IsEmpty()) + { + rs->MoveFirst(); + + do + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbParts.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + m_cbParts.Select(m_strSelPart); + + + + + + //========================================== + //CLIENTS LIST + + m_cbClient.Clear(); + + m_cbClient.AddRow(" ","0"); + + rs->QueryReadOnly("SELECT clients.id,clients.isheadoffice, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS name " + "FROM clients WHERE (((clients.isheadoffice)=False)) ORDER BY IIf(IsNull([company]),[last] & \", \" & [first],[company]);"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbClient.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } + m_cbClient.Select(m_strSelClient); + + //============================================ + //FILL UNIT LIST: + m_cbUnits.Clear(); + m_cbUnits.AddRow(" < No unit >","0"); + + + + rs->QueryReadOnly("SELECT units.id, [sn] & \" - \" & [company_person] & \" \" & [unitmodels].[description] & \" \" & [unitmodels].[model] AS name " + "FROM (units LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "WHERE (((units.loaner)=True)) " + "ORDER BY units.sn;"); + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + strData.TrimRight("- "); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + + //see if it's out right now + q.Format("SELECT rentals.unitlink FROM rentals " + "WHERE (((rentals.returned)=False) AND ((rentals.unitlink)=%u));",lData); + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty())//out + strData="z_Out: " + strData; + m_cbUnits.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } + + m_cbUnits.Select(m_strSelUnit); +} + +//**************************************************** +//Saving/updating and exit +void CLoanersEditDlg::OnBtndone() +{ + + if(m_bReadOnly) + CDialog::OnOK(); + COleCurrency crCharges; + COleDateTime dtOut,dtDue,dtReturned; + bool bReturned; + long lPart,lUnit,lClient; + CString q,strData,strDescription,strLoanedTo,strNotes,strRef; + + + //CHARGES + m_edCharges.GetWindowText(strData); + crCharges.ParseCurrency(strData); + + //CLIENT + strData=m_cbClient.GetCurrentRowID(); + lClient=atol(strData); + + //LOANED TO + m_edLoanedTo.GetWindowText(strLoanedTo); + + //UNIT + strData=m_cbUnits.GetCurrentRowID(); + lUnit=atol(strData); + + //PART + strData=m_cbParts.GetCurrentRowID(); + lPart=atol(strData); + + //ITEM DESCRIPTION + m_edDescription.GetWindowText(strDescription); + + //OUT DATE + m_dtDateOut.GetTime(dtOut); + + //DUE DATE + m_dtDateDue.GetTime(dtDue); + + //RETURNED DATE + m_dtDateReturn.GetTime(dtReturned); + + //RETURNED FLAG + bReturned=m_ckReturned.GetCheck() ? true : false; + + //REFERENCE + m_edRef.GetWindowText(strRef); + + //NOTES + m_edNotes.GetWindowText(strNotes); + + + //Validation and judging: "Whose cuisine will reign supreme?" + if(lClient==0 && strLoanedTo.IsEmpty()) + { + AfxMessageBox("You need to indicate who has this equipment"); + return; + } + + if(lUnit==0 && lPart ==0 && strDescription.IsEmpty()) + { + AfxMessageBox("You haven't indicated what item this record refers to"); + return; + } + + + + + if(m_strRentalID.IsEmpty()) + {//Add new record + q="SELECT rentals.* FROM rentals " + "WHERE (((rentals.id)=0));"; + } + else + { + //update existing record + q.Format("SELECT rentals.* FROM rentals " + "WHERE (((rentals.id)=%s));",m_strRentalID); + + } + + rs->Query(q); + //Add a record if necessary + if(m_strRentalID.IsEmpty()) + rs->AddNewRecord(); + + //Update the fields: + rs->UpdateField("partlink",&lPart); + rs->UpdateField("unitlink",&lUnit); + rs->UpdateField("clientlink",&lClient); + rs->UpdateField("loanedto",&strLoanedTo); + rs->UpdateField("description",&strDescription); + rs->UpdateField("dateout",&dtOut); + rs->UpdateField("datedue",&dtDue); + rs->UpdateField("datereturn",&dtReturned); + rs->UpdateField("charges",&crCharges); + rs->UpdateField("returned",&bReturned); + rs->UpdateField("ref",&strRef); + rs->UpdateField("notes",&strNotes); + rs->SaveRecord(); + + + + + + //this is just to flush the update through + //rs->Query("SELECT rentals.* from rentals WHERE rentals.id=0;"); + //modified Jan 10 2000 as proper flush is now + //guranteed with a close + rs->Close(); + CDialog::OnOK(); +} + + +//Validate charges as entered +void CLoanersEditDlg::OnKillfocusEdcharges() +{ + CString strData; + COleCurrency crData; + m_edCharges.GetWindowText(strData); + crData.ParseCurrency(strData); + m_edCharges.SetWindowText(cfm->Format(crData)); + +} + +void CLoanersEditDlg::OnCloseupCbpart() +{ + + m_strSelPart=m_cbParts.GetCurrentRowID(); + //erase other two fields + if(m_strSelPart!="0") + { + m_strSelUnit="0"; + m_cbUnits.Select(m_strSelUnit); + m_edDescription.SetWindowText(""); + } +} + +void CLoanersEditDlg::OnCloseupCbunit() +{ + m_strSelUnit=m_cbUnits.GetCurrentRowID(); + //erase other two fields + if(m_strSelUnit!="0") + { + m_strSelPart="0"; + m_cbParts.Select(m_strSelPart); + m_edDescription.SetWindowText(""); + } +} + +void CLoanersEditDlg::OnKillfocusEddescription() +{ + CString strData; + m_edDescription.GetWindowText(strData); + if(strData.GetLength()>1) + { + m_strSelUnit="0"; + m_strSelPart="0"; + m_cbParts.Select(m_strSelPart); + m_cbUnits.Select(m_strSelUnit); + + } +} + + + +void CLoanersEditDlg::OnBtncancel() +{ + CDialog::OnCancel(); + +} + +void CLoanersEditDlg::OnOK(){} + + +void CLoanersEditDlg::OnCkreturned() +{ + m_dtDateReturn.EnableWindow(m_ckReturned.GetCheck()); + +} + +void CLoanersEditDlg::Security() +{ + int x=m_pApp->Allowed(RLOANERS,true); + m_bReadOnly=false; + if(x==2)//read only + { + m_bReadOnly=true; + m_btnCancel.ShowWindow(FALSE); + m_cbClient.EnableWindow(FALSE); + m_cbParts.EnableWindow(FALSE); + m_cbUnits.EnableWindow(FALSE); + m_ckReturned.EnableWindow(FALSE); + m_dtDateDue.EnableWindow(FALSE); + m_dtDateOut.EnableWindow(FALSE); + m_dtDateReturn.EnableWindow(FALSE); + m_edCharges.SetReadOnly(TRUE); + m_edDescription.SetReadOnly(TRUE); + m_edLoanedTo.SetReadOnly(TRUE); + m_edNotes.SetReadOnly(TRUE); + + } + + + if(x==0) + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } +} + + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.h new file mode 100644 index 0000000..1012dd1 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoanersEditDlg.h @@ -0,0 +1,83 @@ +#if !defined(AFX_LOANERSEDITDLG_H__E6C958A1_4365_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_LOANERSEDITDLG_H__E6C958A1_4365_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LoanersEditDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLoanersEditDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "gzcurrencyformatter.h" +class CLoanersEditDlg : public CDialog +{ +// Construction +public: + bool m_bReadOnly; + void Security(); + CString m_strSelClient; + CString m_strSelUnit; + CString m_strSelPart; + void FillListBoxes(); + void FillFields(); + void SetRentalID(CString * strRentalID); + CString m_strRentalID; + ~CLoanersEditDlg(); + CLoanersEditDlg(CWnd* pParent = NULL); // standard constructor + GZRset* rs; + GZRset* rs2; + + + CSpApp* m_pApp; + CgzCurrencyFormatter* cfm; +// Dialog Data + //{{AFX_DATA(CLoanersEditDlg) + enum { IDD = IDD_LOANERSEDIT }; + CEdit m_edRef; + CButton m_btnCancel; + CDateTimeCtrl m_dtDateDue; + CEdit m_edNotes; + CEdit m_edLoanedTo; + CEdit m_edDescription; + CEdit m_edCharges; + CDateTimeCtrl m_dtDateReturn; + CDateTimeCtrl m_dtDateOut; + CButton m_ckReturned; + CgzCombo m_cbUnits; + CgzCombo m_cbParts; + CgzCombo m_cbClient; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLoanersEditDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLoanersEditDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnBtndone(); + afx_msg void OnKillfocusEdcharges(); + afx_msg void OnCloseupCbpart(); + afx_msg void OnCloseupCbunit(); + afx_msg void OnKillfocusEddescription(); + afx_msg void OnBtncancel(); + virtual void OnOK(); + afx_msg void OnCkreturned(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LOANERSEDITDLG_H__E6C958A1_4365_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.cpp new file mode 100644 index 0000000..c6fd876 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.cpp @@ -0,0 +1,169 @@ +//////////////////////////////////////////////////////////////////////// +// LogTrace.cpp -- Implementation of the CLogTrace class + + +#include "stdafx.h" +#include +#include "LogTrace.h" + +/************************************************** + + How to use CLogTrace + + 1. Make a static CLogTrace object as a member of the application class + + 2. Add the following lines to the InitInstance of the program + + + m_LogTrace.m_strAppName = "MyApp"; // use appropriate name here + + m_LogTrace.SetFileName("Log.txt"); // sets the log file name and puts it in the exe path + + m_LogTrace.OnStartup(TRUE, TRUE); // activates the log trace + + 3. Also in InitInstance, add the following line if you want to empty the log file + each time the application starts + + m_LogTrace.ResetFile(); + + + 4. Any time you want to write to the log file, use the CLogTrace::WriteLine functions + these will write the text along with date and time + + +*******************************************************/ + + + +////////////////////////////////////////////////////// +// Construction/Destruction + +CLogTrace::CLogTrace() +{ + m_bActive = FALSE; + m_bTimeStamp = TRUE; + + CString s; +} + + +CLogTrace::~CLogTrace() +{ + + +} + +//////////////////////////////////////////////////////// +// CLogTrace operations + + +void CLogTrace::ResetFile() +{ + CStdioFile f; + CFileException fe; + CString s; + + if (m_strFileName.IsEmpty()) return; + + if (f.Open(m_strFileName, CFile::modeWrite | CFile::modeCreate, &fe) == FALSE) + { + return; + } + + f.Close(); +} + + + +// bActive tells us if we want the trace to be active or not +// bTimeStamp tells us if we want time stamps on each line +// eliminating the time stamp allows us to use this class for a regular log file +void CLogTrace::OnStartup(BOOL bActive, BOOL bTimeStamp) +{ + m_bActive = bActive; + m_bTimeStamp = bTimeStamp; + if (bTimeStamp == FALSE) return; + CString s; + + // these ***'s help to indicate when one ru of the program ends and another starts + // because we don't always overwrite the file each time + + WriteLine("\n\n******************************************\n\n"); + s.Format("%s Log Trace %s\n\n", m_strAppName, COleDateTime::GetCurrentTime().Format()); + WriteLine(s); +} + + + +// function to write a line of text to the log file +void CLogTrace::WriteLine(LPCTSTR szLine) +{ + CStdioFile f; + CFileException fe; + CString s; + + if (m_bActive == FALSE) return; + if (m_strFileName.IsEmpty()) return; + + if (f.Open(m_strFileName, CFile::modeWrite | CFile::modeCreate | + CFile::modeNoTruncate, &fe) == FALSE) + { + return; + } + + try + { + f.SeekToEnd(); + //TRACE("LOGGIN %s\n", szLine); + if (m_bTimeStamp) + { + s.Format("%s\t%s\n", COleDateTime::GetCurrentTime().Format(), + szLine); + } + else + { + s.Format("%s\n", szLine); + } + f.WriteString(s); + } + catch (CException* e) + { + e->Delete(); + } + f.Close(); +} + +// function to write a line of text, with an extra string +void CLogTrace::WriteLine(LPCTSTR szFormat, LPCTSTR szAddInfo) +{ + if (m_bActive == FALSE) return; + CString s; + s.Format(szFormat, szAddInfo); + WriteLine(s); +} + + +// funtion to write a line of text with an extra integer +void CLogTrace::WriteLine(LPCTSTR szFormat, int nAddInfo) +{ + if (m_bActive == FALSE) return; + CString s; + s.Format(szFormat, nAddInfo); + WriteLine(s); +} + + +// function to set the log file name. don't pass a fill path! +// just pass something like "log.txt" +// the file will be placed in the same dir as the exe file +void CLogTrace::SetFileName(LPCTSTR szFileName) +{ + TCHAR drive[_MAX_PATH], dir[_MAX_PATH], name[_MAX_PATH], ext[_MAX_PATH]; + + const char *path = _pgmptr ; + + _splitpath(path, drive, dir, name, ext); + + m_strFileName.Format("%s%s%s", drive, dir, szFileName); + +} \ No newline at end of file diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.h new file mode 100644 index 0000000..061041f --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LogTrace.h @@ -0,0 +1,53 @@ +//////////////////////////////////////////////////////////////////////// +// LogTrace.cpp -- Interface for the CLogTrace class +// A class to do debug logging + + +#ifndef __LOGTRACE_H__ +#define __LOGTRACE_H__ + +class CLogTrace +{ +// Construction/Destruction +public: + CLogTrace(); + ~CLogTrace(); + + +// Attributes +public: + CString m_strAppName; + +protected: + BOOL m_bActive; + CString m_strFileName; + BOOL m_bTimeStamp; + +// Operations +public: + void WriteLine(LPCTSTR szLine); + void WriteLine(LPCTSTR szFormat, LPCTSTR szAddInfo); + void WriteLine(LPCTSTR szFormat, int nAddInfo); + void ResetFile(); + void OnStartup(BOOL bActive, BOOL bTimeStamp); + void SetFileName(LPCTSTR szFileName); + + +protected: + + + +// Inlines +public: + inline void SetActive(BOOL bSet) + { + m_bActive = bSet; + } + inline CString GetFileName() + { + return m_strFileName; + } +}; + + +#endif // __LOGTRACE_H__ \ No newline at end of file diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.cpp new file mode 100644 index 0000000..e581cbc --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.cpp @@ -0,0 +1,525 @@ +// LoginDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "LoginDlg.h" +//#define WHATTHEFUBAR 0 +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLoginDlg dialog + + +CLoginDlg::CLoginDlg(CWnd* pParent /*=NULL*/) +: CDialog(CLoginDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLoginDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + cryp=new GZK; + + + rs=m_pApp->rsPool->GetRS("Error at:CLoginDlg::CLoginDlg"); + + + //if(rs->Valid()) + // rs->SetConnect(m_pApp->strConnectString); + +} + +CLoginDlg::~CLoginDlg() +{ + + /*dibBanner.DeleteObject(); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + delete cryp;*/ +} + +void CLoginDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLoginDlg) + DDX_Control(pDX, IDC_LBLRC, m_lblRC); + DDX_Control(pDX, IDC_LBLURL, m_lblURL); + DDX_Control(pDX, IDC_EDPASSWORD, m_edPassword); + DDX_Control(pDX, IDC_EDLOGIN, m_edLogin); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLoginDlg, CDialog) +//{{AFX_MSG_MAP(CLoginDlg) +ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLoginDlg message handlers + +BOOL CLoginDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + SetWindowText("Login"); + //Contract + + + m_lblURL.SetTextColor(RGB(0,0,255)); + m_lblURL.SetFontUnderline(TRUE); + //m_lblURL.SetFontBold(TRUE); + m_lblURL.SetFontSize(10); + m_lblURL.SetLink(TRUE); + m_lblURL.SetLinkURL("http://www.ayanova.com"); + m_lblURL.SetLinkCursor(m_pApp->hcHand); + //dibBanner.SetDither(TRUE); +// dibBanner.Load("000");//m_strBannerFile); +#ifdef AYQB + dibBanner.SetBitmap(IDB_QBSPLASH); +#else + dibBanner.SetBitmap(IDB_SPLASH); +#endif + + + + CString strComp; + + //if invalid recordset just abort + //this is the only way apparently + if(!rs->Valid()) + CDialog::OnCancel(); + + //Added Sept 30th 2002 + //This is the first recordset instantiated, from here + //Set the use transactions value so all future calls + //will use the method selected + + //Turn errors off in case db has not been updated yet + bool bUseTransactions=false; + + rs->m_bSupressErrors=true; + if(rs->QueryReadOnly("SELECT defaults.transact FROM defaults;")) + { + + if(rs->FetchField("transact",&bUseTransactions)) + { + m_pApp->m_bUseTransactions=bUseTransactions; + m_pApp->rsPool->m_bUseTransactions=bUseTransactions; + } + } + + //turn errors back on + rs->m_bSupressErrors=false; + + + rs->QueryReadOnly("SELECT defaults.regto FROM defaults;"); + if(!rs->IsEmpty()) + { + rs->FetchField("regto",&strComp); + if(strComp=="Evaluation" || strComp=="AyaNova Evaluation") + { + m_edLogin.SetWindowText("manager"); + m_edPassword.SetWindowText("letmein"); + } + + } + +#ifdef _DEBUG + m_edLogin.SetWindowText("manager"); + m_edPassword.SetWindowText("letmein"); +#endif + +m_lblRC.SetTextColor(RGB(255,255,255)); + m_lblRC.SetBkColor(RGB(255,112,16)); + m_lblRC.SetFontBold(TRUE); + m_lblRC.SetFontSize(8); + //m_lblRC.SetFontName("Arial"); + m_edLogin.SetFocus(); + + char* bogus=new char[34]; + delete bogus; + + + + + return FALSE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CLoginDlg::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + dibBanner.Draw(GetDC(), CPoint(11,10)); // pDC is of type CDC* + + // Do not call CDialog::OnPaint() for painting messages +} + + + +void CLoginDlg::OnOK() +{ + m_edLogin.GetWindowText(login); + m_edPassword.GetWindowText(password); + if(login.IsEmpty()) + { + AfxMessageBox("You must enter a user name to login"); + } + else + { + ProcessLogin(); + } +} + + + +void CLoginDlg::OnCancel() +{ + Cleanup(); + CDialog::OnCancel(); +} + +void CLoginDlg::ProcessLogin() +{ + + CString q; + CString user; + CString pass; + CString testempty; + CString strError; + long lData=0; + m_pApp->m_lusrID=0; + + + pass=password; + user=login; + + + //PROCESS A LOG IN + + // m_ctlLogin.GetWindowText(user); + // m_ctlPassword.GetWindowText(pass); + if(user.IsEmpty()) + { + AfxMessageBox("You must enter a login name"); + + } + else + { +#ifdef _WTF_ + AfxMessageBox("Process login: head"); +#endif + //check for super user account + //SuperUser(user); + //hash entries + cryp->GZHash(&user); + testempty="@" + user +"gz"; + + + if(pass.IsEmpty()) + pass=testempty; + + cryp->GZHash(&pass); + //q.Format("SELECT users.* FROM users WHERE (((users.login)=\"%s\") AND ((users.pass)=\"%s\"));",user,pass); + q.Format("SELECT users.* FROM users WHERE (((users.login)='%s') AND ((users.pass)='%s'));",user,pass); +#ifdef _DEBUG + // m_pApp->ShowStuff(q); +#endif + if(!rs->QueryReadOnly(q)) + { + strError=rs->GetLastError(); + if(strError.Find("Unrecognized database format",0)!=-1) + { + if(AfxMessageBox("It appears that your database file scdata.sc may be corrupt.\r\n\r\n" + "AyaNova can attempt to repair it, however due to a bug in the Microsoft \r\n" + "Data access components, AyaNova may not be able to do it on it's own.\r\n" + "If AyaNova is unable to repair it you will receive an error:\r\n" + "\"Unrecognized database format\" and it will need to be repaired with Access 2000\r\n" + "Microsoft Access 2000 can be used to repair your scdata.sc file if\r\n" + "AyaNova is unable to repair it. Email us your scdata.sc file zipped up\r\n" + "and we can do that for you, or if you have Access 2000, open it first, then open scdata.sc.\r\n" + "Note that Access won't list scdata.sc as a file available to be opened as it doesn't end \r\n" + "in the .mdb file extension, but you can type in the name yourself.\r\n" + "\r\nWe are awaiting a bug fix from Microsoft that will allow AyaNova\r\n" + "to perform as complete a repair as Microsoft Access 2000\r\n" + "You can always email us if you have any questions about this at support@ayanova.com\r\n\r\n" + "Would you like to attempt a repair now?",MB_YESNO)==IDYES) + { + rs->Close();//delete rs; + rs=NULL; +#ifdef _WTF_ + AfxMessageBox("Process login post unrecognized error"); +#endif + Compact(true); + Cleanup(); + CDialog::OnCancel(); + + return; + + } + + + } + else //not unrecognized database format, some other error + { + #ifdef _WTF_ + AfxMessageBox("Process login post dbase access error\r\nNot unrecognized database format related."); +#endif + + AfxMessageBox("The following error occured when trying to \r\n" + "and access the database for the first time."); + AfxMessageBox(strError); + } + + } + + + + + + if(rs->IsEmpty()) + { + AfxMessageBox("Access denied"); + + } + else + { + + rs->FetchField("id",&lData); + m_pApp->m_lusrID=lData; + rs->Close(); + Cleanup(); + CDialog::OnOK(); + } + + + + }//else not access denied + + + + + +} + + + + + + +//**************************************************** +// compact the database through a jro object +//********************************************** +bool CLoginDlg::Compact(bool bKeepOld) +{ + bool status=true; + CString src,dest,tempfile; + CFileStatus fstat; + CWaitCursor wait; + + + //delete old one if exists + tempfile.Format("%sscdata.tmp",m_pApp->m_strDBPATH); + if(CFile::GetStatus(tempfile,fstat)==TRUE)//file exists + { + TRY + { + CFile::Remove( tempfile ); + } + CATCH( CFileException, e ) + { + status=false; + CString cstrErrMsg; + cstrErrMsg.Format("Error in Compact: %s cannot be removed",tempfile); + AfxMessageBox(cstrErrMsg); + } + END_CATCH + } + + if(status==true) + { + + + + src.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sscdata.sc;Jet OLEDB:Engine Type=5;", + m_pApp->m_strDBPATH); + + dest.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sscdata.tmp;Jet OLEDB:Engine Type=5;", + m_pApp->m_strDBPATH); + + + _bstr_t bstsrc(src); + _bstr_t bstdest(dest); + + try + { + IJetEnginePtr jet(__uuidof(JetEngine)); + + jet->CompactDatabase(bstsrc, bstdest); + } + catch(_com_error &e) + { + status=false; + CString cstrErrMsg; + //get info from com error + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE( "*************************************************\n"); + TRACE( "Exception thrown for classes generated by #import\n"); + TRACE( "\tCode = %081x\n", e.Error); + TRACE( "\tCode Meaning = %s\n",e.ErrorMessage()); + TRACE( "\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE( "Description = %s\n", (LPCTSTR) bstrDescription); + TRACE( "*************************************************\n"); + cstrErrMsg.Format("Error in Compact: %s,\r\n%s",e.ErrorMessage(),(LPCTSTR) bstrDescription); + AfxMessageBox(cstrErrMsg); + + } + catch(...) + { + status=false; + TRACE( "*** Unhandled exception ***" ); + AfxMessageBox("Unhandled Error in Compact"); + PostQuitMessage(-1);//exit now before anything worse happens + + } + + + } + + //Added. indexing can leave a 100+mb old file + //this way can delete it + if(bKeepOld) + { + //copy mdb over old + src.Format("%sscdata.sc",m_pApp->m_strDBPATH); + dest.Format("%sscdata.old",m_pApp->m_strDBPATH); + status=CopyFile(src.GetBuffer(100),dest.GetBuffer(100)); + } + + + + if(status==true) + { + + + src.Format("%sscdata.tmp",m_pApp->m_strDBPATH); + dest.Format("%sscdata.sc",m_pApp->m_strDBPATH); + status=CopyFile(src.GetBuffer(100),dest.GetBuffer(100)); + + + }//if status==true + + //delete gz1 + tempfile.Format("%sscdata.tmp",m_pApp->m_strDBPATH); + if(CFile::GetStatus(tempfile,fstat)==TRUE)//file exists + { + TRY + { + CFile::Remove( tempfile ); + } + CATCH( CFileException, e ) + { + status=false; + CString cstrErrMsg; + cstrErrMsg.Format("Error at end of Compact: %s cannot be removed\r\nOtherwise compact OK",tempfile); + AfxMessageBox(cstrErrMsg); + } + END_CATCH + } + + + return status; +} + +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + + + + + + + + + + + +//******************************************* +//copy a file, overwrite dest if exists +bool CLoginDlg::CopyFile(char *src, char *dest) +{ + + CFile sourceFile; + CFile destFile; + CFileException ex; + CString tempfile; + + + + // open the source file for reading + + if (!sourceFile.Open(src, + CFile::modeRead | CFile::shareDenyWrite, &ex)) + { + // complain if an error happened + // no need to delete the ex object + + TCHAR szError[1024]; + ex.GetErrorMessage(szError, 1024); + CString errormsg; + errormsg.Format("Error copying file %s to %s\r\n The error was: %s",src,dest,szError); + AfxMessageBox(errormsg); + return false; + } + else + { + if (!destFile.Open(dest, CFile::modeWrite | + CFile::shareExclusive | CFile::modeCreate, &ex)) + { + TCHAR szError[1024]; + ex.GetErrorMessage(szError, 1024); + CString errormsg; + errormsg.Format("Error copying file %s to %s\r\n The error was: %s",src,dest,szError); + AfxMessageBox(errormsg); + sourceFile.Close(); + return false; + } + + BYTE buffer[4096]; + DWORD dwRead; + + // Read in 4096-byte blocks, + // remember how many bytes were actually read, + // and try to write that many out. This loop ends + // when there are no more bytes to read. + + do + { + dwRead = sourceFile.Read(buffer, 4096); + destFile.Write(buffer, dwRead); + } + while (dwRead > 0); + + // Close both files + + destFile.Close(); + sourceFile.Close(); + } + + return true; + +} + + +// Clean up allocated objects before closing +void CLoginDlg::Cleanup(void) +{ + dibBanner.DeleteObject(); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + delete cryp; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.h new file mode 100644 index 0000000..256e03f --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/LoginDlg.h @@ -0,0 +1,71 @@ +#if !defined(AFX_LOGINDLG_H__6CB48A21_4631_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_LOGINDLG_H__6CB48A21_4631_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LoginDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLoginDlg dialog +#include "dibsectionlite.h"//bitmap display class +#include "gzk.h" +#include "gzrset.h" +#include "label.h" +class CLoginDlg : public CDialog +{ +// Construction +public: + + + GZK * cryp; + GZRset* rs; + CSpApp* m_pApp; + void ProcessLogin(); + bool Compact(bool bKeepOld); + bool CopyFile(char *src, char *dest); + CString strRegisteredTo; + CString m_strBannerFile; + CString password; + CString login; + ~CLoginDlg(); + CLoginDlg(CWnd* pParent = NULL); // standard constructor +CDIBSectionLite dibBanner; +// Dialog Data + //{{AFX_DATA(CLoginDlg) + enum { IDD = IDD_LOGIN }; + CLabel m_lblRC; + CLabel m_lblURL; + CEdit m_edPassword; + CEdit m_edLogin; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLoginDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLoginDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + virtual void OnOK(); + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + // Clean up allocated objects before closing + void Cleanup(void); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LOGINDLG_H__6CB48A21_4631_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tlh b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tlh new file mode 100644 index 0000000..91e257b --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tlh @@ -0,0 +1,344 @@ +// Created by Microsoft (R) C/C++ Compiler Version 12.00.8447.0 (17b94d25). +// +// MSJRO.tlh +// +// C++ source equivalent of Win32 type library C:\PROGRAM FILES\COMMON FILES\System\ado\MSJRO.DLL +// compiler-generated file created 08/28/00 at 14:47:54 - DO NOT EDIT! + +// +// Cross-referenced type libraries: +// +// #import "C:\PROGRAM FILES\COMMON FILES\SYSTEM\ADO\msado15.dll" +// + +#pragma once +#pragma pack(push, 8) + +#include + +// +// Forward references and typedefs +// + +struct __declspec(uuid("d2d139e0-b6ca-11d1-9f31-00c04fc29d52")) +/* dual interface */ IReplica; +struct __declspec(uuid("d2d139e2-b6ca-11d1-9f31-00c04fc29d52")) +/* dual interface */ Filters; +struct __declspec(uuid("d2d139e1-b6ca-11d1-9f31-00c04fc29d52")) +/* dual interface */ Filter; +struct __declspec(uuid("9f63d980-ff25-11d1-bb6f-00c04fae22da")) +/* dual interface */ IJetEngine; +struct /* coclass */ Replica; +struct /* coclass */ JetEngine; + +// +// Smart pointer typedef declarations +// + +_COM_SMARTPTR_TYPEDEF(IReplica, __uuidof(IReplica)); +_COM_SMARTPTR_TYPEDEF(Filters, __uuidof(Filters)); +_COM_SMARTPTR_TYPEDEF(Filter, __uuidof(Filter)); +_COM_SMARTPTR_TYPEDEF(IJetEngine, __uuidof(IJetEngine)); + +// +// Type library items +// + +enum ReplicaTypeEnum +{ + jrRepTypeNotReplicable = 0, + jrRepTypeDesignMaster = 1, + jrRepTypeFull = 2, + jrRepTypePartial = 3 +}; + +enum VisibilityEnum +{ + jrRepVisibilityGlobal = 1, + jrRepVisibilityLocal = 2, + jrRepVisibilityAnon = 4 +}; + +enum UpdatabilityEnum +{ + jrRepUpdFull = 0, + jrRepUpdReadOnly = 2 +}; + +enum SyncTypeEnum +{ + jrSyncTypeExport = 1, + jrSyncTypeImport = 2, + jrSyncTypeImpExp = 3 +}; + +enum SyncModeEnum +{ + jrSyncModeIndirect = 1, + jrSyncModeDirect = 2, + jrSyncModeInternet = 3 +}; + +enum FilterTypeEnum +{ + jrFilterTypeTable = 1, + jrFilterTypeRelationship = 2 +}; + +struct __declspec(uuid("d2d139e0-b6ca-11d1-9f31-00c04fc29d52")) +IReplica : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetActiveConnection,put=PutRefActiveConnection)) + IDispatchPtr ActiveConnection; + __declspec(property(get=GetConflictFunction,put=PutConflictFunction)) + _bstr_t ConflictFunction; + __declspec(property(get=GetConflictTables)) + _RecordsetPtr ConflictTables; + __declspec(property(get=GetDesignMasterId,put=PutDesignMasterId)) + _variant_t DesignMasterId; + __declspec(property(get=GetPriority)) + long Priority; + __declspec(property(get=GetReplicaId)) + _variant_t ReplicaId; + __declspec(property(get=GetReplicaType)) + enum ReplicaTypeEnum ReplicaType; + __declspec(property(get=GetRetentionPeriod,put=PutRetentionPeriod)) + long RetentionPeriod; + __declspec(property(get=GetVisibility)) + enum VisibilityEnum Visibility; + __declspec(property(get=GetFilters)) + FiltersPtr Filters; + + // + // Wrapper methods for error-handling + // + + void PutRefActiveConnection ( + IDispatch * ppconn ); + void PutActiveConnection ( + const _variant_t & ppconn ); + IDispatchPtr GetActiveConnection ( ); + _bstr_t GetConflictFunction ( ); + void PutConflictFunction ( + _bstr_t pbstr ); + _RecordsetPtr GetConflictTables ( ); + _variant_t GetDesignMasterId ( ); + void PutDesignMasterId ( + const _variant_t & pvar ); + long GetPriority ( ); + _variant_t GetReplicaId ( ); + enum ReplicaTypeEnum GetReplicaType ( ); + long GetRetentionPeriod ( ); + void PutRetentionPeriod ( + long pl ); + enum VisibilityEnum GetVisibility ( ); + HRESULT CreateReplica ( + _bstr_t replicaName, + _bstr_t description, + enum ReplicaTypeEnum ReplicaType, + enum VisibilityEnum Visibility, + long Priority, + enum UpdatabilityEnum updatability ); + VARIANT_BOOL GetObjectReplicability ( + _bstr_t objectName, + _bstr_t objectType ); + HRESULT SetObjectReplicability ( + _bstr_t objectName, + _bstr_t objectType, + VARIANT_BOOL replicability ); + HRESULT MakeReplicable ( + _bstr_t connectionString, + VARIANT_BOOL columnTracking ); + HRESULT PopulatePartial ( + _bstr_t FullReplica ); + HRESULT Synchronize ( + _bstr_t target, + enum SyncTypeEnum syncType, + enum SyncModeEnum syncMode ); + FiltersPtr GetFilters ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall putref_ActiveConnection ( + IDispatch * ppconn ) = 0; + virtual HRESULT __stdcall put_ActiveConnection ( + VARIANT ppconn ) = 0; + virtual HRESULT __stdcall get_ActiveConnection ( + IDispatch * * ppconn ) = 0; + virtual HRESULT __stdcall get_ConflictFunction ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall put_ConflictFunction ( + BSTR pbstr ) = 0; + virtual HRESULT __stdcall get_ConflictTables ( + struct _Recordset * * pprset ) = 0; + virtual HRESULT __stdcall get_DesignMasterId ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall put_DesignMasterId ( + VARIANT pvar ) = 0; + virtual HRESULT __stdcall get_Priority ( + long * pl ) = 0; + virtual HRESULT __stdcall get_ReplicaId ( + VARIANT * pvar ) = 0; + virtual HRESULT __stdcall get_ReplicaType ( + enum ReplicaTypeEnum * pl ) = 0; + virtual HRESULT __stdcall get_RetentionPeriod ( + long * pl ) = 0; + virtual HRESULT __stdcall put_RetentionPeriod ( + long pl ) = 0; + virtual HRESULT __stdcall get_Visibility ( + enum VisibilityEnum * pl ) = 0; + virtual HRESULT __stdcall raw_CreateReplica ( + BSTR replicaName, + BSTR description, + enum ReplicaTypeEnum ReplicaType, + enum VisibilityEnum Visibility, + long Priority, + enum UpdatabilityEnum updatability ) = 0; + virtual HRESULT __stdcall raw_GetObjectReplicability ( + BSTR objectName, + BSTR objectType, + VARIANT_BOOL * replicability ) = 0; + virtual HRESULT __stdcall raw_SetObjectReplicability ( + BSTR objectName, + BSTR objectType, + VARIANT_BOOL replicability ) = 0; + virtual HRESULT __stdcall raw_MakeReplicable ( + BSTR connectionString, + VARIANT_BOOL columnTracking ) = 0; + virtual HRESULT __stdcall raw_PopulatePartial ( + BSTR FullReplica ) = 0; + virtual HRESULT __stdcall raw_Synchronize ( + BSTR target, + enum SyncTypeEnum syncType, + enum SyncModeEnum syncMode ) = 0; + virtual HRESULT __stdcall get_Filters ( + struct Filters * * ppFilters ) = 0; +}; + +struct __declspec(uuid("d2d139e2-b6ca-11d1-9f31-00c04fc29d52")) +Filters : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetItem)) + FilterPtr Item[]; + __declspec(property(get=GetCount)) + long Count; + + // + // Wrapper methods for error-handling + // + + HRESULT Refresh ( ); + IUnknownPtr _NewEnum ( ); + long GetCount ( ); + FilterPtr GetItem ( + const _variant_t & Index ); + HRESULT Append ( + _bstr_t TableName, + enum FilterTypeEnum FilterType, + _bstr_t FilterCriteria ); + HRESULT Delete ( + const _variant_t & Index ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_Refresh ( ) = 0; + virtual HRESULT __stdcall raw__NewEnum ( + IUnknown * * ppvObject ) = 0; + virtual HRESULT __stdcall get_Count ( + long * c ) = 0; + virtual HRESULT __stdcall get_Item ( + VARIANT Index, + struct Filter * * ppvObject ) = 0; + virtual HRESULT __stdcall raw_Append ( + BSTR TableName, + enum FilterTypeEnum FilterType, + BSTR FilterCriteria ) = 0; + virtual HRESULT __stdcall raw_Delete ( + VARIANT Index ) = 0; +}; + +struct __declspec(uuid("d2d139e1-b6ca-11d1-9f31-00c04fc29d52")) +Filter : IDispatch +{ + // + // Property data + // + + __declspec(property(get=GetTableName)) + _bstr_t TableName; + __declspec(property(get=GetFilterType)) + enum FilterTypeEnum FilterType; + __declspec(property(get=GetFilterCriteria)) + _bstr_t FilterCriteria; + + // + // Wrapper methods for error-handling + // + + _bstr_t GetTableName ( ); + enum FilterTypeEnum GetFilterType ( ); + _bstr_t GetFilterCriteria ( ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall get_TableName ( + BSTR * pbstr ) = 0; + virtual HRESULT __stdcall get_FilterType ( + enum FilterTypeEnum * ptype ) = 0; + virtual HRESULT __stdcall get_FilterCriteria ( + BSTR * pbstr ) = 0; +}; + +struct __declspec(uuid("9f63d980-ff25-11d1-bb6f-00c04fae22da")) +IJetEngine : IDispatch +{ + // + // Wrapper methods for error-handling + // + + HRESULT CompactDatabase ( + _bstr_t SourceConnection, + _bstr_t Destconnection ); + HRESULT RefreshCache ( + struct _Connection * Connection ); + + // + // Raw methods provided by interface + // + + virtual HRESULT __stdcall raw_CompactDatabase ( + BSTR SourceConnection, + BSTR Destconnection ) = 0; + virtual HRESULT __stdcall raw_RefreshCache ( + struct _Connection * Connection ) = 0; +}; + +struct __declspec(uuid("d2d139e3-b6ca-11d1-9f31-00c04fc29d52")) +Replica; + // [ default ] interface IReplica + +struct __declspec(uuid("de88c160-ff2c-11d1-bb6f-00c04fae22da")) +JetEngine; + // [ default ] interface IJetEngine + +// +// Wrapper method implementations +// + +#include "MSJRO.tli" + +#pragma pack(pop) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tli b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tli new file mode 100644 index 0000000..a75daa4 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MSJRO.tli @@ -0,0 +1,230 @@ +// Created by Microsoft (R) C/C++ Compiler Version 12.00.8447.0 (17b94d25). +// +// MSJRO.tli +// +// Wrapper implementations for Win32 type library C:\PROGRAM FILES\COMMON FILES\System\ado\MSJRO.DLL +// compiler-generated file created 08/28/00 at 14:47:54 - DO NOT EDIT! + +#pragma once + +// +// interface IReplica wrapper method implementations +// + +inline void IReplica::PutRefActiveConnection ( IDispatch * ppconn ) { + HRESULT _hr = putref_ActiveConnection(ppconn); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline void IReplica::PutActiveConnection ( const _variant_t & ppconn ) { + HRESULT _hr = put_ActiveConnection(ppconn); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline IDispatchPtr IReplica::GetActiveConnection ( ) { + IDispatch * _result; + HRESULT _hr = get_ActiveConnection(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IDispatchPtr(_result, false); +} + +inline _bstr_t IReplica::GetConflictFunction ( ) { + BSTR _result; + HRESULT _hr = get_ConflictFunction(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline void IReplica::PutConflictFunction ( _bstr_t pbstr ) { + HRESULT _hr = put_ConflictFunction(pbstr); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline _RecordsetPtr IReplica::GetConflictTables ( ) { + struct _Recordset * _result; + HRESULT _hr = get_ConflictTables(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _RecordsetPtr(_result, false); +} + +inline _variant_t IReplica::GetDesignMasterId ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_DesignMasterId(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline void IReplica::PutDesignMasterId ( const _variant_t & pvar ) { + HRESULT _hr = put_DesignMasterId(pvar); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline long IReplica::GetPriority ( ) { + long _result; + HRESULT _hr = get_Priority(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _variant_t IReplica::GetReplicaId ( ) { + VARIANT _result; + VariantInit(&_result); + HRESULT _hr = get_ReplicaId(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _variant_t(_result, false); +} + +inline enum ReplicaTypeEnum IReplica::GetReplicaType ( ) { + enum ReplicaTypeEnum _result; + HRESULT _hr = get_ReplicaType(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline long IReplica::GetRetentionPeriod ( ) { + long _result; + HRESULT _hr = get_RetentionPeriod(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline void IReplica::PutRetentionPeriod ( long pl ) { + HRESULT _hr = put_RetentionPeriod(pl); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); +} + +inline enum VisibilityEnum IReplica::GetVisibility ( ) { + enum VisibilityEnum _result; + HRESULT _hr = get_Visibility(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline HRESULT IReplica::CreateReplica ( _bstr_t replicaName, _bstr_t description, enum ReplicaTypeEnum ReplicaType, enum VisibilityEnum Visibility, long Priority, enum UpdatabilityEnum updatability ) { + HRESULT _hr = raw_CreateReplica(replicaName, description, ReplicaType, Visibility, Priority, updatability); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline VARIANT_BOOL IReplica::GetObjectReplicability ( _bstr_t objectName, _bstr_t objectType ) { + VARIANT_BOOL _result; + HRESULT _hr = raw_GetObjectReplicability(objectName, objectType, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline HRESULT IReplica::SetObjectReplicability ( _bstr_t objectName, _bstr_t objectType, VARIANT_BOOL replicability ) { + HRESULT _hr = raw_SetObjectReplicability(objectName, objectType, replicability); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT IReplica::MakeReplicable ( _bstr_t connectionString, VARIANT_BOOL columnTracking ) { + HRESULT _hr = raw_MakeReplicable(connectionString, columnTracking); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT IReplica::PopulatePartial ( _bstr_t FullReplica ) { + HRESULT _hr = raw_PopulatePartial(FullReplica); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT IReplica::Synchronize ( _bstr_t target, enum SyncTypeEnum syncType, enum SyncModeEnum syncMode ) { + HRESULT _hr = raw_Synchronize(target, syncType, syncMode); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline FiltersPtr IReplica::GetFilters ( ) { + struct Filters * _result; + HRESULT _hr = get_Filters(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return FiltersPtr(_result, false); +} + +// +// interface Filters wrapper method implementations +// + +inline HRESULT Filters::Refresh ( ) { + HRESULT _hr = raw_Refresh(); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline IUnknownPtr Filters::_NewEnum ( ) { + IUnknown * _result; + HRESULT _hr = raw__NewEnum(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return IUnknownPtr(_result, false); +} + +inline long Filters::GetCount ( ) { + long _result; + HRESULT _hr = get_Count(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline FilterPtr Filters::GetItem ( const _variant_t & Index ) { + struct Filter * _result; + HRESULT _hr = get_Item(Index, &_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return FilterPtr(_result, false); +} + +inline HRESULT Filters::Append ( _bstr_t TableName, enum FilterTypeEnum FilterType, _bstr_t FilterCriteria ) { + HRESULT _hr = raw_Append(TableName, FilterType, FilterCriteria); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT Filters::Delete ( const _variant_t & Index ) { + HRESULT _hr = raw_Delete(Index); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +// +// interface Filter wrapper method implementations +// + +inline _bstr_t Filter::GetTableName ( ) { + BSTR _result; + HRESULT _hr = get_TableName(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +inline enum FilterTypeEnum Filter::GetFilterType ( ) { + enum FilterTypeEnum _result; + HRESULT _hr = get_FilterType(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _result; +} + +inline _bstr_t Filter::GetFilterCriteria ( ) { + BSTR _result; + HRESULT _hr = get_FilterCriteria(&_result); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _bstr_t(_result, false); +} + +// +// interface IJetEngine wrapper method implementations +// + +inline HRESULT IJetEngine::CompactDatabase ( _bstr_t SourceConnection, _bstr_t Destconnection ) { + HRESULT _hr = raw_CompactDatabase(SourceConnection, Destconnection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} + +inline HRESULT IJetEngine::RefreshCache ( struct _Connection * Connection ) { + HRESULT _hr = raw_RefreshCache(Connection); + if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); + return _hr; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.cpp new file mode 100644 index 0000000..2974552 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.cpp @@ -0,0 +1,318 @@ +// MailMsgDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "MailMsgDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMailMsgDlg dialog + + +CMailMsgDlg::CMailMsgDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMailMsgDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMailMsgDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + k=new GZK; + k->GZSetUniqueKey(40); + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Mail message entry screen error:"); + rs->SetConnect(m_pApp->strConnectString); + */ +//Initialize recordset pointer +rs=m_pApp->rsPool->GetRS("CMailMsgDlg"); + + m_strMessage.Empty(); + m_strSubject.Empty(); + m_bNoRE=false; +} + + +void CMailMsgDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMailMsgDlg) + DDX_Control(pDX, IDC_USERS, m_lbUsers); + DDX_Control(pDX, IDC_SUBJECT, m_edSubject); + DDX_Control(pDX, IDC_SEND, m_btnSend); + DDX_Control(pDX, IDC_POPUP, m_ckPopup); + DDX_Control(pDX, IDC_MESSAGE, m_edMessage); + DDX_Control(pDX, IDC_DATETIMEPICKER1, m_dtDate); + DDX_Control(pDX, IDC_CANCEL, m_btnCancel); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMailMsgDlg, CDialog) + //{{AFX_MSG_MAP(CMailMsgDlg) + ON_BN_CLICKED(IDC_SEND, OnSend) + ON_BN_CLICKED(IDC_CANCEL, OnCancel) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMailMsgDlg message handlers + +void CMailMsgDlg::OnOK() +{ + + //CDialog::OnOK(); +} + +void CMailMsgDlg::OnCancel() +{ + CDialog::OnOK(); +} + +void CMailMsgDlg::OnSend() +{ + CString strMsg,strSubject,q; + COleDateTime dtData,dtData2,dtData3; + long lData; + bool bData; + int nRecipients=m_lbUsers.SelectionCount(); + //Ensure there is at least one selected user + if(nRecipients==0) + { + AfxMessageBox("You must select at least one person\r\n" + "to send this message to."); + return; + + } + + //encrypt the subject and message + // + m_edMessage.GetWindowText(strMsg); + m_edSubject.GetWindowText(strSubject); + + if(strSubject.IsEmpty()) + { + AfxMessageBox("A subject is required"); + return; + } + + k->GZEncrypt(&strMsg,false); + k->GZEncrypt(&strSubject,false); + + //save the message + + + //open the recordset without returning a record (no id=0) + rs->Query("SELECT mail.* FROM mail;"); + rs->AddNewRecord(); + + + //******************************** + // START SAVING FIELDS + //******************************** + //FROM + rs->UpdateField("from",&m_pApp->m_lusrID); + //rs->SaveRecord(); + + //DATE: + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("date",&dtData); + //rs->SaveRecord(); + + + //POPUP + bData = m_ckPopup.GetCheck() ? true:false; + rs->UpdateField("popup",&bData); + //rs->SaveRecord(); + + + //SUBJECT + rs->UpdateField("subject",&strSubject); +// rs->SaveRecord(); + + //MESSAGE + rs->UpdateField("message",&strMsg); + //rs->SaveRecord(); + + //DELIVERY DATE + //get the date, remove on the date portion which + //sets the time to 0:0:0 (midnight) + m_dtDate.GetTime(dtData3); + dtData2.SetDate(dtData3.GetYear(),dtData3.GetMonth(),dtData3.GetDay()); + + rs->UpdateField("deliverydate",&dtData2); + rs->SaveRecord(); + + +//****************** DONE SAVING FIELDS ************* +//*************************************************** + + //retrieve the id number + q.Format("SELECT mail.* FROM mail " + "WHERE (((mail.from)=%u) AND ((mail.date)=#%s#));" + ,m_pApp->m_lusrID,dtData.Format(_T("%m/%d/%Y %H:%M:%S"))); + + rs->Query(q); + + + //should work but.... + ASSERT(!rs->IsEmpty()); + + rs->FetchField("id",&lData); + + + //save the recipient records + for(int x=0;xEx(q); + + } + + rs->Close(); + CDialog::OnOK(); + +} + +BOOL CMailMsgDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + rs->Query("SELECT users.id, users.mail, [last] & \", \" & [first] AS name " + "FROM users WHERE (((users.active)=True) AND (users.mail)=True) " + "ORDER BY [last] & \", \" & [first];"); + + if(rs->IsEmpty())//bail + { + AfxMessageBox("No users could be found for you to send mail to"); + CDialog::OnOK(); + } + + //fill the list box + + + CString strData; + CString strIndex; + long lData; + m_lbUsers.Clear(); + //fill combo box with available zones + rs->MoveFirst(); + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_lbUsers.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_lbUsers.AddRow(strData,strIndex); + } + + + if(!m_strSubject.IsEmpty()) + { + if(m_bNoRE) + { + m_edSubject.SetWindowText(m_strSubject); + m_edMessage.SetWindowText(m_strMessage); + } + else + { + //if replying/forwarding, set previous message + if(m_strSubject.Left(3)!="Re:") + m_strSubject="Re: " + m_strSubject; + m_strMessage=">" + m_strMessage; + m_strMessage.Replace("\r\n","\r\n> "); + m_edSubject.SetWindowText(m_strSubject); + m_edMessage.SetWindowText(m_strMessage); + } + } + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +//***********************88 +CMailMsgDlg::~CMailMsgDlg() +{ +m_pApp->rsPool->ReleaseRS(&rs->m_nID); + delete k; +} + + + + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CMailMsgDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + + edControl->SetModify(FALSE); + return true; +} + + + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CMailMsgDlg::SaveField(CButton *ckControl,CString fldname) +{ + + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + + return true; +} +//************************************************************ +//SAVE DateTimePicker CONTROL FIELD +//************************************************************ +bool CMailMsgDlg::SaveField(CDateTimeCtrl *dtControl,CString fldname) +{ + + COleDateTime dtData; + dtControl->GetTime(dtData); + rs->UpdateField(fldname,&dtData); + rs->SaveRecord(); + + return true; +} + +void CMailMsgDlg::SetForwardInfo(CString *pSubject, CString *pMessage) +{ + m_strMessage=*pMessage; + m_strSubject=*pSubject; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.h new file mode 100644 index 0000000..ef904af --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailMsgDlg.h @@ -0,0 +1,71 @@ +#if !defined(AFX_MAILMSGDLG_H__D18DDDA4_2658_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_MAILMSGDLG_H__D18DDDA4_2658_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MailMsgDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMailMsgDlg dialog +#include "gzk.h" +#include "gzlistbox.h" +#include "gzrset.h" +class CMailMsgDlg : public CDialog +{ +// Construction +public: + bool m_bNoRE; + void SetForwardInfo(CString* pSubject,CString* pMessage); + CString m_strSubject; + CString m_strMessage; + + ~CMailMsgDlg(); + CMailMsgDlg(CWnd* pParent = NULL); // standard constructor + GZK* k; + GZRset* rs; + CSpApp* m_pApp; + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool SaveField(CButton* ckControl,CString fldname); + bool SaveField(CDateTimeCtrl* dtControl,CString fldname); + + //------------------------------- +// Dialog Data + //{{AFX_DATA(CMailMsgDlg) + enum { IDD = IDD_MAILMSG }; + CgzListBox m_lbUsers; + CEdit m_edSubject; + CButton m_btnSend; + CButton m_ckPopup; + CEdit m_edMessage; + CDateTimeCtrl m_dtDate; + CButton m_btnCancel; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMailMsgDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMailMsgDlg) + virtual void OnOK(); + afx_msg void OnCancel(); + afx_msg void OnSend(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAILMSGDLG_H__D18DDDA4_2658_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.cpp new file mode 100644 index 0000000..1296627 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.cpp @@ -0,0 +1,511 @@ +// MailReaderDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "MailReaderDlg.h" +#include "MailMsgDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMailReaderDlg dialog + + +CMailReaderDlg::CMailReaderDlg(CWnd* pParent /*=NULL*/) +: CDialog(CMailReaderDlg::IDD, pParent) +, m_bReadOnly(false) +{ + //{{AFX_DATA_INIT(CMailReaderDlg) + + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + k=new GZK; + k->GZSetUniqueKey(40); + m_pApp= (CSpApp*)AfxGetApp(); + + rs=m_pApp->rsPool->GetRS("CMailReaderDlg"); +} + +CMailReaderDlg::~CMailReaderDlg() +{ + delete k; + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + + +void CMailReaderDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMailReaderDlg) + DDX_Control(pDX, IDC_MAIL_REPORT, m_rcMail); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMailReaderDlg, CDialog) +//{{AFX_MSG_MAP(CMailReaderDlg) +ON_NOTIFY(RVN_ITEMDRAWPREVIEW, IDC_MAIL_REPORT, OnRvnItemDrawPreview) +ON_NOTIFY(RVN_ITEMDBCLICK, IDC_MAIL_REPORT, OnRvnItemDbClick) +//}}AFX_MSG_MAP +ON_COMMAND(ID_MAIL_NEWMESSAGE, OnMailNewmessage) +ON_COMMAND(ID_MAIL_REPLY, OnMailReply) +ON_COMMAND(ID_MAIL_DELETE, OnMailDelete) +ON_COMMAND(ID_MAIL_CLOSETHISSCREEN, OnMailClosethisscreen) +ON_COMMAND(ID_MAIL_HELP, OnMailHelp) +ON_COMMAND(ID_MAIL_CHECKFORNEWMAIL, OnMailCheckfornewmail) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMailReaderDlg message handlers + +BOOL CMailReaderDlg::OnInitDialog() +{ + + + CDialog::OnInitDialog(); + m_resize.Create( this ); + Security(); + + m_resize.Add(IDC_MAIL_REPORT,0,0,100,100); + //Use the current width and height as the minimum size + m_resize.SetMinimumTrackingSize(); + + CString profile,q; + q.Format("SELECT users.mailprofile " + "FROM users WHERE (((users.id)=%u));",m_pApp->m_lusrID); + rs->Query(q); + rs->FetchField("mailprofile",&profile); + + + + + + + //m_rcMail.ModifyStyle(0,RVS_SHOWVGRID); + m_ilReport.Create(IDB_REPORT, 16, 1, RGB(255,0,255)); + m_rcMail.SetImageList(&m_ilReport); + + ShowWindow(SW_MAXIMIZE); + + m_rcMail.InsertColor(0, 0x00C0D8C0); + m_rcMail.InsertColor(1, ::GetSysColor(COLOR_GRAYTEXT)); + m_rcMail.InsertColor(2, 0x00D0C0C0); + m_rcMail.InsertColor(3, 0x00804000); + + /* + + RVCOLUMN rvc; + rvc.lpszText = "Field"; + rvc.iWidth = 100; + m_rcAbout.DefineColumn(0, &rvc); + + rvc.lpszText = "Data"; + rvc.iWidth = 320; + m_rcAbout.DefineColumn(1, &rvc); + + m_rcAbout.ActivateColumn(0, 0); + m_rcAbout.ActivateColumn(1, 1); + + m_rcAbout.SetItemCount(100); + */ + + RVCOLUMN rvc; + + rvc.nFormat = RVCF_IMAGE|RVCF_EX_AUTOWIDTH|RVCF_EX_FIXEDWIDTH|RVCF_SUBITEM_IMAGE; + rvc.iImage = 0; + rvc.lpszText = _T("Icon"); + m_rcMail.DefineColumn(0, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "From:"; + rvc.iWidth = 175; + m_rcMail.DefineColumn(1, &rvc); + + rvc.lpszText = "Subject:"; + rvc.iWidth = 325; + m_rcMail.DefineColumn(2, &rvc); + + rvc.lpszText = "Date:"; + rvc.iWidth = 175; + m_rcMail.DefineColumn(3, &rvc); + + //setup according to users preferences + if(!profile.IsEmpty()) + m_rcMail.GetProfile(&profile); + else + { + + //not needed when setting by pref + //but if there are no preferences then you would need it + + m_rcMail.ActivateColumn(0, 0); + m_rcMail.ActivateColumn(1, 1); + m_rcMail.ActivateColumn(2, 2); + m_rcMail.ActivateColumn(3, 3); + + + } + + + + m_rcMail.ModifyStyle(0, RVS_SINGLESELECT); + //m_rcMail.ModifyStyle(0, RVS_SHOWCOLORALTERNATE); + + + //turn off the grids + m_rcMail.ModifyStyle(RVS_SHOWVGRID, 0); + m_rcMail.ModifyStyle(RVS_SHOWHGRID, 0); + + + + //retrieve the mail and display it + FillView(); + + + + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CMailReaderDlg::OnRvnItemDrawPreview(NMHDR* pNMHDR, LRESULT* pResult) +{ + + CString strText; + LPNMRVDRAWPREVIEW lpnmrvdp = (LPNMRVDRAWPREVIEW)pNMHDR; + + strText=m_Messages[0].GetAt(m_Messages[0].FindIndex(lpnmrvdp->iItem)); + + CReportCtrl& rc = m_rcMail; + + CDC dc; + dc.Attach(lpnmrvdp->hDC); + if(lpnmrvdp->nState&RVIS_SELECTED) + dc.SetTextColor(::GetFocus()==rc.m_hWnd ? GetSysColor(COLOR_HIGHLIGHTTEXT):GetSysColor(COLOR_HIGHLIGHT)); + else + dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHT)); + + lpnmrvdp->rect.left += 40; + lpnmrvdp->rect.top += 2; + lpnmrvdp->rect.bottom -= 2; + dc.DrawText(strText, &lpnmrvdp->rect, DT_LEFT|DT_END_ELLIPSIS|DT_WORDBREAK|DT_NOPREFIX|DT_EXPANDTABS); + + dc.Detach(); + *pResult = FALSE; + + +} + +void CMailReaderDlg::OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + int x=lpnmrv->iItem; + CString temp,msg,sub,strdate,sender,q; + temp=m_Messages[0].GetAt(m_Messages[0].FindIndex(x)); + sub=m_rcMail.GetItemText(x,2); + strdate=m_rcMail.GetItemText(x,3); + sender=m_rcMail.GetItemText(x,1); + + //Now format with header info + msg.Format("From: %s\r\n" + "Sent: %s\r\n" + "Subject: %s\r\n\r\nMessage:\r\n%s",sender,strdate,sub,temp); + + m_pApp->ShowStuff(msg); + //AfxMessageBox(msg,MB_ICONINFORMATION|MB_OK); + + //FLAG MAIL MESSAGE AS BEING READ + q.Format("UPDATE mailroute SET mailroute.remind = False " + "WHERE (((mailroute.maillink)=%s) AND ((mailroute.recipient)=%u));" + ,m_Messages[1].GetAt(m_Messages[1].FindIndex(lpnmrv->iItem)),m_pApp->m_lusrID); + + rs->Ex(q); + + + + RVITEM rvi; + rvi.iItem = lpnmrv->iItem; + rvi.iSubItem = 0; + rvi.nMask = RVIM_IMAGE|RVIM_PREVIEW|RVIM_STATE; + rvi.iImage = 4; + rvi.nPreview = 0; + rvi.nState = 0; + m_rcMail.SetItem(&rvi); + + } + + *pResult = FALSE; +} + + +void CMailReaderDlg::FillView() +{ + + CString q; + bool bUnread; + int x=0; + + m_Messages[0].RemoveAll(); + m_Messages[1].RemoveAll(); + m_rcMail.DeleteAllItems(); + + q.Format("SELECT mail.*, [last] & \", \" & [first] AS fromname, mailroute.remind " + "FROM (mail INNER JOIN mailroute ON mail.id = mailroute.maillink) " + "LEFT JOIN users ON mail.from = users.id " + "WHERE (((mailroute.recipient)=%u) AND ((mail.deliverydate)m_lusrID); + + + rs->Query(q); + + if(rs->IsEmpty()) + return; + + + + CString strFrom,strSubject,strMessage,strDate,strID; + COleDateTime dtDate; + long lData; + + + rs->MoveFirst(); + + + do + { + + rs->FetchField("fromname",&strFrom); + //fix if a deleted user sent the message + if(strFrom.Compare(", ")==0) + strFrom=""; + + rs->FetchField("subject",&strSubject); + k->GZDecrypt(&strSubject,false); + rs->FetchField("message",&strMessage); + k->GZDecrypt(&strMessage,false); + m_Messages[0].AddTail(strMessage); + rs->FetchField("deliverydate",&dtDate); + //keep track of the ID numbers + rs->FetchField("id",&lData); + strID.Format("%u",lData); + m_Messages[1].AddTail(strID); + rs->FetchField("remind",&bUnread); + + //Set the look of the row and insert it + RVITEM rvi; + rvi.iItem = x; + rvi.iSubItem = 0; + rvi.nMask = RVIM_IMAGE|RVIM_PREVIEW|RVIM_STATE|RVIM_LPARAM; + if(bUnread==false) + { + rvi.nState = 0; + rvi.iImage = 4;//Opened envelope + rvi.nPreview = 0;//no preview necessary + } + else + { + rvi.nState = RVIS_BOLD; + rvi.iImage = 3;//closed envelope + if(!strMessage.IsEmpty()) + rvi.nPreview = 17;//hmmm? + else + rvi.nPreview=0;//nothing to show + } + + rvi.lParam = x; + m_rcMail.InsertItem(&rvi); + + + //RVS_OWNERDATA<---this is causing an assert + + //FROM + rvi.iSubItem = 1; + rvi.nMask = RVIM_TEXT; + rvi.lpszText = strFrom.GetBuffer(strFrom.GetLength()); + m_rcMail.SetItem(&rvi); + + //SUBJECT + rvi.iSubItem = 2; + rvi.lpszText = strSubject.GetBuffer(strSubject.GetLength()); + m_rcMail.SetItem(&rvi); + + //DATE + rvi.iSubItem = 3; + strDate=dtDate.Format(); + rvi.lpszText = strDate.GetBuffer(strDate.GetLength()); + m_rcMail.SetItem(&rvi); + + x++; + + }while(rs->MoveForward()); + + +} + + + + + + + + + + + + + +void CMailReaderDlg::OnOk() +{} + + + + +void CMailReaderDlg::Security() +{ +m_bReadOnly=false; + int x=m_pApp->Allowed(REMAIL,true); + +if(x==2)//read only +{ + m_bReadOnly=true; + //m_btnNew.ShowWindow(FALSE); + //m_btnDelete.ShowWindow(FALSE); + //m_btnForward.ShowWindow(FALSE); + +} + + +if(x==0) +{ + m_bReadOnly=true; + m_pApp->SecurityWarning(); + CDialog::OnCancel(); +} +} + +void CMailReaderDlg::OnMailNewmessage() +{ + // New message + if(m_bReadOnly==true) + { + AfxMessageBox("Your AyaNova administrator has given you\r\n" + "read-only access to mail."); + return; + + } + CMailMsgDlg d; + + d.DoModal(); + FillView(); +} + +void CMailReaderDlg::OnMailReply() +{ + if(m_bReadOnly==true) + { + AfxMessageBox("Your AyaNova administrator has given you\r\n" + "read-only access to mail."); + return; + + } + CString temp,msg,sub,strdate,sender; + int x=m_rcMail.GetFirstSelectedItem(); + //validate there is a selection + if(x<0) + return; + + temp=m_Messages[0].GetAt(m_Messages[0].FindIndex(x)); + sub=m_rcMail.GetItemText(x,2); + strdate=m_rcMail.GetItemText(x,3); + sender=m_rcMail.GetItemText(x,1); + msg.Empty(); + //Now format with header info + msg.Format("-----Original Message-----\r\n" + "From: %s\r\n" + "Sent: %s\r\n" + "Subject: %s\r\n\r\n%s",sender,strdate,sub,temp); + + + + //---Original Message----- + //From: MCC First Aid [mailto:mccfirstaid@suncor.com] + //Sent: Friday, May 12, 2000 8:00 AM + //To: 'J Cardinal' + //Subject: RE: Update for database program + // + + + + CMailMsgDlg d; + d.SetForwardInfo(&sub,&msg); + d.DoModal(); + + FillView(); +} + +void CMailReaderDlg::OnMailDelete() +{ + CString q; + int x=m_rcMail.GetFirstSelectedItem(); + //validate there is a selection + if(x<0) + return; + if(AfxMessageBox("Permanently delete this message?",MB_YESNO)==IDYES) + { + q.Format("DELETE mailroute.*, mailroute.maillink, mailroute.recipient " + "FROM mailroute WHERE (((mailroute.maillink)=%s) AND ((mailroute.recipient)=%u));" + ,m_Messages[1].GetAt(m_Messages[1].FindIndex(x)),m_pApp->m_lusrID); + + rs->Ex(q); + rs->Close(); + FillView(); + + } + +} + +void CMailReaderDlg::OnMailClosethisscreen() +{ + CString profile,q; + + //save to user prefs. + m_rcMail.WriteProfile(&profile); + q.Format("UPDATE users SET users.mailprofile = \"%s\" " + "WHERE (((users.id)=%u));",profile,m_pApp->m_lusrID); + rs->Ex(q); + + CDialog::OnOK(); +} + +void CMailReaderDlg::OnMailHelp() +{ + WinHelp(0x2008E); +} + +void CMailReaderDlg::OnMailCheckfornewmail() +{ + CWaitCursor cw; + FillView(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.h new file mode 100644 index 0000000..e63c6e0 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MailReaderDlg.h @@ -0,0 +1,68 @@ +#if !defined(AFX_MAILREADERDLG_H__638302E1_2734_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_MAILREADERDLG_H__638302E1_2734_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MailReaderDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMailReaderDlg dialog +#include "ReportCtrl.h" +#include "gzk.h" +#include "gzrset.h" +#include "ResizeCtrl.h" + +class CMailReaderDlg : public CDialog +{ +// Construction +public: + CResizeCtrl m_resize; + void Security(); + ~CMailReaderDlg(); + CStringList m_Messages[2]; + void FillView(); + CMailReaderDlg(CWnd* pParent = NULL); // standard constructor + void OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnRvnItemDrawPreview(NMHDR* pNMHDR, LRESULT* pResult); + GZK* k; + GZRset* rs; + CSpApp* m_pApp; +// Dialog Data + //{{AFX_DATA(CMailReaderDlg) + enum { IDD = IDD_MAILREADER }; + CReportCtrl m_rcMail; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMailReaderDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + CImageList m_ilReport; + // Generated message map functions + //{{AFX_MSG(CMailReaderDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnOk(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnMailNewmessage(); + afx_msg void OnMailReply(); + afx_msg void OnMailDelete(); + afx_msg void OnMailClosethisscreen(); + afx_msg void OnMailHelp(); + bool m_bReadOnly; + afx_msg void OnMailCheckfornewmail(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAILREADERDLG_H__638302E1_2734_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.cpp new file mode 100644 index 0000000..d1dbe7c --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.cpp @@ -0,0 +1,96 @@ +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "sp.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//#define _CRTDBG_MAP_ALLOC +//#include +//#include + + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CLOSE() + //}}AFX_MSG_MAP + // Global help commands + ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder) + ON_COMMAND(ID_HELP, CFrameWnd::OnHelp) + ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp) + ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here + m_bAutoMenuEnable = FALSE; +} + +CMainFrame::~CMainFrame() +{ +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CFrameWnd::PreCreateWindow(cs) ) + return FALSE; + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE + | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;// | WS_MAXIMIZE + + cs.style &= ~FWS_ADDTOTITLE; // no title + + /* +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) + { + cs.style &= ~FWS_ADDTOTITLE; // no title + return CFrameWnd::PreCreateWindow(cs); + } + */ + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + //CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + + +void CMainFrame::OnClose() +{ + m_pApp= (CSpApp*)AfxGetApp(); + m_pApp->OnExit(); + //CFrameWnd::OnClose(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.h new file mode 100644 index 0000000..7db7d3d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MainFrm.h @@ -0,0 +1,53 @@ +// MainFrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAINFRM_H__A74C37E9_FC36_11D3_964F_00C0F02C4B69__INCLUDED_) +#define AFX_MAINFRM_H__A74C37E9_FC36_11D3_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CMainFrame : public CFrameWnd +{ + +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + CSpApp* m_pApp; +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg void OnClose(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__A74C37E9_FC36_11D3_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MakeHelp.bat b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MakeHelp.bat new file mode 100644 index 0000000..45c7f71 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MakeHelp.bat @@ -0,0 +1,39 @@ +@echo off +REM -- First make map file from Microsoft Visual C++ generated resource.h +echo // MAKEHELP.BAT generated Help Map file. Used by SP.HPJ. >"hlp\sp.hm" +echo. >>"hlp\sp.hm" +echo // Commands (ID_* and IDM_*) >>"hlp\sp.hm" +makehm ID_,HID_,0x10000 IDM_,HIDM_,0x10000 resource.h >>"hlp\sp.hm" +echo. >>"hlp\sp.hm" +echo // Prompts (IDP_*) >>"hlp\sp.hm" +makehm IDP_,HIDP_,0x30000 resource.h >>"hlp\sp.hm" +echo. >>"hlp\sp.hm" +echo // Resources (IDR_*) >>"hlp\sp.hm" +makehm IDR_,HIDR_,0x20000 resource.h >>"hlp\sp.hm" +echo. >>"hlp\sp.hm" +echo // Dialogs (IDD_*) >>"hlp\sp.hm" +makehm IDD_,HIDD_,0x20000 resource.h >>"hlp\sp.hm" +echo. >>"hlp\sp.hm" +echo // Frame Controls (IDW_*) >>"hlp\sp.hm" +makehm IDW_,HIDW_,0x50000 resource.h >>"hlp\sp.hm" +REM -- Make help for Project SP + + +echo Building Win32 Help files +start /wait hcw /C /E /M "hlp\sp.hpj" +if errorlevel 1 goto :Error +if not exist "hlp\sp.hlp" goto :Error +if not exist "hlp\sp.cnt" goto :Error +echo. +if exist Debug\nul copy "hlp\sp.hlp" Debug +if exist Debug\nul copy "hlp\sp.cnt" Debug +if exist Release\nul copy "hlp\sp.hlp" Release +if exist Release\nul copy "hlp\sp.cnt" Release +echo. +goto :done + +:Error +echo hlp\sp.hpj(1) : error: Problem encountered creating help file + +:done +echo. diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/MemDC.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MemDC.h new file mode 100644 index 0000000..1ac05c9 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/MemDC.h @@ -0,0 +1,93 @@ +#if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_) +#define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// MemDC.h : header file +// + +////////////////////////////////////////////////// +// CMemDC - memory DC +// +// Author: Keith Rule +// Email: keithr@europa.com +// Copyright 1996-1997, Keith Rule +// +// You may freely use or modify this code provided this +// Copyright is included in all derived versions. +// +// History - 10/3/97 Fixed scrolling bug. +// Added print support. +// 25 feb 98 - fixed minor assertion bug +// +// This class implements a memory Device Context + +class CMemDC : public CDC +{ +public: + + // constructor sets up the memory DC + CMemDC(CDC* pDC) : CDC() + { + ASSERT(pDC != NULL); + + m_pDC = pDC; + m_pOldBitmap = NULL; + m_bMemDC = !pDC->IsPrinting(); + + if (m_bMemDC) // Create a Memory DC + { + pDC->GetClipBox(&m_rect); + CreateCompatibleDC(pDC); + m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); + m_pOldBitmap = SelectObject(&m_bitmap); + SetWindowOrg(m_rect.left, m_rect.top); + } + else // Make a copy of the relevent parts of the current DC for printing + { + m_bPrinting = pDC->m_bPrinting; + m_hDC = pDC->m_hDC; + m_hAttribDC = pDC->m_hAttribDC; + } + } + + // Destructor copies the contents of the mem DC to the original DC + ~CMemDC() + { + if (m_bMemDC) + { + // Copy the offscreen bitmap onto the screen. + m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), + this, m_rect.left, m_rect.top, SRCCOPY); + + //Swap back the original bitmap. + SelectObject(m_pOldBitmap); + } else { + // All we need to do is replace the DC with an illegal value, + // this keeps us from accidently deleting the handles associated with + // the CDC that was passed to the constructor. + m_hDC = m_hAttribDC = NULL; + } + } + + // Allow usage as a pointer + CMemDC* operator->() {return this;} + + // Allow usage as a pointer + operator CMemDC*() {return this;} + +private: + CBitmap m_bitmap; // Offscreen bitmap + CBitmap* m_pOldBitmap; // bitmap originally found in CMemDC + CDC* m_pDC; // Saves CDC passed in constructor + CRect m_rect; // Rectangle of drawing area. + BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.cpp new file mode 100644 index 0000000..24d071a --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.cpp @@ -0,0 +1,337 @@ +// ModelCatsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ModelCatsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CModelCatsDlg dialog + + +CModelCatsDlg::CModelCatsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CModelCatsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CModelCatsDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bAddMode=false; + m_pApp = (CSpApp*)AfxGetApp(); + + /*rs=new GZRset("Error: Unit model categories dialog"); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer +rs=m_pApp->rsPool->GetRS("CModelCatsDlg"); + + m_pstrReturnValue=NULL; +} + +CModelCatsDlg::~CModelCatsDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + + +void CModelCatsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CModelCatsDlg) + DDX_Control(pDX, IDC_LBLCATEGORY, m_lblCategory); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_EDCATEGORY, m_edCategory); + DDX_Control(pDX, IDC_CBCATEGORIES, m_cbCategories); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNDELETE, m_btnDelete); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CModelCatsDlg, CDialog) +//{{AFX_MSG_MAP(CModelCatsDlg) +ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) +ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_CBN_CLOSEUP(IDC_CBCATEGORIES, OnCloseupCbcategories) +ON_EN_KILLFOCUS(IDC_EDCATEGORY, OnKillfocusEdcategory) +ON_EN_KILLFOCUS(IDC_EDNOTES, OnKillfocusEdnotes) +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CModelCatsDlg message handlers + +BOOL CModelCatsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + FillList(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CModelCatsDlg::OnBtnadd() +{ + CString strName,strNotes,q; + + if(!m_bAddMode) + { + //go add mode + m_btnDone.ShowWindow(FALSE); + m_btnAdd.SetWindowText("SAVE"); + m_lblCategory.ShowWindow(FALSE); + m_cbCategories.ShowWindow(FALSE); + m_btnDelete.SetWindowText("CANCEL"); + m_edCategory.SetWindowText(""); + m_edNotes.SetWindowText(""); + m_bAddMode=true; + + } + else + { + //save + m_edCategory.GetWindowText(strName); + m_edNotes.GetWindowText(strNotes); + if(strName.IsEmpty()) + { + AfxMessageBox("A category name is required to save this record"); + return; + } + + + q.Format("INSERT INTO unitmodelcats ( name, notes )" + "SELECT \"%s\" , \"%s\";",strName,strNotes); + if(!rs->Ex(q)) + return; + rs->Close(); + + + + //go normal mode + m_btnDone.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_lblCategory.ShowWindow(TRUE); + m_cbCategories.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_strSelectedCategory=""; + m_bAddMode=false; + FillList(); + } + + +} + +void CModelCatsDlg::OnBtndelete() +{ + CString q; + if(m_bAddMode) + { + m_btnDone.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_lblCategory.ShowWindow(TRUE); + m_cbCategories.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_strSelectedCategory=""; + m_bAddMode=false; + FillList(); + + return; + } + + + + //DELETE + //see if it can be deleted first + q.Format("SELECT unitmodels.id " + "FROM unitmodels WHERE (((unitmodels.category)=%s));",m_strSelectedCategory); + + rs->Query(q); + if(!rs->IsEmpty()) + { + AfxMessageBox("Data integrity protection!\r\n" + "You can't delete this record at this time because\r\n" + "it's attached to one or more Unit models."); + return; + } + + + if(AfxMessageBox("Permanently delete this category.\r\nAre you sure?",MB_YESNO)==IDYES) + { + //run a delete query on it + q.Format("DELETE unitmodelcats.*, unitmodelcats.id " + "FROM unitmodelcats WHERE (((unitmodelcats.id)=%s));",m_strSelectedCategory); + rs->Ex(q); + m_strSelectedCategory.Empty(); + FillList(); + + + + } + +} + +void CModelCatsDlg::OnBtndone() +{ + if(m_pstrReturnValue!=NULL) + *m_pstrReturnValue=m_strSelectedCategory; + CDialog::OnOK(); +} + +void CModelCatsDlg::OnCloseupCbcategories() +{ + m_strSelectedCategory=m_cbCategories.GetCurrentRowID(); + + FillFields(); +} + +void CModelCatsDlg::OnKillfocusEdcategory() +{ + + + SaveField(&m_edCategory,"name",false); + if(!m_bAddMode) + FillList(); + +} + +void CModelCatsDlg::OnKillfocusEdnotes() +{ + + SaveField(&m_edNotes,"notes",false); + +} + +void CModelCatsDlg::SetReturnString(CString *strReturn) +{ + m_pstrReturnValue=strReturn; +} + + + +//**************************************** +//FILL LIST BOX +//**************************************** +void CModelCatsDlg::FillList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbCategories.Clear(); + + + + rs->Query("SELECT unitmodelcats.* FROM unitmodelcats;"); + if(rs->IsEmpty()) + return; + + + rs->MoveFirst(); + + do + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbCategories.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + + + //pretend user has selected so that other fields get filled in + if(m_strSelectedCategory.IsEmpty()) //first time in + { + m_cbCategories.SetCurSel(0); + m_strSelectedCategory=m_cbCategories.GetCurrentRowID(); + + } + else//something valid was selected before so stick with it + m_cbCategories.Select(m_strSelectedCategory); + + + FillFields(); + + +} + + +//Fillout contents of fields +void CModelCatsDlg::FillFields() +{ + CString q,strData; + q.Format("SELECT unitmodelcats.* " + "FROM unitmodelcats " + "WHERE (((unitmodelcats.id)=%s));",m_cbCategories.GetCurrentRowID()); + + rs->Query(q); + if(rs->IsEmpty()) + return; + rs->FetchField("name",&strData); + m_edCategory.SetWindowText(strData); + + rs->FetchField("notes",&strData); + m_edNotes.SetWindowText(strData); + +} + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CModelCatsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + + return true; +} + + + +void CModelCatsDlg::Security() +{ + + int x=m_pApp->Allowed(RMODELS,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + + //m_cbCategories.EnableWindow(FALSE); + m_edCategory.SetReadOnly(TRUE); + m_edNotes.SetReadOnly(TRUE); + m_lblCategory.EnableWindow(FALSE); + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.h new file mode 100644 index 0000000..bc5ecdd --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelCatsDlg.h @@ -0,0 +1,72 @@ +#if !defined(AFX_MODELCATSDLG_H__19D53F22_27FA_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_MODELCATSDLG_H__19D53F22_27FA_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ModelCatsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CModelCatsDlg dialog +#include "gzcombo.h" +#include "gzrset.h" + +class CModelCatsDlg : public CDialog +{ +// Construction +public: + bool m_bReadOnly; + void Security(); + ~CModelCatsDlg(); + void FillFields(); + void FillList(); + bool m_bAddMode; + CString m_strSelectedCategory; + void SetReturnString(CString* strReturn); + CModelCatsDlg(CWnd* pParent = NULL); // standard constructor + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + + CSpApp* m_pApp; +GZRset* rs; +CString * m_pstrReturnValue; +// Dialog Data + //{{AFX_DATA(CModelCatsDlg) + enum { IDD = IDD_MODELCATS }; + CStatic m_lblCategory; + CEdit m_edNotes; + CEdit m_edCategory; + CgzCombo m_cbCategories; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CModelCatsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CModelCatsDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnBtnadd(); + afx_msg void OnBtndelete(); + afx_msg void OnBtndone(); + afx_msg void OnCloseupCbcategories(); + afx_msg void OnKillfocusEdcategory(); + afx_msg void OnKillfocusEdnotes(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MODELCATSDLG_H__19D53F22_27FA_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.cpp new file mode 100644 index 0000000..ac8cac6 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.cpp @@ -0,0 +1,951 @@ +// ModelsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ModelsDlg.h" +#include "ModelCatsDlg.h" +#include "NonClientsDlg.h" +#include "PM.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CModelsDlg dialog + + +CModelsDlg::CModelsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CModelsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CModelsDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bAddMode=false; + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Unit models dialog"); + rs->SetConnect(m_pApp->strConnectString); + + cbrs=new GZRset("Error: Unit models dialog combo box recordset\r\n"); + cbrs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + +cbrs=m_pApp->rsPool->GetRS("CModelsDlg (CBRS)"); +rs=m_pApp->rsPool->GetRS("CModelsDlg (RS)"); + + m_pstrReturnValue=NULL; + m_strSelectedModel.Empty(); + m_bListByDescription=true; + +} + +CModelsDlg::~CModelsDlg() +{ + + m_pApp->rsPool->ReleaseRS(&cbrs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + + +void CModelsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CModelsDlg) + DDX_Control(pDX, IDC_LBLBYDESC, m_lblByDesc); + DDX_Control(pDX, IDC_LBLBYMODEL, m_lblByModel); + DDX_Control(pDX, IDC_EDDESCRIPTION, m_edDescription); + DDX_Control(pDX, IDC_BTNPM, m_btnPM); + DDX_Control(pDX, IDC_LBLMODELLIST, m_lblModels); + DDX_Control(pDX, IDC_LBLMANUFACTURER, m_lblManufacturer); + DDX_Control(pDX, IDC_LBLCATEGORY, m_lblCategory); + DDX_Control(pDX, IDC_EDWARRANTYTERMS, m_edWarrantyTerms); + DDX_Control(pDX, IDC_EDWARRANTYMONTHS, m_edWarrantyMonths); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_EDMODEL, m_edModel); + DDX_Control(pDX, IDC_DTINTRODUCED, m_dtIntroduced); + DDX_Control(pDX, IDC_DTDISCONTINUED, m_dtDiscontinued); + DDX_Control(pDX, IDC_CKLIFETIME, m_ckLifetime); + DDX_Control(pDX, IDC_CKDISCONTINUED, m_ckDiscontinued); + DDX_Control(pDX, IDC_CKACTIVE, m_ckActive); + DDX_Control(pDX, IDC_CBMODELS, m_cbModels); + DDX_Control(pDX, IDC_CBMANUFACTURERS, m_cbManufacturers); + DDX_Control(pDX, IDC_CBCATEGORIES, m_cbCategories); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNDELETE, m_btnDelete); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CModelsDlg, CDialog) + //{{AFX_MSG_MAP(CModelsDlg) + ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) + ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_CBN_CLOSEUP(IDC_CBCATEGORIES, OnCloseupCbcategories) + ON_CBN_CLOSEUP(IDC_CBMANUFACTURERS, OnCloseupCbmanufacturers) + ON_CBN_CLOSEUP(IDC_CBMODELS, OnCloseupCbmodels) + ON_BN_CLICKED(IDC_CKDISCONTINUED, OnCkdiscontinued) + ON_BN_CLICKED(IDC_CKLIFETIME, OnCklifetime) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTDISCONTINUED, OnDatetimechangeDtdiscontinued) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTINTRODUCED, OnDatetimechangeDtintroduced) + ON_EN_KILLFOCUS(IDC_EDMODEL, OnKillfocusEdmodel) + ON_EN_KILLFOCUS(IDC_EDNOTES, OnKillfocusEdnotes) + ON_EN_KILLFOCUS(IDC_EDWARRANTYMONTHS, OnKillfocusEdwarrantymonths) + ON_EN_KILLFOCUS(IDC_EDWARRANTYTERMS, OnKillfocusEdwarrantyterms) + ON_BN_CLICKED(IDC_LBLCATEGORY, OnLblcategory) + ON_BN_CLICKED(IDC_LBLMANUFACTURER, OnLblmanufacturer) + ON_BN_CLICKED(IDC_BTNPM, OnBtnpm) + ON_EN_KILLFOCUS(IDC_EDDESCRIPTION, OnKillfocusEddescription) + ON_BN_CLICKED(IDC_LBLBYMODEL, OnLblbymodel) + ON_BN_CLICKED(IDC_LBLBYDESC, OnLblbydesc) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CModelsDlg message handlers + +BOOL CModelsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + //make "hyperlinks" + m_lblCategory.SetTextColor(RGB(0,0,255)); + m_lblCategory.SetFontUnderline(TRUE); + m_lblCategory.SetLink(TRUE); + m_lblCategory.SetLinkCursor(m_pApp->hcHand); + m_lblCategory.SetLinkURL(""); + + + //make "hyperlinks" + m_lblManufacturer.SetTextColor(RGB(0,0,255)); + m_lblManufacturer.SetFontUnderline(TRUE); + m_lblManufacturer.SetLink(TRUE); + m_lblManufacturer.SetLinkCursor(m_pApp->hcHand); + m_lblManufacturer.SetLinkURL(""); + + + m_lblByDesc.SetTextColor(RGB(0,0,255)); + m_lblByDesc.SetFontUnderline(TRUE); + m_lblByDesc.SetLink(TRUE); + m_lblByDesc.SetLinkCursor(m_pApp->hcHand); + m_lblByDesc.SetLinkURL(""); + + m_lblByModel.SetTextColor(RGB(0,0,255)); + m_lblByModel.SetFontUnderline(TRUE); + m_lblByModel.SetLink(TRUE); + m_lblByModel.SetLinkCursor(m_pApp->hcHand); + m_lblByModel.SetLinkURL(""); + + + FillCategoryList(); + FillManufacturerList(); +//this one has to be last because it's going to + //trigger selections on the other two + FillModelList(); + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + + + + + + +void CModelsDlg::OnBtnadd() +{ + CString strData; + long lData; + bool bData; + COleDateTime dtData; + CString q; + + if(!m_bAddMode) + { + //Go into add mode + EnableFields(true); + m_bAddMode=true; + m_lblModels.ShowWindow(FALSE); + m_cbModels.ShowWindow(FALSE); + m_btnPM.ShowWindow(FALSE); + m_btnDone.ShowWindow(FALSE); + m_btnAdd.SetWindowText("SAVE"); + m_btnDelete.SetWindowText("CANCEL"); + m_cbCategories.Select("0"); + m_cbManufacturers.Select("0"); + m_ckDiscontinued.SetCheck(FALSE); + m_ckLifetime.SetCheck(FALSE); + m_dtDiscontinued.SetTime(COleDateTime::GetCurrentTime()); + m_dtIntroduced.SetTime(COleDateTime::GetCurrentTime()); + m_edModel.SetWindowText(""); + m_edDescription.SetWindowText(""); + m_edNotes.SetWindowText(""); + m_edWarrantyMonths.SetWindowText(""); + m_edWarrantyTerms.SetWindowText(""); + m_lblByDesc.ShowWindow(FALSE); + m_lblByModel.ShowWindow(FALSE); + + } + else + { + //Validate and Save record + m_edModel.GetWindowText(strData); + if(strData.IsEmpty()) + { + AfxMessageBox("A Model number is required to save this record"); + return; + } + + //check if duplicate model number + q.Format("SELECT unitmodels.model FROM unitmodels WHERE (((unitmodels.model)=\"%s\"));",strData); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + q.Format("Model number \"%s\" has already been used.\r\n" + "Each model record must have a unique model number\r\n" + "Change the model number to save this record.",strData); + AfxMessageBox(q); + m_edModel.SetFocus(); + return; + + } + rs->Query("SELECT unitmodels.* FROM unitmodels WHERE unitmodels.id = 0;"); + rs->AddNewRecord(); + + //MODEL + rs->UpdateField("model",&strData); + + //Description + m_edDescription.GetWindowText(strData); + rs->UpdateField("description",&strData); + + //CATEGORY + strData=m_cbCategories.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("category",&lData); + + //LIFETIMEWARRANTY + bData=(m_ckLifetime.GetCheck() ? true : false); + rs->UpdateField("lifetimewarranty",&bData); + + //WARRANTY (months) + m_edWarrantyMonths.GetWindowText(strData); + lData=atol(strData); + rs->UpdateField("warranty",&lData); + + //WARRANTYTERMS + m_edWarrantyTerms.GetWindowText(strData); + rs->UpdateField("warrantyterms",&strData); + + //MANUFACTURER + strData=m_cbManufacturers.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("manufacturer",&lData); + + //DISCONTINUED + bData=(m_ckDiscontinued.GetCheck() ? true : false); + rs->UpdateField("discontinued",&bData); + + //DISCONTINUED DATE + m_dtDiscontinued.GetTime(dtData); + rs->UpdateField("discodate",&dtData); + + //INTRODUCED DATE + m_dtIntroduced.GetTime(dtData); + rs->UpdateField("introduced",&dtData); + + //NOTES + m_edNotes.GetWindowText(strData); + rs->UpdateField("notes",&strData); + + //SAVE NEW RECORD + rs->SaveRecord(); + + + m_bAddMode=false; + m_lblByDesc.ShowWindow(TRUE); + m_lblByModel.ShowWindow(TRUE); + m_btnPM.ShowWindow(TRUE); + m_lblModels.ShowWindow(TRUE); + m_cbModels.ShowWindow(TRUE); + m_btnDone.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + FillModelList(); + } + +} + + +//Delete +void CModelsDlg::OnBtndelete() +{ + CString q; + + if(m_bAddMode)//then this is the cancel button + { + m_bAddMode=false; + m_btnPM.ShowWindow(TRUE); + m_lblModels.ShowWindow(TRUE); + m_cbModels.ShowWindow(TRUE); + m_btnDone.ShowWindow(TRUE); + m_lblByDesc.ShowWindow(TRUE); + m_lblByModel.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + FillModelList(); + return; + } + + if(m_bNoRecords) return; + + //Delete the current record + + //check if safe to delete + q.Format("SELECT units.id " + "FROM units WHERE (((units.model)=%s));",m_cbModels.GetCurrentRowID()); + + cbrs->Query(q); + + if(!cbrs->IsEmpty()) + { + AfxMessageBox("DATA INTEGRITY PROTECTION!\r\n" + "There are one or more units that are attached to this model number.\r\n" + "You can't delete this record at this time."); + return; + + } + + //SAFE TO DELETE + q.Format("DELETE unitmodels.*, unitmodels.id " + "FROM unitmodels WHERE (((unitmodels.id)=%s));",m_cbModels.GetCurrentRowID()); + + if(AfxMessageBox("Delete this record permanently?\r\nAre you sure?",MB_YESNO)==IDYES) + { + cbrs->Ex(q); + m_strSelectedModel=""; + FillModelList(); + } + + + +} + + + + + + + + + + + +void CModelsDlg::OnBtndone() +{ + + CDialog::OnOK(); +} + + +//******************************** +void CModelsDlg::OnCloseupCbcategories() +{ + SaveField(&m_cbCategories,"category"); + +} + +void CModelsDlg::OnCloseupCbmanufacturers() +{ + SaveField(&m_cbManufacturers,"manufacturer"); + +} + + +//-**************************** +void CModelsDlg::OnCloseupCbmodels() +{ + m_strSelectedModel=m_cbModels.GetCurrentRowID(); + + FillFields(); + +} + + +//******************************* +void CModelsDlg::OnCkdiscontinued() +{ + SaveField(&m_ckDiscontinued,"discontinued"); + m_dtDiscontinued.ShowWindow(m_ckDiscontinued.GetCheck()); + if(m_bReadOnly) + m_dtDiscontinued.EnableWindow(FALSE); +} + + +//******************************* +void CModelsDlg::OnCklifetime() +{ + SaveField(&m_ckLifetime,"lifetimewarranty"); + +} + +//************************************************ +void CModelsDlg::OnDatetimechangeDtdiscontinued(NMHDR* pNMHDR, LRESULT* pResult) +{ + SaveField(&m_dtDiscontinued,"discodate"); + + + *pResult = 0; +} + +//************************************************ +void CModelsDlg::OnDatetimechangeDtintroduced(NMHDR* pNMHDR, LRESULT* pResult) +{ + SaveField(&m_dtIntroduced,"introduced"); + *pResult = 0; +} + +//***************************************** +void CModelsDlg::OnKillfocusEdmodel() +{ + + SaveField(&m_edModel,"model",false); + if(!m_bAddMode) + FillModelList(); +} + +//********************************************* +void CModelsDlg::OnKillfocusEdnotes() +{ + SaveField(&m_edNotes,"notes",true); + +} + +//************************************************ +void CModelsDlg::OnKillfocusEdwarrantymonths() +{ + + long lData; + + CString str; + //do nothing if not changed + if(m_edWarrantyMonths.GetModify()!=TRUE) return; + + m_edWarrantyMonths.GetWindowText(str); + //lData=atol(str); +_variant_t vtData(str); +//v1.9.4.4 added try / catch mechanism to catch dumb-asses entering text in a numeric field + try + { + lData=(long)vtData;//cast variant to float (locale friendly) + } + catch( _com_error &e ) + { + + AfxMessageBox("I could not interpret your entry in the Warranty Months 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_edWarrantyMonths.Undo(); + m_edWarrantyMonths.SetModify(FALSE); + m_edWarrantyMonths.SetFocus(); + return; + } + + //v1.9.4.4 moved down here so validation will run in any mode + if(m_bAddMode) return;//dont attempt to update + + rs->UpdateField("warranty",&lData); + rs->SaveRecord(); + UpdateModified(); + + +} + +void CModelsDlg::OnKillfocusEdwarrantyterms() +{ + SaveField(&m_edWarrantyTerms,"warrantyterms",true); + +} + + +//******************************* +void CModelsDlg::OnLblcategory() +{ + CString str,id; + CModelCatsDlg d; + d.SetReturnString(&str); +if(d.DoModal()==IDOK) + { + id=m_cbCategories.GetCurrentRowID(); + FillCategoryList(); + m_cbCategories.Select(id); +} + //OnCloseupCbcategories(); + +} + + +//********************************** +void CModelsDlg::OnLblmanufacturer() +{ + CString str,id; + long ldata=3;//manufacturers are type 3 + CNonClientsDlg d; + d.SetType(&ldata); + d.SetReturnString(&str); + if(d.DoModal()==IDOK) + { + id=m_cbManufacturers.GetCurrentRowID(); + FillManufacturerList(); + m_cbManufacturers.Select(id); + //this will save the field change tothe + //database since the user didn't select + //the regular way. + ////OnCloseupCbmanufacturers(); + + + } +} + +void CModelsDlg::FillCategoryList() +{ + CString strData; + CString strIndex; + long lData; + m_cbCategories.Clear(); + + //Set the default + strData=""; + strIndex="0"; + m_cbCategories.AddRow(strData,strIndex); + + cbrs->Query("SELECT unitmodelcats.* FROM unitmodelcats;"); + if(cbrs->IsEmpty()) + return; + + + cbrs->MoveFirst(); + + do + { + cbrs->FetchField("name",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbCategories.AddRow(strData,strIndex); + }while(cbrs->MoveForward()); + + + + +} + + + +//******************************** +void CModelsDlg::FillModelList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbModels.Clear(); + + + if(m_bListByDescription) + { + rs->Query("SELECT [company_person] & \" \" & [description] & \" \" & [model] AS item, unitmodels.id " + "FROM unitmodels LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "ORDER BY [company_person] & \" \" & [description] & \" \" & [model];"); + + } + else + { + rs->Query("SELECT [model] & \" \" & [company_person] & \" \" & [description] AS item, unitmodels.id " + "FROM unitmodels LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "ORDER BY [company_person] & \" \" & [description] & \" \" & [model];"); + + } + + if(rs->IsEmpty()) + { + EnableFields(false); + m_bNoRecords=true; + return; + } + else + m_bNoRecords=false; + EnableFields(true); + + rs->MoveFirst(); + + do + { + rs->FetchField("item",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbModels.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + + //pretend user has selected so that other fields get filled in + if(m_strSelectedModel.IsEmpty()) //first time in + { + m_cbModels.SetCurSel(0); + m_strSelectedModel=m_cbModels.GetCurrentRowID(); + + } + else//something valid was selected before so stick with it + m_cbModels.Select(m_strSelectedModel); + + + //trigger selection + OnCloseupCbmodels(); +} + + +//******************************************** +void CModelsDlg::FillManufacturerList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbManufacturers.Clear(); + + //set defaults + strData=""; + strIndex="0"; + m_cbManufacturers.AddRow(strData,strIndex); + + //type 3 = manufacturers + cbrs->Query("SELECT nonclients.* " +"FROM nonclients " +"WHERE (((nonclients.type)=3)) " +"ORDER BY nonclients.company_person;"); + + + if(cbrs->IsEmpty()) + return; + + + cbrs->MoveFirst(); + + do + { + cbrs->FetchField("company_person",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbManufacturers.AddRow(strData,strIndex); + }while(cbrs->MoveForward()); + +} + + +//******************************************* + +void CModelsDlg::SetReturnString(CString *strReturn) +{ + m_pstrReturnValue=strReturn; + //specific record should be shown? + if(!m_pstrReturnValue->IsEmpty()) + m_strSelectedModel=*m_pstrReturnValue; +} + + + +//**************************************** +void CModelsDlg::FillFields() +{ + + CString q,strData; + COleDateTime dtData; + bool bData; + long lData; + //Fill all fields based on current record. + strData=m_cbModels.GetCurrentRowID(); + if(strData.IsEmpty()) + return; + + q.Format("SELECT unitmodels.* " + "FROM unitmodels " + "WHERE (((unitmodels.id)=%s));",strData); + + rs->Query(q); + + if(rs->IsEmpty()) + return;//something very wrong if this ever gets called + + //FETCHFIELDS AND FILL BOXES + + //MODEL + rs->FetchField("model",&strData); + m_edModel.SetWindowText(strData); + + //DESCRIPTION + rs->FetchField("description",&strData); + m_edDescription.SetWindowText(strData); + + //CATEGORY + rs->FetchField("category",&lData); + strData.Format("%u",lData); + m_cbCategories.Select(strData); + + //LIFETIMEWARRANTY + rs->FetchField("lifetimewarranty",&bData); + m_ckLifetime.SetCheck(bData ? TRUE : FALSE); + + //WARRANTY (months) + rs->FetchField("warranty",&lData); + strData.Format("%u",lData); + m_edWarrantyMonths.SetWindowText(strData); + + //WARRANTYTERMS + rs->FetchField("warrantyterms",&strData); + m_edWarrantyTerms.SetWindowText(strData); + + //MANUFACTURER + rs->FetchField("manufacturer",&lData); + strData.Format("%u",lData); + m_cbManufacturers.Select(strData); + + //DISCONTINUED + rs->FetchField("discontinued",&bData); + m_ckDiscontinued.SetCheck(bData ? TRUE : FALSE); + m_dtDiscontinued.ShowWindow(bData ? TRUE : FALSE); + if(m_bReadOnly) + m_dtDiscontinued.EnableWindow(FALSE); + //DISCONTINUED DATE (IF APPLICABLE) + if(bData) + { + rs->FetchField("discodate",&dtData); + m_dtDiscontinued.SetTime(dtData); + + } + + //INTRODUCED DATE + rs->FetchField("introduced",&dtData); + m_dtIntroduced.SetTime(dtData); + + //NOTES + rs->FetchField("notes",&strData); + m_edNotes.SetWindowText(strData); + + // +} + + + + + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CModelsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode || m_bNoRecords) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE GZCOMBO CONTROL FIELD +//************************************************************ +bool CModelsDlg::SaveField(CgzCombo *cbControl,CString fldname) +{ + + if(m_bAddMode || m_bNoRecords) return true;//dont attempt to update + CString str; + long lData; + str=cbControl->GetCurrentRowID(); + if(str.IsEmpty()) return false;//shouldn't happen but... + lData=atol(str); + rs->UpdateField(fldname,&lData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CModelsDlg::SaveField(CButton *ckControl,CString fldname) +{ + if(m_bAddMode || m_bNoRecords) return true;//dont attempt to update + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + UpdateModified(); + return true; +} +//************************************************************ +//SAVE DateTimePicker CONTROL FIELD +//************************************************************ +bool CModelsDlg::SaveField(CDateTimeCtrl *dtControl,CString fldname) +{ + if(m_bAddMode || m_bNoRecords) return true;//dont attempt to update + COleDateTime dtData; + dtControl->GetTime(dtData); + rs->UpdateField(fldname,&dtData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + + +//************************************************ +//UPDATE MODIFIED DATA +//************************************************* +bool CModelsDlg::UpdateModified() +{ + + //updates modified by and modified on fields + rs->UpdateField("modifier",&m_pApp->m_lusrID); + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + rs->SaveRecord(); + + + return true; +} + + + + + + + +void CModelsDlg::OnBtnpm() +{ + + if(m_bNoRecords || m_strSelectedModel.IsEmpty() || m_strSelectedModel=="0") return; + + +//Open the PM dialog for this model + CPM d; + CString prompt; + CString str; + str=m_cbModels.GetCurrentRowText();//m_edModel.GetWindowText(str); + prompt="Preventive maintenance for Model#: " + str; + + //set criteria serial number + d.PreInitialize(false,true,m_strSelectedModel,prompt); + d.DoModal(); + + +} + + +void CModelsDlg::EnableFields(bool bEnable) +{ + if(m_bReadOnly) + return; + BOOL enable = bEnable ? TRUE : FALSE; + m_btnDelete.EnableWindow(enable); + m_btnPM.EnableWindow(enable); + m_cbCategories.EnableWindow(enable); + m_cbManufacturers.EnableWindow(enable); + m_cbModels.EnableWindow(enable); + m_ckActive.EnableWindow(enable); + m_ckDiscontinued.EnableWindow(enable); + m_ckLifetime.EnableWindow(enable); + m_dtDiscontinued.EnableWindow(enable); + m_dtIntroduced.EnableWindow(enable); + m_edModel.EnableWindow(enable); + m_edNotes.EnableWindow(enable); + m_lblCategory.EnableWindow(enable); + m_lblManufacturer.EnableWindow(enable); + m_lblModels.EnableWindow(enable); + m_edWarrantyMonths.EnableWindow(enable); + m_edWarrantyTerms.EnableWindow(enable); + m_edDescription.EnableWindow(enable); + +} + +void CModelsDlg::OnKillfocusEddescription() +{ +SaveField(&m_edDescription,"description",true); +if(!m_bAddMode) + FillModelList(); +} + +void CModelsDlg::OnLblbymodel() +{ +m_bListByDescription=false; +FillModelList(); +} + +void CModelsDlg::OnLblbydesc() +{ +m_bListByDescription=true; +FillModelList(); +} + +void CModelsDlg::Security() +{ + m_bReadOnly=false; + int x=m_pApp->Allowed(RMODELS,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + m_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_cbCategories.EnableWindow(FALSE); + m_cbManufacturers.EnableWindow(FALSE); + //m_cbModels.EnableWindow(FALSE); + m_ckActive.EnableWindow(FALSE); + m_ckDiscontinued.EnableWindow(FALSE); + m_ckLifetime.EnableWindow(FALSE); + m_dtDiscontinued.EnableWindow(FALSE); + m_dtIntroduced.EnableWindow(FALSE); + m_edDescription.SetReadOnly(TRUE); + m_edModel.SetReadOnly(TRUE); + m_edWarrantyTerms.SetReadOnly(TRUE); + m_edWarrantyMonths.SetReadOnly(TRUE); + m_lblCategory.EnableWindow(FALSE); + m_lblManufacturer.EnableWindow(FALSE); + + m_lblModels.EnableWindow(FALSE); + m_edNotes.SetReadOnly(TRUE); + + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.h new file mode 100644 index 0000000..43bea6c --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModelsDlg.h @@ -0,0 +1,115 @@ +#if !defined(AFX_MODELSDLG_H__19D53F21_27FA_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_MODELSDLG_H__19D53F21_27FA_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ModelsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CModelsDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +//#include "statusdlg.h" +class CModelsDlg : public CDialog +{ +// Construction +public: + bool m_bReadOnly; + void Security(); + bool m_bListByDescription; + void EnableFields(bool bEnable); + bool m_bNoRecords; + ~CModelsDlg(); + bool m_bAddMode; + void FillFields(); + CString m_strSelectedModel; + void FillManufacturerList(); + void FillModelList(); + void FillCategoryList(); + void SetReturnString(CString *strReturn); + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool SaveField(CgzCombo* cbControl,CString fldname); + bool SaveField(CButton* ckControl,CString fldname); + bool SaveField(CDateTimeCtrl* dtControl,CString fldname); + bool UpdateModified(); + //------------------------------- + CModelsDlg(CWnd* pParent = NULL); // standard constructor +CSpApp* m_pApp; + +//The Extra recordset is for filling combo boxes +GZRset* rs; +GZRset* cbrs; +CString * m_pstrReturnValue; +// Dialog Data + //{{AFX_DATA(CModelsDlg) + enum { IDD = IDD_MODELS }; + CLabel m_lblByDesc; + CLabel m_lblByModel; + CEdit m_edDescription; + CButton m_btnPM; + CStatic m_lblModels; + CLabel m_lblManufacturer; + CLabel m_lblCategory; + CEdit m_edWarrantyTerms; + CEdit m_edWarrantyMonths; + CEdit m_edNotes; + CEdit m_edModel; + CDateTimeCtrl m_dtIntroduced; + CDateTimeCtrl m_dtDiscontinued; + CButton m_ckLifetime; + CButton m_ckDiscontinued; + CButton m_ckActive; + CgzCombo m_cbModels; + CgzCombo m_cbManufacturers; + CgzCombo m_cbCategories; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CModelsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CModelsDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnBtnadd(); + afx_msg void OnBtndelete(); + afx_msg void OnBtndone(); + afx_msg void OnCloseupCbcategories(); + afx_msg void OnCloseupCbmanufacturers(); + afx_msg void OnCloseupCbmodels(); + afx_msg void OnCkdiscontinued(); + afx_msg void OnCklifetime(); + afx_msg void OnDatetimechangeDtdiscontinued(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDatetimechangeDtintroduced(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKillfocusEdmodel(); + afx_msg void OnKillfocusEdnotes(); + afx_msg void OnKillfocusEdwarrantymonths(); + afx_msg void OnKillfocusEdwarrantyterms(); + afx_msg void OnLblcategory(); + afx_msg void OnLblmanufacturer(); + afx_msg void OnBtnpm(); + afx_msg void OnKillfocusEddescription(); + afx_msg void OnLblbymodel(); + afx_msg void OnLblbydesc(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MODELSDLG_H__19D53F21_27FA_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.cpp new file mode 100644 index 0000000..ca2b7d6 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.cpp @@ -0,0 +1,135 @@ +//////////////////////////////////////////////////////////////// +// 1998 Microsoft Systems Journal +// If this code works, it was written by Paul DiLascia. +// If not, I don't know who wrote it. +// +// CModuleVersion provides an easy way to get version info +// for a module.(DLL or EXE). +// +#include "StdAfx.h" +#include "ModulVer.h" + +CModuleVersion::CModuleVersion() +{ + m_pVersionInfo = NULL; // raw version info data +} + +////////////////// +// Destroy: delete version info +// +CModuleVersion::~CModuleVersion() +{ + delete [] m_pVersionInfo; +} + +////////////////// +// Get file version info for a given module +// Allocates storage for all info, fills "this" with +// VS_FIXEDFILEINFO, and sets codepage. +// +BOOL CModuleVersion::GetFileVersionInfo(LPCTSTR modulename) +{ + m_translation.charset = 1252; // default = ANSI code page + memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO)); + + // get module handle + TCHAR filename[_MAX_PATH]; + HMODULE hModule = ::GetModuleHandle(modulename); + if (hModule==NULL && modulename!=NULL) + return FALSE; + + // get module file name + DWORD len = GetModuleFileName(hModule, filename, + sizeof(filename)/sizeof(filename[0])); + if (len <= 0) + return FALSE; + + // read file version info + DWORD dwDummyHandle; // will always be set to zero + len = GetFileVersionInfoSize(filename, &dwDummyHandle); + if (len <= 0) + return FALSE; + + m_pVersionInfo = new BYTE[len]; // allocate version info + if (!::GetFileVersionInfo(filename, 0, len, m_pVersionInfo)) + return FALSE; + + LPVOID lpvi; + UINT iLen; + if (!VerQueryValue(m_pVersionInfo, _T("\\"), &lpvi, &iLen)) + return FALSE; + + // copy fixed info to myself, which am derived from VS_FIXEDFILEINFO + *(VS_FIXEDFILEINFO*)this = *(VS_FIXEDFILEINFO*)lpvi; + + // Get translation info + if (VerQueryValue(m_pVersionInfo, + "\\VarFileInfo\\Translation", &lpvi, &iLen) && iLen >= 4) { + m_translation = *(TRANSLATION*)lpvi; + TRACE("code page = %d\n", m_translation.charset); + } + + return dwSignature == VS_FFI_SIGNATURE; +} + +////////////////// +// Get string file info. +// Key name is something like "CompanyName". +// returns the value as a CString. +// +CString CModuleVersion::GetValue(LPCTSTR lpKeyName) +{ + CString sVal; + if (m_pVersionInfo) { + + // To get a string value must pass query in the form + // + // "\StringFileInfo\\keyname" + // + // where is the languageID concatenated with the + // code page, in hex. Wow. + // + CString query; + query.Format(_T("\\StringFileInfo\\%04x%04x\\%s"), + m_translation.langID, + m_translation.charset, + lpKeyName); + + LPCTSTR pVal; + UINT iLenVal; + if (VerQueryValue(m_pVersionInfo, (LPTSTR)(LPCTSTR)query, + (LPVOID*)&pVal, &iLenVal)) { + + sVal = pVal; + } + } + return sVal; +} + +// typedef for DllGetVersion proc +typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *); + +///////////////// +// Get DLL Version by calling DLL's DllGetVersion proc +// +BOOL CModuleVersion::DllGetVersion(LPCTSTR modulename, DLLVERSIONINFO& dvi) +{ + HINSTANCE hinst = LoadLibrary(modulename); + if (!hinst) + return FALSE; + + // Must use GetProcAddress because the DLL might not implement + // DllGetVersion. Depending upon the DLL, the lack of implementation of the + // function may be a version marker in itself. + // + DLLGETVERSIONPROC pDllGetVersion = + (DLLGETVERSIONPROC)GetProcAddress(hinst, _T("DllGetVersion")); + + if (!pDllGetVersion) + return FALSE; + + memset(&dvi, 0, sizeof(dvi)); // clear + dvi.cbSize = sizeof(dvi); // set size for Windows + + return SUCCEEDED((*pDllGetVersion)(&dvi)); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.h new file mode 100644 index 0000000..6496ff4 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ModulVer.h @@ -0,0 +1,63 @@ +//////////////////////////////////////////////////////////////// +// 1998 Microsoft Systems Journal +// +// If this code works, it was written by Paul DiLascia. +// If not, I don't know who wrote it. +// +#ifndef __MODULEVER_H +#define __MODULEVER_H + +// tell linker to link with version.lib for VerQueryValue, etc. +#pragma comment(linker, "/defaultlib:version.lib") + +#ifndef DLLVERSIONINFO +// following is from shlwapi.h, in November 1997 release of the Windows SDK + +typedef struct _DllVersionInfo +{ + DWORD cbSize; + DWORD dwMajorVersion; // Major version + DWORD dwMinorVersion; // Minor version + DWORD dwBuildNumber; // Build number + DWORD dwPlatformID; // DLLVER_PLATFORM_* +} DLLVERSIONINFO; + +// Platform IDs for DLLVERSIONINFO +#define DLLVER_PLATFORM_WINDOWS 0x00000001 // Windows 95 +#define DLLVER_PLATFORM_NT 0x00000002 // Windows NT + +#endif // DLLVERSIONINFO + + + +////////////////// +// CModuleVersion version info about a module. +// To use: +// +// CModuleVersion ver +// if (ver.GetFileVersionInfo("_T("mymodule))) { +// // info is in ver, you can call GetValue to get variable info like +// CString s = ver.GetValue(_T("CompanyName")); +// } +// +// You can also call the static fn DllGetVersion to get DLLVERSIONINFO. +// +class CModuleVersion : public VS_FIXEDFILEINFO { +protected: + BYTE* m_pVersionInfo; // all version info + + struct TRANSLATION { + WORD langID; // language ID + WORD charset; // character set (code page) + } m_translation; + +public: + CModuleVersion(); + virtual ~CModuleVersion(); + + BOOL GetFileVersionInfo(LPCTSTR modulename); + CString GetValue(LPCTSTR lpKeyName); + static BOOL DllGetVersion(LPCTSTR modulename, DLLVERSIONINFO& dvi); +}; + +#endif diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.cpp new file mode 100644 index 0000000..8780d47 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.cpp @@ -0,0 +1,677 @@ +// NonClientsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "NonClientsDlg.h" +#include "StatusDlg.h" +#include ".\nonclientsdlg.h" +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CNonClientsDlg dialog + + +CNonClientsDlg::CNonClientsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CNonClientsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNonClientsDlg) + //}}AFX_DATA_INIT + m_pstrReturnValue=NULL; + m_strSelectedContact.Empty(); + m_lListType=0;//not specified + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Non-client entry screen"); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + +rs=m_pApp->rsPool->GetRS("CNonClientsDlg"); +//v1.9.4.4 +rs2=m_pApp->rsPool->GetRS("CNonClientsDlgRS2"); +} + + +//destructor added by me later! +CNonClientsDlg::~CNonClientsDlg() +{ + +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +//v1.9.4.4 +m_pApp->rsPool->ReleaseRS(&rs2->m_nID); +} + +void CNonClientsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNonClientsDlg) + DDX_Control(pDX, IDC_EDACCT, m_edAccount); + DDX_Control(pDX, IDC_DONE, m_btnDone); + DDX_Control(pDX, IDC_HISTORY, m_lblHistory); + DDX_Control(pDX, IDC_LBLLIST, m_lblList); + DDX_Control(pDX, IDC_LBLWEBSITE, m_lblWebsite); + DDX_Control(pDX, IDC_LBLEMAIL, m_lblEmail); + DDX_Control(pDX, IDC_WEBSITE, m_edWebsite); + DDX_Control(pDX, IDC_PHONE, m_edPhone); + DDX_Control(pDX, IDC_NOTES, m_edNotes); + DDX_Control(pDX, IDC_LIST, m_cbList); + DDX_Control(pDX, IDC_FAX, m_edFax); + DDX_Control(pDX, IDC_EMAIL, m_edEmail); + DDX_Control(pDX, IDC_DELETE, m_btnDelete); + DDX_Control(pDX, IDC_CONTACT, m_edContact); + DDX_Control(pDX, IDC_COMPNAME, m_edCompName); + DDX_Control(pDX, IDC_ADDRESS, m_edAddress); + DDX_Control(pDX, IDC_ADD, m_btnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNonClientsDlg, CDialog) +//{{AFX_MSG_MAP(CNonClientsDlg) +ON_CBN_CLOSEUP(IDC_LIST, OnCloseupList) +ON_BN_CLICKED(IDC_ADD, OnAdd) +ON_EN_KILLFOCUS(IDC_ADDRESS, OnKillfocusAddress) +ON_EN_KILLFOCUS(IDC_COMPNAME, OnKillfocusCompname) +ON_EN_KILLFOCUS(IDC_CONTACT, OnKillfocusContact) +ON_BN_CLICKED(IDC_DELETE, OnDelete) +ON_EN_KILLFOCUS(IDC_EMAIL, OnKillfocusEmail) +ON_EN_KILLFOCUS(IDC_FAX, OnKillfocusFax) +ON_EN_KILLFOCUS(IDC_NOTES, OnKillfocusNotes) +ON_EN_KILLFOCUS(IDC_PHONE, OnKillfocusPhone) +ON_EN_KILLFOCUS(IDC_WEBSITE, OnKillfocusWebsite) +ON_BN_CLICKED(IDC_LBLEMAIL, OnLblemail) +ON_BN_CLICKED(IDC_LBLWEBSITE, OnLblwebsite) +ON_BN_CLICKED(IDC_DONE, OnDone) +ON_BN_CLICKED(IDOK, OnOk) +ON_BN_CLICKED(IDC_HISTORY, OnHistory) + ON_EN_KILLFOCUS(IDC_EDACCT, OnKillfocusEdacct) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CNonClientsDlg message handlers + +BOOL CNonClientsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + ASSERT(m_lListType!=0);//wasn't set + + //make a WEBSITE "hyperlink" + m_lblWebsite.SetTextColor(RGB(0,0,255)); + m_lblWebsite.SetFontUnderline(TRUE); + m_lblWebsite.SetLink(TRUE); + m_lblWebsite.SetLinkCursor(m_pApp->hcHand); + m_lblWebsite.SetLinkURL(""); + + //make a EMAIL "hyperlink" + m_lblEmail.SetTextColor(RGB(0,0,255)); + m_lblEmail.SetFontUnderline(TRUE); + m_lblEmail.SetLink(TRUE); + m_lblEmail.SetLinkCursor(m_pApp->hcHand); + m_lblEmail.SetLinkURL(""); + + //make a HISTORY "hyperlink" + m_lblHistory.SetTextColor(RGB(0,0,255)); + m_lblHistory.SetFontUnderline(TRUE); + m_lblHistory.SetLink(TRUE); + m_lblHistory.SetLinkCursor(m_pApp->hcHand); + m_lblHistory.SetLinkURL(""); + + FillList(); + + m_bAddMode=false; + //looks wierd, but may be ok if more fields + //added later so left in for that reason + //ShowWindow(SW_SHOWMAXIMIZED); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CNonClientsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + UpdateModified(false); + return true; +} + + + + +//************************************************ +//UPDATE MODIFIED DATA +//************************************************* +bool CNonClientsDlg::UpdateModified(bool IsNew) +{ + COleDateTime dtData; + //updates modified by and modified on fields + if(IsNew)//update creator and created as well + { + rs->UpdateField("creator",&m_pApp->m_lusrID); + + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("created",&dtData); + } + + rs->UpdateField("modifier",&m_pApp->m_lusrID); + + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + if(!rs->SaveRecord()) return false; + + + return true; +} + + + + +void CNonClientsDlg::FillList() +{ + + CString strData; + CString strIndex; + CString q; + long lData; + m_cbList.Clear(); + + q.Format("SELECT nonclients.*, nonclienttypes.description AS LISTNAME " + "FROM nonclients LEFT JOIN nonclienttypes ON " + "nonclients.type = nonclienttypes.id " + "WHERE (((nonclients.type)=%u)) " + "ORDER BY nonclients.company_person;",m_lListType); + + + rs->Query(q); + if(!rs->IsEmpty()) + { + //fill combo box with available zones + rs->MoveFirst(); + rs->FetchField("LISTNAME",&strData); + SetWindowText(strData); + + rs->FetchField("company_person",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbList.AddRow(strData,strIndex); + + while(rs->MoveForward()) + { + rs->FetchField("company_person",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbList.AddRow(strData,strIndex); + } + + + + //pretend user has selected so that other fields get filled in + if(m_strSelectedContact.IsEmpty()) //first time in + { + m_cbList.SetCurSel(0); + } + else//something valid was selected before so stick with it + m_cbList.Select(m_strSelectedContact); + + OnCloseupList(); + } + else + DisableAll(true); + + +} + +//************************************************* +void CNonClientsDlg::SetType(long *pType) +{ + m_lListType=*pType; +} + + +//***************************** +void CNonClientsDlg::OnCloseupList() +{ + //Fill the fields as this is a simple dialog. + //user has made a selection, update the visible list + CString q; + CString strData; + strData=m_cbList.GetCurrentRowID(); + if(strData.IsEmpty()) + return; + q.Format("SELECT nonclients.* FROM nonclients " + "WHERE (((nonclients.id)=%s));",m_cbList.GetCurrentRowID()); + rs->Query(q); + if(!rs->IsEmpty()) + { + //COMPANY_PERSON + rs->FetchField("company_person",&strData); + m_edCompName.SetWindowText(strData); + + //CONTACT + rs->FetchField("contact",&strData); + m_edContact.SetWindowText(strData); + + //ADDRESS + rs->FetchField("address",&strData); + m_edAddress.SetWindowText(strData); + + //PHONE + rs->FetchField("phone",&strData); + m_edPhone.SetWindowText(strData); + + //FAX + rs->FetchField("fax",&strData); + m_edFax.SetWindowText(strData); + + //EMAIL + rs->FetchField("email",&strData); + m_edEmail.SetWindowText(strData); + + //WEBSITE + rs->FetchField("website",&strData); + m_edWebsite.SetWindowText(strData); + + //ACCOUNT + rs->FetchField("account",&strData); + m_edAccount.SetWindowText(strData); + + //NOTES + rs->FetchField("notes",&strData); + m_edNotes.SetWindowText(strData); + + + } + //save current selection so that updates and changes + //will still show what was last selected + m_strSelectedContact=m_cbList.GetCurrentRowID(); +} + +//************************************ +//ADD NEW / SAVE +//************************************ +void CNonClientsDlg::OnAdd() +{ + CString strData; + + if(!m_bAddMode) + {//go to add mode + DisableAll(false); + m_bAddMode=true; + m_btnDone.ShowWindow(FALSE); + m_btnAdd.SetWindowText("Save"); + m_btnDelete.SetWindowText("Cancel"); + m_lblList.ShowWindow(FALSE); + m_cbList.ShowWindow(FALSE); + m_edAddress.SetWindowText(""); + m_edCompName.SetWindowText(""); + m_edContact.SetWindowText(""); + m_edEmail.SetWindowText(""); + m_edFax.SetWindowText(""); + m_edNotes.SetWindowText(""); + m_edPhone.SetWindowText(""); + m_edWebsite.SetWindowText(""); + m_edAccount.SetWindowText(""); + + + } + else//save and exit add mode + { + m_edCompName.GetWindowText(strData); + if(strData.IsEmpty()) + { + AfxMessageBox("Company or Name is required."); + m_edCompName.Undo(); + m_edCompName.SetFocus(); + return; + } + if(IsDupeCompany(strData)) + { + CString st; + st.Format( + "The company name \"%s\" has already been entered\r\n" + "as a non-client contact and can not be used again.",strData); + AfxMessageBox(st); + m_edCompName.Undo(); + m_edCompName.SetFocus(); + return; + + } + + //add the record + if(rs->AddNewRecord()) + { + rs->UpdateField("type",&m_lListType); + rs->UpdateField("company_person",&strData); + + m_edAddress.GetWindowText(strData); + rs->UpdateField("address",&strData); + + m_edContact.GetWindowText(strData); + rs->UpdateField("contact",&strData); + + m_edEmail.GetWindowText(strData); + rs->UpdateField("email",&strData); + + m_edFax.GetWindowText(strData); + rs->UpdateField("fax",&strData); + + m_edNotes.GetWindowText(strData); + rs->UpdateField("notes",&strData); + + m_edPhone.GetWindowText(strData); + rs->UpdateField("phone",&strData); + + m_edWebsite.GetWindowText(strData); + rs->UpdateField("website",&strData); + + m_edAccount.GetWindowText(strData); + rs->UpdateField("account",&strData); + + + //this will save the record as well + if(!UpdateModified(true)) + return; + + m_bAddMode=false; + m_btnDone.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + m_lblList.ShowWindow(TRUE); + m_cbList.ShowWindow(TRUE); + FillList(); + + } + + + + } + +} + +//************************************ +//DELETE / CANCEL +//************************************ +void CNonClientsDlg::OnDelete() +{ + CString q,strID; + + + if(m_bAddMode)//user pressed cancel button + { + m_btnDone.ShowWindow(TRUE); + m_bAddMode=false; + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + m_lblList.ShowWindow(TRUE); + m_cbList.ShowWindow(TRUE); + FillList(); + return; + } + + + + //USER IS REQUESTING TO DELETE RECORD + //check subrepairs to see if records exist + strID=m_cbList.GetCurrentRowID(); + q.Format("SELECT subrepair.where " + "FROM subrepair WHERE (((subrepair.where)=%s)) " + "OR (((subrepair.sentvia)=%s));",strID,strID); + rs->Query(q); + if(!rs->IsEmpty()) + { + AfxMessageBox("DATA INTEGRITY PROTECTION:\r\n" + "You can't delete this record at this time.\r\n" + "It is attached to one or more sub-contracted repair records."); + return; + + } + else + { + if(AfxMessageBox("Permanently delete?\r\nAre you sure?",MB_YESNO)==IDYES) + { + q.Format("DELETE nonclients.*, nonclients.id " + "FROM nonclients WHERE (((nonclients.id)=%s));" + ,m_cbList.GetCurrentRowID()); + rs->Ex(q); + //a deleted contact can't be selected + m_strSelectedContact=""; + FillList(); + } + + } + + +} + +//************************************** +//SAVE FIELDS +//************************************** +void CNonClientsDlg::OnKillfocusAddress() +{SaveField(&m_edAddress,"address",true);} + +void CNonClientsDlg::OnKillfocusCompname() +{ + if(m_edCompName.GetModify()==FALSE) return; + + CString strData; + m_edCompName.GetWindowText(strData); + if(strData.IsEmpty()) + { + AfxMessageBox("Company or Name is required, can't leave blank."); + m_edCompName.Undo(); + m_edCompName.SetModify(FALSE); + m_edCompName.SetFocus(); + return; + } + + if(IsDupeCompany(strData)) + { + CString st; + st.Format( + "The company name \"%s\" has already been entered\r\n" + "as a non-client contact and can not be used again.",strData); + AfxMessageBox(st); + +m_edCompName.Undo(); +m_edCompName.SetModify(FALSE); + m_edCompName.SetFocus(); + return; + } + + SaveField(&m_edCompName,"company_person",false); + if(!m_bAddMode) + FillList(); +} + +void CNonClientsDlg::OnKillfocusContact() +{SaveField(&m_edContact,"contact",true);} + +void CNonClientsDlg::OnKillfocusEmail() +{SaveField(&m_edEmail,"email",true);} + +void CNonClientsDlg::OnKillfocusFax() +{SaveField(&m_edFax,"fax",true);} + +void CNonClientsDlg::OnKillfocusNotes() +{SaveField(&m_edNotes,"notes",true);} + +void CNonClientsDlg::OnKillfocusPhone() +{SaveField(&m_edPhone,"phone",true);} + +void CNonClientsDlg::OnKillfocusWebsite() +{SaveField(&m_edWebsite,"website",true);} + +void CNonClientsDlg::OnKillfocusEdacct() +{SaveField(&m_edAccount,"account",true);} + + + +//***************************************** +void CNonClientsDlg::OnLblemail() +{ + CString strURL; + m_edEmail.GetWindowText(strURL); + if(!strURL.IsEmpty())//do this only if there was an url + { + strURL="mailto:" + strURL; + ShellExecute(NULL,"open",strURL,NULL,NULL,SW_SHOWNORMAL); + + } + + +} + + +//******************************************* +void CNonClientsDlg::OnLblwebsite() +{ + CString strURL; + m_edWebsite.GetWindowText(strURL); + if(!strURL.IsEmpty())//do this only if there was an url + { + + ShellExecute(NULL,"open",strURL,NULL,NULL,SW_SHOWNORMAL); + + } + +} + +void CNonClientsDlg::OnDone() +{ + + if(m_pstrReturnValue!=NULL) + *m_pstrReturnValue=m_strSelectedContact; + CDialog::OnOK(); +} + +void CNonClientsDlg::OnOk() +{ + //do nothing +} + +void CNonClientsDlg::OnHistory() +{ + + + + COleDateTime dtCreated,dtModified; + CString modifier,creator; + long m,c; + //GET RECORD STATUS FIELDS + rs->FetchField("created",&dtCreated); + rs->FetchField("modified",&dtModified); + + rs->FetchField("creator",&c); + + rs->FetchField("modifier",&m); + creator.Format("%u",c); + modifier.Format("%u",m); + + + CStatusDlg d; + d.SetValues(&creator,&modifier,&dtCreated,&dtModified); + d.DoModal(); + +} + +void CNonClientsDlg::SetReturnString(CString* strReturn) +{ + m_pstrReturnValue=strReturn; +} + +void CNonClientsDlg::DisableAll(bool disable) +{ + BOOL e=disable ? FALSE : TRUE; + m_btnDelete.EnableWindow(e); + m_cbList.EnableWindow(e); + m_edAddress.EnableWindow(e); + m_edCompName.EnableWindow(e); + m_edContact.EnableWindow(e); + m_edEmail.EnableWindow(e); + m_edFax.EnableWindow(e); + m_edNotes.EnableWindow(e); + m_edPhone.EnableWindow(e); + m_edWebsite.EnableWindow(e); + m_edAccount.EnableWindow(e); + + +} + +void CNonClientsDlg::Security() +{ + + //m_bReadOnly=false; + int x=m_pApp->Allowed(RNONCLIENTS,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + // m_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_edAddress.SetReadOnly(TRUE); + m_edCompName.SetReadOnly(TRUE); + m_edContact.SetReadOnly(TRUE); + m_edEmail.SetReadOnly(TRUE); + m_edFax.SetReadOnly(TRUE); + m_edNotes.SetReadOnly(TRUE); + m_edPhone.SetReadOnly(TRUE); + m_edWebsite.SetReadOnly(TRUE); + m_edAccount.SetReadOnly(TRUE); + + + } +} + + + +// v 1.9.4.4 addition - returns true if the company name entered already exists in the table +bool CNonClientsDlg::IsDupeCompany(CString strNewCompanyName) +{ + CString q; + bool bIsDupe=false; + q.Format("SELECT nonclients.company_person FROM nonclients WHERE " +"(((nonclients.company_person)=\"%s\"));",strNewCompanyName); + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty()) + bIsDupe=true; + + rs2->Close(); + + return bIsDupe; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.h new file mode 100644 index 0000000..2d5be74 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NonClientsDlg.h @@ -0,0 +1,103 @@ +#if !defined(AFX_NONCLIENTSDLG_H__12A88141_2588_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_NONCLIENTSDLG_H__12A88141_2588_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NonClientsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CNonClientsDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" + +class CNonClientsDlg : public CDialog +{ +// Construction +public: + void Security(); + void DisableAll(bool disable); + void SetReturnString(CString* strReturn); + CString m_strSelectedContact; + void SetType(long* pType); + long m_lListType; + void FillList(); + CNonClientsDlg(CWnd* pParent = NULL); // standard constructor + ~CNonClientsDlg(); + CSpApp* m_pApp; + GZRset* rs; + //v1.9.4.4 - added to confirm no dupes in company name before attempting to update + GZRset* rs2; + + CString * m_pstrReturnValue; + bool m_bAddMode; + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool UpdateModified(bool IsNew); + //------------------------------- +// Dialog Data + //{{AFX_DATA(CNonClientsDlg) + enum { IDD = IDD_NONCLIENTS }; + CEdit m_edAccount; + CButton m_btnDone; + CLabel m_lblHistory; + CStatic m_lblList; + CLabel m_lblWebsite; + CLabel m_lblEmail; + CEdit m_edWebsite; + CEdit m_edPhone; + CEdit m_edNotes; + CgzCombo m_cbList; + CEdit m_edFax; + CEdit m_edEmail; + CButton m_btnDelete; + CEdit m_edContact; + CEdit m_edCompName; + CEdit m_edAddress; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CNonClientsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CNonClientsDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnCloseupList(); + afx_msg void OnAdd(); + afx_msg void OnKillfocusAddress(); + afx_msg void OnKillfocusCompname(); + afx_msg void OnKillfocusContact(); + afx_msg void OnDelete(); + afx_msg void OnKillfocusEmail(); + afx_msg void OnKillfocusFax(); + afx_msg void OnKillfocusNotes(); + afx_msg void OnKillfocusPhone(); + afx_msg void OnKillfocusWebsite(); + afx_msg void OnLblemail(); + afx_msg void OnLblwebsite(); + afx_msg void OnDone(); + afx_msg void OnOk(); + afx_msg void OnHistory(); + afx_msg void OnKillfocusEdacct(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + // v 1.9.4.4 addition - returns true if the company name entered already exists in the table + bool IsDupeCompany(CString strNewCompanyName); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_NONCLIENTSDLG_H__12A88141_2588_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.cpp new file mode 100644 index 0000000..b0f40e5 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.cpp @@ -0,0 +1,72 @@ +// NullForm.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "NullForm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CNullForm + +IMPLEMENT_DYNCREATE(CNullForm, CFormView) + +CNullForm::CNullForm() + : CFormView(CNullForm::IDD) +{ + //{{AFX_DATA_INIT(CNullForm) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +CNullForm::~CNullForm() +{ +} + +void CNullForm::DoDataExchange(CDataExchange* pDX) +{ + CFormView::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNullForm) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNullForm, CFormView) + //{{AFX_MSG_MAP(CNullForm) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CNullForm diagnostics + +#ifdef _DEBUG +void CNullForm::AssertValid() const +{ + CFormView::AssertValid(); +} + +void CNullForm::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CNullForm message handlers + +void CNullForm::Activate() +{ + +} + +void CNullForm::DeActivate() +{ + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.h new file mode 100644 index 0000000..1869a49 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/NullForm.h @@ -0,0 +1,65 @@ +#if !defined(AFX_NULLFORM_H__75C81BC1_5E20_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_NULLFORM_H__75C81BC1_5E20_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NullForm.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CNullForm form view + +#ifndef __AFXEXT_H__ +#include +#endif + +class CNullForm : public CFormView +{ +public: + CNullForm(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(CNullForm) + +// Form Data +public: + //{{AFX_DATA(CNullForm) + enum { IDD = IDD_NULLFORM_FORM }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + +// Attributes +public: + +// Operations +public: + void DeActivate(); + void Activate(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CNullForm) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~CNullForm(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(CNullForm) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_NULLFORM_H__75C81BC1_5E20_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.cpp new file mode 100644 index 0000000..4cc4f7d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.cpp @@ -0,0 +1,2275 @@ +// 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=" " + 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 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;yEx(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;xShowStuff(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); + */ + + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.h new file mode 100644 index 0000000..fcc1aa9 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PM.h @@ -0,0 +1,184 @@ +#if !defined(AFX_PM_H__BA63E282_9608_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PM_H__BA63E282_9608_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PM.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPM dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "gzlistbox.h" +#include "label.h" +#include "afxwin.h" +#include "afxdtctl.h" + +class CPM : public CDialog +{ +// Construction +public: + CString m_strPrompt; + bool m_bQuick; + CString m_strSelCategory; + CString m_strSelProject; + void FillTypeList(); + void FillProjectList(); + bool m_bModel; + void UpdateMeterCount(bool bWriting); + void Aging(); + COleDateTime m_dtUnitPurchasedDate; + int m_nSeries; + long m_lCurrentRecordID; + void Schedule(); + void ScheduleClear(); + bool m_bEditing; + bool m_bReschedule; + void FillRequiredPartsList(); + CString m_strSelectedTech; + void FillTechList(); + void ClearFields(); + void FillFields(); + CString m_strSelectedPM; + void FillPMList(); + void FillPartsList(); + bool m_bNoRecord; + CSpApp* m_pApp; + GZRset* rs; + GZRset* cbrs; + bool m_bAddMode; + bool m_bAutoRepeat; + bool m_bAutoWO; + int m_nCurrentMode; + void SwitchMode(); + bool m_bReadOnly; + void EnableFields(bool bEnable); + CString m_strCriteria; + bool m_bClientMode; + void PreInitialize(bool bClientMode, bool bModel, CString strCriteria, CString strPrompt, bool bResave=false); + void GroupClick(int nClicked); + ~CPM(); + CPM(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CPM) + enum { IDD = IDD_PM }; + CStatic m_lblSeries; + CEdit m_edSeries; + CStatic m_lblTime5; + CStatic m_lblTime4; + CEdit m_edTimeRepeatEveryWeeks; + CEdit m_edTimeRepeatEveryDays; + CgzCombo m_cbCategories; + CLabel m_lblType; + CLabel m_lblProject; + CButton m_ckQuick; + CButton m_ckOnsite; + CgzCombo m_cbProjects; + CButton m_btnEdit; + CButton m_ckHold; + CStatic m_lblQuant; + CStatic m_lblPartsList; + CLabel m_lblPart; + CgzListBox m_lbParts; + CEdit m_edPartQuantity; + CButton m_btnRemovePart; + CButton m_btnAddPart; + CgzCombo m_cbParts; + CButton m_rdTime; + CButton m_rdMetric; + CButton m_rdAge; + CStatic m_lblTime3; + CStatic m_lblTime2; + CStatic m_lblTime1; + CStatic m_lblTech; + CStatic m_lblPMList; + CStatic m_lblMeter4; + CStatic m_lblMeter3; + CStatic m_lblMeter2; + CStatic m_lblMeter1; + CStatic m_lblDayOfWeek; + CStatic m_lblConvertMeter; + CStatic m_lblConvertDays; + CStatic m_lblAge5; + CStatic m_lblAge4; + CStatic m_lblAge3; + CStatic m_lblAge2; + CStatic m_lblAge1; + CEdit m_edTimeRepeatEveryMonths; + CEdit m_edNotes; + CEdit m_edMeterRepeat; + CEdit m_edMeterLastReading; + CEdit m_edMeterFirstService; + CEdit m_edDescription; + CEdit m_edConvertToWoAfter; + CEdit m_edAgeYears; + CEdit m_edAgeRepeat; + CEdit m_edAgeMonths; + CDateTimeCtrl m_dtTimeNextServiceDate; + CDateTimeCtrl m_dtAgeFirstServiceDate; + CButton m_ckAutoWO; + CButton m_ckAutoRepeat; + CgzCombo m_cbTech; + CgzCombo m_cbPMList; + CComboBox m_cbDayOfWeek; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnClone; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPM) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPM) + virtual BOOL OnInitDialog(); + afx_msg void OnRdage(); + afx_msg void OnRdmetric(); + afx_msg void OnRdtime(); + afx_msg void OnBtndone(); + afx_msg void OnCkautorepeat(); + afx_msg void OnCkautowo(); + afx_msg void OnBtnadd(); + afx_msg void OnCloseupCbpmlist(); + afx_msg void OnBtnaddpart(); + afx_msg void OnBtnremovepart(); + afx_msg void OnBtnedit(); + afx_msg void OnBtndelete(); + virtual void OnOK(); + afx_msg void OnKillfocusEdageyrs(); + afx_msg void OnKillfocusEdagemonths(); + afx_msg void OnKillfocusEdmeterlastreading(); + afx_msg void OnCkquick(); + afx_msg void OnLblpart(); + afx_msg void OnLblproject(); + afx_msg void OnLbltype(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + void Security(); + bool m_bReadOnlySecurity; +public: + CStatic m_lblStartTime; + CStatic m_lblEndTime; + CDateTimeCtrl m_dtStartTime; + CDateTimeCtrl m_dtEndtime; + // Used to force auto resaves when called from the client screen when a unit is selected as part of a model's PM + bool m_bResave; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PM_H__BA63E282_9608_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.cpp new file mode 100644 index 0000000..f7b7ad8 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.cpp @@ -0,0 +1,1239 @@ +// PMCheckDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "PMCheckDlg.h" +#include "PM.h" +#include "PMViewPrompt.h" +#include "gzCurrencyFormatter.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +//memory leak debugging help +#define _CRTDBG_MAP_ALLOC +#include +#include +///////////////////////////////////////////////////////////////////////////// +// CPMCheckDlg dialog + + +CPMCheckDlg::CPMCheckDlg(CWnd* pParent /*=NULL*/) +: CDialog(CPMCheckDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPMCheckDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("PMCHECK rs error:"); + rs->SetConnect(m_pApp->strConnectString); + + rs2=new GZRset("PMCHECK rs2 error:"); + rs2->SetConnect(m_pApp->strConnectString); + + rs3=new GZRset("PMCHECK rs3 error:"); + rs3->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer +rs=m_pApp->rsPool->GetRS("CPMCheckDlg (RS)"); +rs2=m_pApp->rsPool->GetRS("CPMCheckDlg (RS2)"); +rs3=m_pApp->rsPool->GetRS("CPMCheckDlg (RS3)"); +} + + +void CPMCheckDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPMCheckDlg) + // NOTE: the ClassWizard will add DDX and DDV calls here + DDX_Control(pDX, IDC_REPORT, m_rc); + //}}AFX_DATA_MAP + +} + + +BEGIN_MESSAGE_MAP(CPMCheckDlg, CDialog) +//{{AFX_MSG_MAP(CPMCheckDlg) +ON_COMMAND(ID_PMVIEW_DONE, OnPmviewDone) +ON_COMMAND(ID_PMVIEW_SHOWDATEITEMS, OnPmviewShowdateitems) +ON_COMMAND(ID_PMVIEW_SHOWMETERED, OnPmviewShowmetered) +ON_COMMAND(ID_PMVIEW_SELECTEDITEM_CONVERTTOWORKORDER, OnPmviewSelecteditemConverttoworkorder) +ON_COMMAND(ID_PMVIEW_SELECTEDITEM_DELETE, OnPmviewSelecteditemDelete) +ON_COMMAND(ID_PMVIEW_SELECTEDITEM_EDIT, OnPmviewSelecteditemEdit) +ON_COMMAND(ID_PMVIEW_SELECTEDITEM_HOLDRELEASE, OnPmviewSelecteditemHoldrelease) +ON_NOTIFY(RVN_ITEMDBCLICK, IDC_REPORT, OnRvnItemDbClick) +ON_NOTIFY(RVN_COLUMNCLICK, IDC_REPORT, OnColumnClick) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPMCheckDlg message handlers + +CPMCheckDlg::~CPMCheckDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs2->m_nID); + m_pApp->rsPool->ReleaseRS(&rs3->m_nID); + +} + + +void CPMCheckDlg::OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + CString q,link; + long lData; + bool isclient,ismodel; + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + + q.Format("SELECT pmhead.id, pmhead.ismodel, pmhead.isclient, pmhead.link " + "FROM pmitems INNER JOIN pmhead ON pmitems.pmschedlink = pmhead.id " + "WHERE (((pmitems.id)=%s));",m_rc.GetItemText(lpnmrv->iItem,7)); + rs2->Query(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("There is a problem trying to retrieve the\r\nmaster record for this item."); + return; + + } + + rs2->FetchField("ismodel",&ismodel); + rs2->FetchField("isclient",&isclient); + rs2->FetchField("link",&lData); + link.Format("%u",lData); + + CPM d; + d.PreInitialize(isclient,ismodel,link,"Edit PM scheduled item"); + d.DoModal(); + FillView(); + + + + } + + *pResult = FALSE; +} + + +//=================================== +BOOL CPMCheckDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + m_resize.Create( this ); + Security(); + ShowWindow(SW_HIDE); + CWaitCursor wait; + //defaults + m_bShowDateFormat=true; + //Set the initial sort order for the columns + for(int xx=0;xx<9;xx++) + bColumnSortAsc[xx]=FALSE; + m_strOrderBy.Empty(); + + CString profile,q; + + + q.Format("SELECT users.pmprofile " + "FROM users WHERE (((users.id)=%u));",m_pApp->m_lusrID); + rs->Query(q); + rs->FetchField("pmprofile",&profile); + + + + m_ilReport.Create(IDB_BM2, 16, 1, RGB(255,0,255)); + m_rc.SetImageList(&m_ilReport); + + + + m_rc.InsertColor(0, 0x00C0D8C0); + m_rc.InsertColor(1, ::GetSysColor(COLOR_GRAYTEXT)); + m_rc.InsertColor(2, 0x00D0C0C0); + m_rc.InsertColor(3, 0x00804000); + + + RVCOLUMN rvc; + + rvc.nFormat = RVCF_TEXT|RVCF_LEFT;//RVCF_TEXT|RVCF_EX_AUTOWIDTH|RVCF_SUBITEM_IMAGE; + rvc.iImage = 1; + rvc.lpszText = _T("Client"); + rvc.iWidth = 60; + m_rc.DefineColumn(0, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Date"; + rvc.iWidth = 60; + m_rc.DefineColumn(1, &rvc); + + rvc.lpszText = "Service meter"; + rvc.iWidth = 60; + m_rc.DefineColumn(2, &rvc); + + rvc.lpszText = "Last reading"; + rvc.iWidth = 60; + m_rc.DefineColumn(3, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Hold"; + rvc.iWidth = 60; + m_rc.DefineColumn(4, &rvc); + + rvc.lpszText = "Tech."; + rvc.iWidth = 60; + m_rc.DefineColumn(5, &rvc); + + rvc.lpszText = "Description"; + rvc.iWidth = 60; + m_rc.DefineColumn(6, &rvc); + + rvc.nFormat = RVCF_TEXT | RVCF_EX_FIXEDWIDTH; + rvc.lpszText = "pmheadid"; + rvc.iWidth = 0; + m_rc.DefineColumn(7, &rvc); + + //setup according to users preferences + if(!profile.IsEmpty()) + m_rc.GetProfile(&profile); + else + { + + //not needed when setting by pref + //but if there are no preferences then you would need it + + m_rc.ActivateColumn(0, 0); + m_rc.ActivateColumn(1, 1); + m_rc.ActivateColumn(2, 2); + m_rc.ActivateColumn(3, 3); + m_rc.ActivateColumn(4, 4); + m_rc.ActivateColumn(5, 5); + m_rc.ActivateColumn(6, 6); + m_rc.ActivateColumn(7, 7); + + + } + + + + + + m_rc.ModifyStyle(0, RVS_SINGLESELECT); + //m_rc.ModifyStyle(0, RVS_SHOWCOLORALTERNATE); + + + //turn off the grids + m_rc.ModifyStyle(RVS_SHOWVGRID, 0); + m_rc.ModifyStyle(RVS_SHOWHGRID, 0); + + + + //retrieve the loaner items and display them + FillView(); + + m_resize.Add(IDC_REPORT,0,0,100,100); +//Use the current width and height as the minimum size + m_resize.SetMinimumTrackingSize(); + + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + + +void CPMCheckDlg::FillView() +{ + int x=0; + CString q,strTemp,strClient,strTech,strDetails; + COleDateTime dtDate; + long lMeter,lLastMeter,lID,lLink; + + bool bHold; + bool bIsClient; + + if(m_bShowDateFormat) + strTemp=" = 0"; + else + strTemp=" <> 0"; + + + /*q.Format("SELECT IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS clientname, pmitems.schedate, pmitems.schedmeter, pmitems.hold, pmhead.description, pmitems.id, IIf([pmitems].[schedtech]=0,\"Any\",[users].[last] & \", \" & [users].[first]) AS techname, pmitems.link " + "FROM ((pmitems LEFT JOIN clients ON pmitems.clientlink = clients.id) LEFT JOIN pmhead ON pmitems.pmschedlink = pmhead.id) LEFT JOIN users ON pmitems.schedtech = users.id " + "WHERE (((pmitems.schedmeter)%s)) %s;",strTemp, m_strOrderBy);*/ + + q.Format("SELECT pmitems.isclient, IIf(IsNull([clients]![company]),[clients]![first] " +"& \" \" & [clients]![last],[clients]![company]) " +"AS clientname, pmitems.schedate, " +"pmitems.schedmeter, pmitems.hold, pmhead.description, " +"pmitems.id, IIf([pmitems].[schedtech]=0,\"Any\",[users].[last] " +"& \", \" & [users].[first]) AS techname, " +"pmitems.link FROM ((pmitems LEFT JOIN clients " +"ON pmitems.clientlink = clients.id) LEFT JOIN pmhead " +"ON pmitems.pmschedlink = pmhead.id) LEFT JOIN " +"users ON pmitems.schedtech = users.id WHERE (((pmitems.schedmeter)%s)) %s; ",strTemp, m_strOrderBy); + + //vvvvvvvvvvvvvvvvvvv + +//#ifdef _DEBUG +// m_pApp->ShowStuff(q); +//#endif + + //^^^^^^^^^^^^^^^^^^^ + + rs->Query(q); + m_rc.DeleteAllItems(); + + + if(rs->IsEmpty()) return; + + do + { + //added 02/21/2003 + rs->FetchField("isclient",&bIsClient); + + rs->FetchField("clientname",&strClient); + //avoid the underline in the report control + //for a single & + strClient.Replace("&","&&"); + + rs->FetchField("schedate",&dtDate); + + rs->FetchField("schedmeter",&lMeter); + + rs->FetchField("hold",&bHold); + + rs->FetchField("description",&strDetails); + + rs->FetchField("techname",&strTech); + + rs->FetchField("id",&lID); + + rs->FetchField("link",&lLink); + + + + //Set the look of the row and insert it + + //CLIENT + RVITEM rvi; + rvi.iItem = x; + rvi.iSubItem = 0; + rvi.nMask = RVIM_TEXT; + //rvi.nState = 0; + //rvi.nPreview = 0;//no preview necessary + rvi.lpszText = strClient.GetBuffer(strClient.GetLength()); + rvi.lParam = x; + m_rc.InsertItem(&rvi); + + + //DATE + if(!m_bShowDateFormat) + strTemp="n/a"; + else + strTemp=dtDate.Format(); + + rvi.iSubItem = 1; + rvi.nMask = RVIM_TEXT; + rvi.lpszText = strTemp.GetBuffer(strTemp.GetLength()); + m_rc.SetItem(&rvi); + + //METER + if(m_bShowDateFormat) + strTemp="n/a"; + else + strTemp.Format("%u",lMeter); + + rvi.iSubItem = 2; + rvi.lpszText = strTemp.GetBuffer(strTemp.GetLength()); + m_rc.SetItem(&rvi); + + //LAST METER READING + //LOOK UP LAST METER READING HERE + //************************************************************** + if(m_bShowDateFormat) + strTemp="n/a"; + else + { + q.Format("SELECT units.lastmeter FROM units WHERE (((units.id)=%u));",lLink); + rs2->Query(q); + if(rs2->IsEmpty()) + { + strTemp="n/a"; + } + else + { + rs2->FetchField("lastmeter",&lLastMeter); + strTemp.Format("%u",lLastMeter); + + + } + } + + rvi.iSubItem = 3; + rvi.lpszText = strTemp.GetBuffer(strTemp.GetLength()); + m_rc.SetItem(&rvi); + + + + //HOLD + if(bHold) + strTemp="HELD"; + else + strTemp="Active"; + + rvi.iSubItem = 4; + rvi.lpszText = strTemp.GetBuffer(strTemp.GetLength()); + m_rc.SetItem(&rvi); + + //TECH + rvi.iSubItem = 5; + rvi.lpszText = strTech.GetBuffer(strTech.GetLength()); + m_rc.SetItem(&rvi); + + + //DETAILS + //If it's a unit, get the serial number here and + //append to details + if(!bIsClient) + { + /*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)=%u));",lLink);*/ + + + //FIX v1.9.4.3 + 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 " +"((units 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 (((units.id)=%u));",lLink); +//#ifdef _DEBUG +// m_pApp->ShowStuff(q); +//#endif + if(!rs2->QueryReadOnly(q)) goto BAIL; + if(rs2->IsEmpty()) goto BAIL; + //Ok, we have a record and are ready to retrieve the details + + if(!rs2->FetchField("USN",&strTemp)) goto BAIL; + strDetails+=" Unit - sn:" + strTemp; + if(!rs2->FetchField("MANU",&strTemp)) goto BAIL; + strDetails+=" " + strTemp; + + if(!rs2->FetchField("MODEL",&strTemp)) goto BAIL; + strDetails+=" " + strTemp; + + + + + } +BAIL: + rvi.iSubItem = 6; + rvi.lpszText = strDetails.GetBuffer(strDetails.GetLength()); + m_rc.SetItem(&rvi); + + //ID + strTemp.Format("%u",lID); + rvi.iSubItem = 7; + rvi.lpszText = strTemp.GetBuffer(strTemp.GetLength()); + m_rc.SetItem(&rvi); + + x++; + + }while(rs->MoveForward()); + + + +} + + +void CPMCheckDlg::OnPmviewDone() +{ + + CString profile,q; + //save to user prefs. + m_rc.WriteProfile(&profile); + q.Format("UPDATE users SET users.pmprofile = \"%s\" " + "WHERE (((users.id)=%u));",profile,m_pApp->m_lusrID); + rs->Ex(q); + CDialog::OnOK(); +} + + + +void CPMCheckDlg::OnPmviewShowdateitems() +{ + if(!m_bShowDateFormat) + FlipMeterDate(); +} + +void CPMCheckDlg::OnPmviewShowmetered() +{ + if(m_bShowDateFormat) + FlipMeterDate(); +} + + +//Toggle meter/date mode +void CPMCheckDlg::FlipMeterDate() +{ + + CMenu* mmenu = GetMenu(); + CMenu* submenu = mmenu->GetSubMenu(0); + + UINT state = submenu->GetMenuState(ID_PMVIEW_SHOWMETERED, MF_BYCOMMAND); + ASSERT(state != 0xFFFFFFFF); + + + if (state & MF_CHECKED) + { + submenu->CheckMenuItem(ID_PMVIEW_SHOWMETERED, MF_UNCHECKED | MF_BYCOMMAND); + submenu->CheckMenuItem(ID_PMVIEW_SHOWDATEITEMS, MF_CHECKED | MF_BYCOMMAND); + m_bShowDateFormat=true; + + } + + else + { + submenu->CheckMenuItem(ID_PMVIEW_SHOWMETERED, MF_CHECKED | MF_BYCOMMAND); + submenu->CheckMenuItem(ID_PMVIEW_SHOWDATEITEMS, MF_UNCHECKED | MF_BYCOMMAND); + m_bShowDateFormat=false; + + } + + + + FillView(); +} + + + + +//SET ORDER BY CLAUSE DEPENDING ON CLICK HERE +void CPMCheckDlg::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + CWaitCursor Wait; + int x; + CString strOrder; + CString str; + CFlatHeaderCtrl* header; + header=m_rc.GetHeaderCtrl(); + + //FIND CLICKED COLUMN + + str=header->m_szHotItemText; + + if(str=="Client") + { + x=0; + goto OUTTAHERE; + } + if(str=="Date") + { + x=1; + goto OUTTAHERE; + } + if(str=="Service meter") + { + x=2; + goto OUTTAHERE; + } + if(str=="Last reading") + { + x=3; + goto OUTTAHERE; + } + if(str=="Hold") + { + x=4; + goto OUTTAHERE; + } + if(str=="Tech.") + { + x=5; + goto OUTTAHERE; + } + + if(str=="Description") + { + x=6; + goto OUTTAHERE; + } + + + + +OUTTAHERE:; + bColumnSortAsc[x]=!bColumnSortAsc[x]; + + if(!bColumnSortAsc[x]) + strOrder=" DESC"; + else + strOrder.Empty(); + + switch(x) + {//DESC + case 0://client + m_strOrderBy.Format("ORDER BY IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) %s, pmitems.id, pmitems.schedate, pmitems.schedmeter",strOrder); + break; + case 1://scheddate + m_strOrderBy.Format("ORDER BY pmitems.schedate %s, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]), pmitems.id, pmitems.schedmeter",strOrder); + break; + + case 2:// + m_strOrderBy.Format("ORDER BY pmitems.schedmeter %s, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]), pmitems.id, pmitems.schedate",strOrder); + break; + + case 3://Last meter reading/not sorted now + m_strOrderBy=""; + break; + + case 4://hold + m_strOrderBy.Format("ORDER BY pmitems.hold %s, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]), pmitems.id, pmitems.schedate, pmitems.schedmeter",strOrder); + break; + + + case 5://tech + m_strOrderBy.Format("ORDER BY IIf([pmitems].[schedtech]=0,\"Any\",[users].[last] & \", \" & [users].[first]) %s, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]), pmitems.id, pmitems.schedate, pmitems.schedmeter, pmitems.hold",strOrder); + break; + + + case 6:// + m_strOrderBy.Format("ORDER BY pmhead.description %s, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]), pmitems.id, pmitems.schedate, pmitems.schedmeter",strOrder); + break; + + + + + + + } + + + + + header->SetSortColumn(header->GetHotIndex(),bColumnSortAsc[x]); + + *pResult = TRUE;//TRUE means we handled it here thanks anyway + FillView(); +} + + + + +void CPMCheckDlg::OnPmviewSelecteditemConverttoworkorder() +{ + CString q; + int x; + x=m_rc.GetFirstSelectedItem(); + if(x<0) + { + AfxMessageBox("You must select one or more items from the list first."); + return;//no selection + } + if(AfxMessageBox("Convert this item to a workorder now? \r\nAre you sure?",MB_YESNO)==IDNO) return; + + + //still here? OK + MakeIntoWorkorder(m_rc.GetItemText(x,7)); + + FillView(); +} + + + + + + + +//Delete item(s) +void CPMCheckDlg::OnPmviewSelecteditemDelete() +{ + CPMViewPrompt d; + int nReturn=0,x; + CString q,strTemp,strID; + long lID; + + x=m_rc.GetFirstSelectedItem(); + if(x<0) + { + AfxMessageBox("You must select one or more items from the list first."); + return;//no selection + } + + d.Setup("Delete items? Are you sure?", "Delete items",&nReturn); + d.DoModal(); + if(nReturn==0) return; + + + + + strID=m_rc.GetItemText(x,7); + + if(nReturn==1) //delete series items only + { + //delete this pmitem only. + q.Format("DELETE pmitems.* FROM pmitems WHERE (((pmitems.id)=%s));",strID); + rs2->Ex(q); + + } + else + { + //DELETE HEADER RECORD + + //locate header record ID + q.Format("SELECT pmitems.pmschedlink FROM pmitems WHERE (((pmitems.id)=%s));",strID); + rs2->Query(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("Error locating header record ID\r\nCan't do it."); + return; + + } + rs2->FetchField("pmschedlink",&lID); + //delete header record + q.Format("DELETE pmhead.*, pmhead.id FROM pmhead WHERE (((pmhead.id)=%u));",lID); + rs2->Ex(q); + + //delete all detail items + q.Format("DELETE pmitems.*, pmitems.pmschedlink " + "FROM pmitems WHERE (((pmitems.pmschedlink)=%u));",lID); + + rs2->Ex(q); + } + + + + + + FillView(); + + +} + +void CPMCheckDlg::OnPmviewSelecteditemEdit() +{ + int x; + CString q,link; + long lData; + bool isclient,ismodel; + + x=m_rc.GetFirstSelectedItem(); + if(x<0) + { + AfxMessageBox("You must select one or more items from the list first."); + return;//no selection + } + + //CLoanersEditDlg d; + //CString item=m_rc.GetItemText(lpnmrv->iItem,6); + //d.SetRentalID(&item); + //d.DoModal(); + q.Format("SELECT pmhead.id, pmhead.ismodel, pmhead.isclient, pmhead.link " + "FROM pmitems INNER JOIN pmhead ON pmitems.pmschedlink = pmhead.id " + "WHERE (((pmitems.id)=%s));",m_rc.GetItemText(x,7)); + //strID=m_rc.GetItemText(x,7); + rs2->Query(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("There is a problem trying to retrieve the\r\nmaster record for this item."); + return; + + } + + rs2->FetchField("ismodel",&ismodel); + rs2->FetchField("isclient",&isclient); + rs2->FetchField("link",&lData); + link.Format("%u",lData); + + CPM d; + d.PreInitialize(isclient,ismodel,link,"Edit PM scheduled item"); + d.DoModal(); + FillView(); +} + + + + + + +//HOLD/RELEASE +void CPMCheckDlg::OnPmviewSelecteditemHoldrelease() +{ + int x; + CString q,tf; + bool bHold; + + x=m_rc.GetFirstSelectedItem(); + if(x<0) + { + AfxMessageBox("You must select one or more items from the list first."); + return;//no selection + } + q.Format("SELECT pmitems.hold FROM pmitems " + "WHERE (((pmitems.id)=%s));",m_rc.GetItemText(x,7)); + + + + rs2->Query(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("There is a problem trying to open this record."); + return; + + } + + rs2->FetchField("hold",&bHold); + + if(bHold) + tf="False"; + else + tf="True"; + + q.Format("UPDATE pmitems SET pmitems.hold = %s " + "WHERE (((pmitems.id)=%s));",tf,m_rc.GetItemText(x,7)); + + //m_pApp->ShowStuff(q); + rs2->Ex(q); + + FillView(); + +} + + + + + + + + + + + + + + + + + + +//************************************************************************ +// CONVERT PM ITEM TO WORKORDER +// +//************************************************************************ +//make a PM Item into a workorder +void CPMCheckDlg::MakeIntoWorkorder(CString strPMItem) +{ + CString q,strDescription,strNotes; + long lHeaderID,lTech,lLink,lClient,lModifier,lCategory,lProject,lWOID,lProbID; + long lSchedMeter,lHighestPMID,lRepeat,lDays, lWeeks, lDOW; + bool bIsClient,bQuick,bOnsite,bAutorpt,bAutoWO, bHold; + int nDOW,d,nTemp; + + COleDateTime dtScheduled,dtNow,dtDefault,dtStartTime,dtEndTime,dtSchedStart,dtSchedStop; + dtNow=COleDateTime::GetCurrentTime(); + dtDefault.SetDate(1968,03,12); + //Get all the details from the detail record first + q.Format("SELECT * " + "FROM pmitems WHERE (((pmitems.id)=%s));",strPMItem); + rs2->Query(q); + if(rs2->IsEmpty()) + { + q.Format("Error converting PM Item %s to workorder",strPMItem); + AfxMessageBox(q); + return; + } + rs2->FetchField("pmschedlink",&lHeaderID); + rs2->FetchField("schedtech",&lTech); + rs2->FetchField("link",&lLink); + rs2->FetchField("isclient",&bIsClient); + rs2->FetchField("clientlink",&lClient); + rs2->FetchField("schedmeter",&lSchedMeter); + rs2->FetchField("schedate",&dtScheduled); + rs2->FetchField("autowo",&bAutoWO); + rs2->FetchField("hold",&bHold); + + /*PMDAYS*/ + //Get the rest of the info from the header record + q.Format("SELECT pmhead.description, pmhead.notes, pmhead.modifier, pmhead.autorpt, pmhead.dow, " + "pmhead.repeatevery, pmhead.rptdays, pmhead.rptweeks, pmhead.wotype, pmhead.woquick, " + "pmhead.woproject, pmhead.woonsite, pmhead.starttime, pmhead.endtime " + "FROM pmhead WHERE (((pmhead.id)=%u));",lHeaderID); + rs2->Query(q); + if(rs2->IsEmpty()) + { + q.Format("Error converting PM head item %u to workorder",lHeaderID); + AfxMessageBox(q); + return; + } + + rs2->FetchField("description",&strDescription); + rs2->FetchField("notes",&strNotes); + rs2->FetchField("modifier",&lModifier); + rs2->FetchField("wotype",&lCategory); + rs2->FetchField("woquick",&bQuick); + rs2->FetchField("woproject",&lProject); + rs2->FetchField("woonsite",&bOnsite); + rs2->FetchField("autorpt",&bAutorpt); + rs2->FetchField("dow",&lDOW); + rs2->FetchField("repeatevery",&lRepeat); + rs2->FetchField("rptdays",&lDays); + rs2->FetchField("rptweeks",&lWeeks); + rs2->FetchField("starttime",&dtStartTime); + rs2->FetchField("endtime",&dtEndTime); + + + //Move the date into the time fields + dtSchedStart.SetDateTime(dtScheduled.GetYear(),dtScheduled.GetMonth(),dtScheduled.GetDay(), + dtStartTime.GetHour(),dtStartTime.GetMinute(),dtStartTime.GetSecond()); + + // dtSchedStop + dtSchedStop.SetDateTime(dtScheduled.GetYear(),dtScheduled.GetMonth(),dtScheduled.GetDay(), + dtEndTime.GetHour(),dtEndTime.GetMinute(),dtEndTime.GetSecond()); + + + /*PMDAYS*/ + + //FIXUP DATE + if(dtScheduled.GetYear()==1968) + dtScheduled=COleDateTime::GetCurrentTime(); + + //PROCESS INTO A WORKORDER + q.Format("INSERT INTO wo ( " + "project, client, type, closed, onsite, " + "anytime, assigntech, quick, creator, modifier, created, modified, " + "starttime, stoptime, notes, pmid ) " + "SELECT %u, %u, %u, #%s#, %s, %s, %u, %s, %u, %u, " + "#%s#, #%s#, #%s#, #%s#, \"%s\",%u;", + lProject, lClient, lCategory, bQuick ? dtScheduled.Format(_T("%m/%d/%Y %H:%M:%S")) : "03/12/1968", + bOnsite ? "True" : "False", "False", + lTech, bQuick ? "True" : "False", lModifier, lModifier, + dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), + /*starttime*/dtSchedStart.Format(_T("%m/%d/%Y %H:%M:%S")), + /*stoptime*/dtSchedStop.Format(_T("%m/%d/%Y %H:%M:%S")), + strDescription,lHeaderID); + + //PROCESS INTO A WORKORDER + //q.Format("INSERT INTO wo ( " + // "project, client, type, closed, onsite, " + // "anytime, assigntech, quick, creator, modifier, created, modified, " + // "starttime, stoptime, notes ) " + // "SELECT %u, %u, %u, #%s#, %s, False, %u, %s, %u, %u, " + // "#%s#, #%s#, #%s#, #%s#, %s;", + // lProject, lClient, lCategory, bQuick ? dtScheduled.Format(_T("%m/%d/%Y %H:%M:%S")) : "03/12/1968", + // bOnsite ? "True" : "False", lTech, bQuick ? "True" : "False", + // lModifier, lModifier, dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), + // dtNow.Format(_T("%m/%d/%Y 12:00:00")), + // /*starttime*/dtSchedStart.Format(_T("%m/%d/%Y %H:%M:%S")), + // /*stoptime*/dtSchedStop.Format(_T("%m/%d/%Y %H:%M:%S")), + // strDescription); + + ///////m_pApp->ShowStuff(q); + + rs2->Ex(q); + rs2->Close(); + + /* + //Fetch workorder ID just created + q.Format("SELECT wo.id FROM wo " + "WHERE (((wo.created)=#%s#) AND ((wo.creator)=%u) AND ((wo.client)=%u));", + dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),lModifier,lClient); + */ + //NOTE: MODIFIED 11/03/00 added TOP 1 and order by + q.Format("SELECT TOP 1 wo.id FROM wo " + "WHERE (((wo.created)=#%s#) AND ((wo.creator)=%u) AND ((wo.client)=%u)) ORDER BY wo.id DESC;", + dtNow.Format(_T("%m/%d/%Y %H:%M:%S")),lModifier,lClient); + + + + rs2->Query(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("Error: Can't locate the workorder record just created.\r\n Contact tech support with the details."); + return; + } + + rs2->FetchField("id",&lWOID); + + //Create a companion problem record + if(bQuick) + q.Format("INSERT INTO probs ( wolink, creator, created, pmscheduleid ) " + "SELECT %u, %u, #%s#, %u;", lWOID, lModifier, dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), lHeaderID); + else + q.Format("INSERT INTO probs ( " + "wolink, creator, created, brief, notes, pmscheduleid, unit ) " + "SELECT %u, %u, #%s#, \"%s\", \"%s\", %u, %u;", + lWOID, lModifier, dtNow.Format(_T("%m/%d/%Y %H:%M:%S")), strDescription, + strNotes, lHeaderID, bIsClient ? 0 : lLink) ;//if client 0 else link=unit + + rs2->Ex(q); + rs2->Close(); + + + //Fetch problem ID just created for parts or labor entries + q.Format("SELECT probs.id FROM probs WHERE (((probs.wolink)=%u));",lWOID); + rs2->Query(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("Error: Can't locate the workorder record (problem id) just created.\r\n Contact tech support with the details."); + return; + } + + rs2->FetchField("id",&lProbID); + + + //QUICK WORKORDER: CREATE A LABOUR RECORD + if(bQuick) + { + //v1.9.4.4 get and set default client rates + //various changes in this block + long lDefRate=0; + long lDefTravelRate=0; + + q.Format("SELECT clients.defrate, clients.deftravelrate FROM " + "clients WHERE (((clients.id)=%u));",lClient); + rs3->QueryReadOnly(q); + if(!rs3->IsEmpty()) + { + rs3->FetchField("defrate",&lDefRate); + rs3->FetchField("deftravelrate",&lDefTravelRate); + + } + rs3->Close(); + + + q.Format("INSERT INTO labor ( link, tech, rate, travrate, start, stop, details ) " + "SELECT %u, %u,%u, %u, #%s#, #%s#, \"%s\";",lProbID,lTech,lDefRate,lDefTravelRate, + dtScheduled.Format(_T("%m/%d/%Y")),dtScheduled.Format(_T("%m/%d/%Y")), + strDescription + "\r\n" + strNotes+"\r\n----------\r\n"); + rs2->Ex(q); + rs2->Close(); + //v1.9.4.4 end of changes in this block + + /* PRE 1944 version + q.Format("INSERT INTO labor ( link, tech, start, stop, details ) " + "SELECT %u, %u, #%s#, #%s#, \"%s\";",lProbID,lTech, + dtScheduled.Format(_T("%m/%d/%Y %H:%M:%S")),dtScheduled.Format(_T("%m/%d/%Y %H:%M:%S")), + "Preventive maintenance:\r\n" + strDescription + "\r\n" + strNotes+"\r\n----------\r\n"); + rs2->Ex(q); + rs2->Close();*/ + } + + //STANDARD WORKORDER: CHECK FOR PARTS AND CREATE WOPARTS RECORDS AS NECESSARY + if(!bQuick) + { + q.Format("SELECT pmparts.pmlink, pmparts.partnum, pmparts.quantity, parts.retail, parts.avgcost " + "FROM pmparts LEFT JOIN parts ON pmparts.partnum = parts.id " + "WHERE (((pmparts.pmlink)=%u));",lHeaderID); + + rs2->QueryReadOnly(q); + + if(!rs2->IsEmpty()) + { + COleCurrency crData; + COleCurrency crCost; + CgzCurrencyFormatter cfm; + long lPartID; + float fQuant; + //CREATE PARTS RECORDS UNTIL NO MORE + do { + rs2->FetchField("partnum",&lPartID); + rs2->FetchField("quantity",&fQuant); + rs2->FetchField("retail",&crData); + rs2->FetchField("avgcost",&crCost); + q.Format("INSERT INTO woparts ( " + "link, partnum, quantity, price, cost, usedby, misc ) " + "SELECT %u, %u, %f, '%s', '%s', %u, Null;",lProbID,lPartID,fQuant,cfm.Format(crData), + cfm.Format(crCost),lTech); + rs3->Ex(q); + rs3->Close(); + + + }while(rs2->MoveForward()); + + } + + + } + + + + + + + //RESCHEDULE TO REPLACE CONVERTED ITEM OR DELETE IF NOT RECURRING + if(!bAutorpt) + { + //Remove PM ITEM here if not recurring, else just change date/meter count: + q.Format("DELETE pmitems.* FROM pmitems WHERE pmitems.id=%s;",strPMItem); + rs2->Ex(q); + } + else + {//increment this record. + + //Find out which record is the highest + q.Format("SELECT TOP 1 pmitems.id " + "FROM pmitems " + "WHERE (((pmitems.pmschedlink)=%u) AND ((pmitems.link)=%u)) " + "ORDER BY pmitems.id DESC;",lHeaderID,lLink); + rs2->Query(q); + if(rs2->IsEmpty()) + { + AfxMessageBox("Error: Can't locate the highest pmschedule for rescheduling.\r\n Contact tech support with the details."); + return; + } + rs2->FetchField("id",&lHighestPMID); + + + + //ASCERTAIN THE HIGHEST RECORD + if(lHighestPMID!=atol(strPMItem))//are were already at the highest to convert to workorder? + {//if no: load in the highest records meter and or date data for processing + q.Format("SELECT pmitems.schedate, pmitems.schedmeter FROM pmitems " + "WHERE (((pmitems.id)=%u));",lHighestPMID); + rs2->Query(q); + + if(rs2->IsEmpty()) + { + AfxMessageBox("Error: Can't open the highest pmschedule for rescheduling.\r\n Contact tech support with the details."); + return; + } + + rs2->FetchField("schedmeter",&lSchedMeter); + rs2->FetchField("schedate",&dtScheduled); + + + //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + //INCREMENT DATE OR METER DEPENDING + + if(dtScheduled.GetYear()==1968)//it's meter based + { + //Process as a meter based record + //this one's easy: + lSchedMeter+=lRepeat; + } + else //calculate next date based pmitem record + { + //prepare a simpledate class object + CSimpleDate sdTemp(dtScheduled.GetMonth(),dtScheduled.GetDay(),dtScheduled.GetYear()); + + + //Add the months, then increment to the right + //day of week if necessary. + sdTemp.AddDays(lDays); + sdTemp.AddDays(lWeeks*7); + sdTemp.AddMonths(lRepeat); + +//******************************************************************* +//ADD DAYS HERE +//******************************************************************* + + //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 + + nDOW=(int)lDOW; + 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(); + + + } + } + + + //set dtTemp back again. + + dtScheduled.SetDate(sdTemp.GetYear(),sdTemp.GetMonth(),sdTemp.GetDay()); + + } + + //<<<<<<<<<<<<<<<<<<<<< + //OK, at this point we have incremented either the date + //or the meter reading and can now insert the replacement record + //and then delete the old record + //done this way rather than updating existing record because were + //relying on a higher id value to indicate the farthest "flung" scheduled item + q.Format("INSERT INTO pmitems ( " + "pmschedlink, schedate, schedmeter, autowo, hold, schedtech, " + "link, isclient, clientlink) " + "SELECT %u, #%s#, %u, %s, %s, %u, %u, %s, %u;", + lHeaderID, dtScheduled.Format(_T("%m/%d/%Y")), lSchedMeter, bAutoWO ? "True" : "False", + bHold ? "True" : "False", lTech, lLink, bIsClient ? "True" : "False", + lClient); + rs2->Ex(q); + rs2->Close(); + + q.Format("DELETE pmitems.* FROM pmitems WHERE pmitems.id=%s;",strPMItem); + rs2->Ex(q); + + + } + } +} + + + + +void CPMCheckDlg::Security() +{ +m_bReadOnly=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_bReadOnly=true; + + CMenu* pMenu=this->GetMenu(); + pMenu->EnableMenuItem(1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED); + + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.h new file mode 100644 index 0000000..bbe3fbf --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMCheckDlg.h @@ -0,0 +1,73 @@ +#if !defined(AFX_PMCHECKDLG_H__742E4B01_43CB_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PMCHECKDLG_H__742E4B01_43CB_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PMCheckDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPMCheckDlg dialog +#include "ReportCtrl.h" +#include "gzrset.h" +#include "SimpleDate.h" +#include "ResizeCtrl.h" +class CPMCheckDlg : public CDialog +{ +// Construction +public: + CResizeCtrl m_resize; + void MakeIntoWorkorder(CString strPMItem); + CString m_strOrderBy; + void FlipMeterDate(); + bool m_bShowDateFormat; + void FillView(); + BOOL bColumnSortAsc[9]; + ~CPMCheckDlg(); + CPMCheckDlg(CWnd* pParent = NULL); // standard constructor + GZRset* rs; + GZRset* rs2; + GZRset* rs3; + CSpApp* m_pApp; + void OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult); +// Dialog Data + //{{AFX_DATA(CPMCheckDlg) + enum { IDD = IDD_PMCHECK }; + CReportCtrl m_rc; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPMCheckDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: +CImageList m_ilReport; + // Generated message map functions + //{{AFX_MSG(CPMCheckDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPmviewDone(); + afx_msg void OnPmviewShowdateitems(); + afx_msg void OnPmviewShowmetered(); + afx_msg void OnPmviewSelecteditemConverttoworkorder(); + afx_msg void OnPmviewSelecteditemDelete(); + afx_msg void OnPmviewSelecteditemEdit(); + afx_msg void OnPmviewSelecteditemHoldrelease(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + bool m_bReadOnly; + void Security(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PMCHECKDLG_H__742E4B01_43CB_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.cpp new file mode 100644 index 0000000..07e57db --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.cpp @@ -0,0 +1,952 @@ +// PMDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "PMDlg.h" +#include "partsdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPMDlg dialog + + +CPMDlg::CPMDlg(CWnd* pParent /*=NULL*/) + : CDialog(CPMDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPMDlg) + //}}AFX_DATA_INIT + m_bAddMode=false; + m_pApp= (CSpApp*)AfxGetApp(); + rs=new GZRset("Error: PM dialog"); + rs->SetConnect(m_pApp->strConnectString); + cbrs=new GZRset("Error: PM dialog combo box recordset\r\n"); + cbrs->SetConnect(m_pApp->strConnectString); + m_strSelectedPM.Empty(); + m_strCriteria.Empty(); + m_bNoRecord=true; + +} + +//********************************* +CPMDlg::~CPMDlg() +{ + delete rs; + delete cbrs; +} + +void CPMDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPMDlg) + DDX_Control(pDX, IDC_CKAUTOWO, m_ckAutoWO); + DDX_Control(pDX, IDC_EDADVANCE, m_edAdvance); + DDX_Control(pDX, IDC_LBLADVANCE, m_lblAdvance); + DDX_Control(pDX, IDC_LBPARTSREQ, m_lbParts); + DDX_Control(pDX, IDC_LBLQUANT, m_lblQuantity); + DDX_Control(pDX, IDC_LBLPARTSLIST, m_lblPartsList); + DDX_Control(pDX, IDC_CKREPEAT, m_ckRepeat); + DDX_Control(pDX, IDC_LBLMETERMONTHS, m_lblMeterMonths); + DDX_Control(pDX, IDC_CKONCEONLY, m_ckOnceOnly); + DDX_Control(pDX, IDC_CKMETER, m_ckMeter); + DDX_Control(pDX, IDC_CKAGE, m_ckAge); + DDX_Control(pDX, IDC_EDQUANTITY, m_edQuantity); + DDX_Control(pDX, IDC_BTNREMOVEPART, m_btnRemovePart); + DDX_Control(pDX, IDC_LBLPMLIST, m_lblPMList); + DDX_Control(pDX, IDC_LBLPART, m_lblPart); + DDX_Control(pDX, IDC_LBLNEXTSERVICEDATE, m_lblNextServiceDate); + DDX_Control(pDX, IDC_LBLAGEMETER, m_lblAgeMeter); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_EDMETERMONTHS, m_edMeterMonths); + DDX_Control(pDX, IDC_EDDESCRIPTION, m_edDescription); + DDX_Control(pDX, IDC_DTNEXTSERVICE, m_dtNextService); + DDX_Control(pDX, IDC_CKACTIVE, m_ckActive); + DDX_Control(pDX, IDC_CBPMLIST, m_cbPMList); + DDX_Control(pDX, IDC_CBPARTS, m_cbParts); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNDELETE, m_btnDelete); + DDX_Control(pDX, IDC_BTNADDPART, m_btnAddPart); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPMDlg, CDialog) + //{{AFX_MSG_MAP(CPMDlg) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_BN_CLICKED(IDC_BTNREMOVEPART, OnBtnremovepart) + ON_BN_CLICKED(IDC_BTNADDPART, OnBtnaddpart) + ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) + ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete) + ON_CBN_CLOSEUP(IDC_CBPARTS, OnCloseupCbparts) + ON_CBN_CLOSEUP(IDC_CBPMLIST, OnCloseupCbpmlist) + ON_BN_CLICKED(IDC_CKACTIVE, OnCkactive) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTNEXTSERVICE, OnDatetimechangeDtnextservice) + ON_EN_KILLFOCUS(IDC_EDDESCRIPTION, OnKillfocusEddescription) + ON_EN_KILLFOCUS(IDC_EDMETERMONTHS, OnKillfocusEdmetermonths) + ON_EN_KILLFOCUS(IDC_EDNOTES, OnKillfocusEdnotes) + ON_BN_CLICKED(IDC_LBLPART, OnLblpart) + ON_BN_CLICKED(IDC_CKAGE, OnCkage) + ON_BN_CLICKED(IDC_CKMETER, OnCkmeter) + ON_BN_CLICKED(IDC_CKONCEONLY, OnCkonceonly) + ON_BN_CLICKED(IDC_CKREPEAT, OnCkrepeat) + ON_EN_KILLFOCUS(IDC_EDADVANCE, OnKillfocusEdadvance) + ON_BN_CLICKED(IDC_CKAUTOWO, OnCkautowo) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPMDlg message handlers + +void CPMDlg::SetMode(bool clientmode) +{ + + m_bClientMode=clientmode; + //false=model record + //true =client record +} + + +//************************************* +BOOL CPMDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); +// ShowWindow(SW_MAXIMIZE); + + //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(""); + + + ASSERT(!m_strCriteria.IsEmpty());//would mean no criteria was passed + if(m_strCriteria.IsEmpty()) + { + AfxMessageBox("Error in PMSCHEDULE dialog, no Model or Client criteria."); + CDialog::OnCancel(); + } + + if(m_bClientMode==true) + { + m_lblAgeMeter.ShowWindow(FALSE); + m_ckAge.ShowWindow(FALSE); + m_ckMeter.ShowWindow(FALSE); + m_lblNextServiceDate.ShowWindow(TRUE); + m_dtNextService.ShowWindow(TRUE); + m_ckRepeat.SetWindowText("Repeat at interval"); + m_ckOnceOnly.SetWindowText("Service once only next service date"); + m_lblMeterMonths.SetWindowText("Repeat interval (months):"); + } + else + { + m_lblAgeMeter.ShowWindow(TRUE); + m_ckAge.ShowWindow(TRUE); + m_ckMeter.ShowWindow(TRUE); + m_lblNextServiceDate.ShowWindow(FALSE); + m_dtNextService.ShowWindow(FALSE); + m_ckRepeat.SetWindowText("Repeat every reading / age interval"); + m_ckOnceOnly.SetWindowText("Service once only at reading / age"); + m_lblMeterMonths.SetWindowText("Repeat interval (meter/months):"); + + } + + + FillPartsList(); + FillPMList(); + + Security(); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE + + +} + + +//************************************** + +void CPMDlg::SetCriteria(CString strID) +{ + ASSERT(!strID.IsEmpty()); + m_strCriteria=strID; +} + + +//*************************************** +void CPMDlg::FillPMList() +{ + + CString strData,strType,q; + CString strIndex; + long lData; + m_cbPMList.Clear(); + + //are we doing this for a client or a model? + if(m_bClientMode) + strType="client"; + else + strType="model"; + + //select all schedule records for this + //client or unit model + q.Format("SELECT pmschedules.* FROM pmschedules " + "WHERE (((pmschedules.%s)=%s)) " + "ORDER BY pmschedules.description;",strType,m_strCriteria); + + rs->QueryReadOnly(q); + + if(rs->IsEmpty()) + { + m_bNoRecord=true; + ClearFields(); + return; + } + m_bNoRecord=false; + + 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 CPMDlg::FillPartsList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbParts.Clear(); + + + + cbrs->QueryReadOnly("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 CPMDlg::OnBtndone() +{ + CDialog::OnOK(); +} + + + + + +//*********************************** +void CPMDlg::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;yExecute(q)) + break; + } + + + + FillRequiredPartsList(); +} + + + + +//check for and fill in required parts lb +void CPMDlg::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->QueryReadOnly(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 CPMDlg::OnBtnaddpart() +{ + CString q,strData; + float fData; + if(m_bNoRecord) return; + m_edQuantity.GetWindowText(strData); + fData=(float)atof(strData); + q.Format("SELECT pmparts.pmlink FROM pmparts " + "WHERE (((pmparts.pmlink)=%s) AND ((pmparts.partnum)=%s));",m_strSelectedPM,m_cbParts.GetCurrentRowID()); + cbrs->QueryReadOnly(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->Execute(q); + cbrs->Close(); + FillRequiredPartsList(); + +} + + + +//************************************************** +void CPMDlg::OnBtnadd() +{ + CString strData,q; + bool bData; + float fData,fZero; + long lData; + COleDateTime dtData; + fZero=0; + + if(!m_bAddMode) + { + //Go Add mode + m_bAddMode=true; + m_lblPart.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_lblPartsList.ShowWindow(FALSE); + m_lblQuantity.ShowWindow(FALSE); + m_edQuantity.ShowWindow(FALSE); + m_btnDone.ShowWindow(FALSE); + m_btnAdd.SetWindowText("SAVE"); + m_btnDelete.SetWindowText("CANCEL"); + ClearFields(); + + + + } + else + { //Save and go edit mode + + + //DESCRIPTION + m_edDescription.GetWindowText(strData); + if(strData.IsEmpty()) + { + AfxMessageBox("Description is required to proceed"); + return; + } + + if(!rs->AddNewRecord()) + return; + + rs->UpdateField("description",&strData); + + //UNITBASED + bData=m_bClientMode ? false : true; + rs->UpdateField("unitbased",&bData); + + //CLIENT + if(m_bClientMode) + lData=atol(m_strCriteria); + else + lData=0; + rs->UpdateField("client",&lData); + + //MODEL + if(!m_bClientMode) + lData=atol(m_strCriteria); + else + lData=0; + rs->UpdateField("model",&lData); + + //AGEBASED + bData=m_ckAge.GetCheck() ? true : false; + rs->UpdateField("agebased",&bData); + + //AGEMONTHS / METER + m_edMeterMonths.GetWindowText(strData); + fData=(float)atof(strData); + + if(bData)//is age + { + rs->UpdateField("agemonths",&fData); + rs->UpdateField("meter",&fZero); + + } + else + {//is metric + rs->UpdateField("meter",&fData); + rs->UpdateField("agemonths",&fZero); + + } + + //CYCLICAL + bData=m_ckRepeat.GetCheck() ? true : false; + rs->UpdateField("cyclical",&bData); + + //NOTES + m_edNotes.GetWindowText(strData); + rs->UpdateField("notes",&strData); + + //NEXTDATE + m_dtNextService.GetTime(dtData); + rs->UpdateField("nextdate",&dtData); + + //ACTIVE + bData=m_ckActive.GetCheck() ? true : false; + rs->UpdateField("active",&bData); + + //ADVANCE WARNING + m_edAdvance.GetWindowText(strData); + if(strData.IsEmpty()) strData="1"; + lData=atol(strData); + if(lData==0) lData=1; + rs->UpdateField("advancewarning",&lData); + + //CREATOR FIELDS + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("creator",&m_pApp->m_lusrID); + rs->UpdateField("created",&dtData); + rs->UpdateField("modifier",&m_pApp->m_lusrID); + rs->UpdateField("modified",&dtData); + if(!rs->SaveRecord()) + return; + + + m_bAddMode=false; + m_cbPMList.ShowWindow(TRUE); + m_lblPart.ShowWindow(TRUE); + m_lblPMList.ShowWindow(TRUE); + m_lbParts.ShowWindow(TRUE); + m_btnRemovePart.ShowWindow(TRUE); + m_btnAddPart.ShowWindow(TRUE); + m_cbParts.ShowWindow(TRUE); + m_lblPartsList.ShowWindow(TRUE); + m_lblQuantity.ShowWindow(TRUE); + m_edQuantity.ShowWindow(TRUE); + m_btnDone.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + FillPMList(); + + } + + + +} + +//*********************************************** +void CPMDlg::OnBtndelete() +{ + CString q; + + if(m_bAddMode) + {//Cancel add mode + m_bAddMode=false; + m_lblPart.ShowWindow(TRUE); + m_lblPMList.ShowWindow(TRUE); + m_lbParts.ShowWindow(TRUE); + m_btnRemovePart.ShowWindow(TRUE); + m_btnAddPart.ShowWindow(TRUE); + m_cbParts.ShowWindow(TRUE); + m_lblPartsList.ShowWindow(TRUE); + m_lblQuantity.ShowWindow(TRUE); + m_edQuantity.ShowWindow(TRUE); + m_cbPMList.ShowWindow(TRUE); + m_btnDone.ShowWindow(TRUE); + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + FillPMList(); + } + +if(m_bNoRecord) return; + + + +if(AfxMessageBox("Permanently delete this PM record?",MB_YESNO)!=IDYES) + return; + +//delete PM entry +q.Format("DELETE pmschedules.*, pmschedules.id FROM pmschedules " +"WHERE (((pmschedules.id)=%s));",m_strSelectedPM); + +if(!rs->Execute(q)) return; + +//Delete parts list enty if any +q.Format("DELETE pmparts.*, pmparts.pmlink FROM pmparts " +"WHERE (((pmparts.pmlink)=%s));",m_strSelectedPM); +rs->Execute(q); + +m_strSelectedPM.Empty(); +FillPMList(); + +} + + +//************************************************ +void CPMDlg::OnCloseupCbparts() +{ + //do nothing, nothing necessary in this case + +} + +//************************************************ +void CPMDlg::OnCloseupCbpmlist() +{ + m_strSelectedPM=m_cbPMList.GetCurrentRowID(); + FillFields(); +} + +//****************************************** +void CPMDlg::OnCkactive() +{ + + SaveField(&m_ckActive,"active"); +} +//******************************** +void CPMDlg::OnDatetimechangeDtnextservice(NMHDR* pNMHDR, LRESULT* pResult) +{ + SaveField(&m_dtNextService,"nextdate"); + + *pResult = 0; +} + + +//************************************* +void CPMDlg::OnKillfocusEddescription() +{ + SaveField(&m_edDescription,"description",false); + if(!m_bAddMode) + FillPMList(); + +} +//************************************* +void CPMDlg::OnKillfocusEdmetermonths() +{ + if(m_bAddMode || m_bNoRecord) return; + CString strData; + bool bData; + float fData,fZero; + fZero=0; + + bData=m_ckAge.GetCheck() ? true : false; + //AGEMONTHS / METER + m_edMeterMonths.GetWindowText(strData); + fData=(float)atof(strData); + + if(bData)//is age + { + rs->UpdateField("agemonths",&fData); + rs->UpdateField("meter",&fZero); + + } + else + {//is metric + rs->UpdateField("meter",&fData); + rs->UpdateField("agemonths",&fZero); + + } + rs->SaveRecord(); + UpdateModified(); +} + +//***************************** +void CPMDlg::OnKillfocusEdnotes() +{ + SaveField(&m_edNotes,"notes",true); + +} + + +//************************************ +void CPMDlg::OnLblpart() +{ + CPartsDlg d; +if(d.DoModal()==IDOK) + FillPartsList(); +} + + + + +//fill fields +void CPMDlg::FillFields() +{ + CString strData,q; + COleDateTime dtData; + bool bData; + float fData; + long lData; + ClearFields(); + q.Format("SELECT pmschedules.* FROM pmschedules " + "WHERE (((pmschedules.id)=%s));",m_cbPMList.GetCurrentRowID()); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + return; + + //DESCRIPTION + rs->FetchField("description",&strData); + m_edDescription.SetWindowText(strData); + + //AGEBASED + rs->FetchField("agebased",&bData); + m_ckAge.SetCheck(bData ? TRUE : FALSE); + m_ckMeter.SetCheck(!m_ckAge.GetCheck()); + + //AGEMONTHS + if(bData)//is age based + rs->FetchField("agemonths",&fData); + else//is metric + rs->FetchField("meter",&fData); + strData.Format("%1.2f",fData); + m_edMeterMonths.SetWindowText(strData); + + + //CYCLICAL + rs->FetchField("cyclical",&bData); + m_ckRepeat.SetCheck(bData ? TRUE : FALSE); + m_ckOnceOnly.SetCheck(!m_ckRepeat.GetCheck()); + + //NOTES + rs->FetchField("notes",&strData); + m_edNotes.SetWindowText(strData); + + //NEXTDATE + rs->FetchField("nextdate",&dtData); + m_dtNextService.SetTime(dtData); + + //ACTIVE + rs->FetchField("active",&bData); + m_ckActive.SetCheck(bData ? TRUE : FALSE); + + //Autoworkorder + rs->FetchField("autoworkorder",&bData); + m_ckAutoWO.SetCheck(bData ? TRUE : FALSE); + + //advance warning + rs->FetchField("advancewarning",&lData); + strData.Format("%u",lData); + m_edAdvance.SetWindowText(strData); + + FillRequiredPartsList(); + + +} + + + +//************************************** +void CPMDlg::OnCkage() +{ + m_ckMeter.SetCheck(!m_ckAge.GetCheck()); + SaveAgeMeterFields(); +} +//******************************************** +void CPMDlg::OnCkmeter() +{ + m_ckAge.SetCheck(!m_ckMeter.GetCheck()); + SaveAgeMeterFields(); +} + +//************************************ +void CPMDlg::OnCkonceonly() +{ + m_ckRepeat.SetCheck(!m_ckOnceOnly.GetCheck()); + if(m_ckRepeat.GetCheck()==FALSE) + m_edMeterMonths.SetWindowText("0"); + SaveRepeatOnceOnlyFields(); + +} +//********************************************* +void CPMDlg::OnCkrepeat() +{ + m_ckOnceOnly.SetCheck(!m_ckRepeat.GetCheck()); + SaveRepeatOnceOnlyFields(); +} + + +//********************************************** +void CPMDlg::OnCkautowo() +{ + SaveField(&m_ckAutoWO,"autoworkorder"); + +} + + +//************************************************ +//UPDATE MODIFIED DATA +//************************************************* +bool CPMDlg::UpdateModified() +{ + //updates modified by and modified on fields + rs->UpdateField("modifier",&m_pApp->m_lusrID); + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + rs->SaveRecord(); + + + return true; +} + + + +//************************************ +void CPMDlg::ClearFields() +{ + + m_edNotes.SetWindowText(""); + m_edQuantity.SetWindowText(""); + m_edMeterMonths.SetWindowText(""); + m_edDescription.SetWindowText(""); + m_dtNextService.SetTime(COleDateTime::GetCurrentTime()); + m_ckRepeat.SetCheck(TRUE); + m_ckOnceOnly.SetCheck(FALSE); + m_ckMeter.SetCheck(FALSE); + m_ckAge.SetCheck(TRUE); + m_ckActive.SetCheck(TRUE); + m_lbParts.Clear(); +} + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CPMDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE GZCOMBO CONTROL FIELD +//************************************************************ +bool CPMDlg::SaveField(CgzCombo *cbControl,CString fldname) +{ + + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + CString str; + long lData; + str=cbControl->GetCurrentRowID(); + if(str.IsEmpty()) return false;//shouldn't happen but... + lData=atol(str); + rs->UpdateField(fldname,&lData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CPMDlg::SaveField(CButton *ckControl,CString fldname) +{ + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + UpdateModified(); + return true; +} +//************************************************************ +//SAVE DateTimePicker CONTROL FIELD +//************************************************************ +bool CPMDlg::SaveField(CDateTimeCtrl *dtControl,CString fldname) +{ + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + COleDateTime dtData; + dtControl->GetTime(dtData); + rs->UpdateField(fldname,&dtData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************** +void CPMDlg::SaveAgeMeterFields() +{ + bool bData; + if(m_bAddMode || m_bNoRecord) return; + bData=m_ckAge.GetCheck() ? true : false; + rs->UpdateField("agebased",&bData); + rs->SaveRecord(); + UpdateModified(); +} + +//************************************* +void CPMDlg::SaveRepeatOnceOnlyFields() +{ + bool bData; + if(m_bAddMode || m_bNoRecord) return; + bData=m_ckRepeat.GetCheck() ? true : false; + rs->UpdateField("cyclical",&bData); + rs->SaveRecord(); + UpdateModified(); +} + + + +void CPMDlg::OnKillfocusEdadvance() +{ + //ADVANCE WARNING + if(m_bAddMode || m_bNoRecord) return; + CString strData; + long lData; + + m_edAdvance.GetWindowText(strData); + if(strData.IsEmpty()) strData="1"; + lData=atol(strData); + if(lData==0) lData=1; + + strData.Format("%u",lData); + m_edAdvance.SetWindowText(strData); + rs->UpdateField("advancewarning",&lData); + + rs->SaveRecord(); + UpdateModified(); +} + +void CPMDlg::Security() +{ + + //m_bReadOnly=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_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_btnAddPart.ShowWindow(FALSE); + m_btnRemovePart.ShowWindow(FALSE); + m_cbParts.EnableWindow(FALSE); + m_ckActive.EnableWindow(FALSE); + m_ckAge.EnableWindow(FALSE); + m_ckMeter.EnableWindow(FALSE); + m_ckOnceOnly.EnableWindow(FALSE); + m_ckRepeat.EnableWindow(FALSE); + m_dtNextService.EnableWindow(FALSE); + m_edAdvance.SetReadOnly(TRUE); + m_edDescription.SetReadOnly(TRUE); + m_edMeterMonths.SetReadOnly(TRUE); + m_edNotes.SetReadOnly(TRUE); + m_edQuantity.SetReadOnly(TRUE); + + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.h new file mode 100644 index 0000000..653783e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMDlg.h @@ -0,0 +1,121 @@ +#if !defined(AFX_PMDLG_H__69649FC2_2BEE_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PMDLG_H__69649FC2_2BEE_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PMDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPMDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "gzlistbox.h" +#include "label.h" + +class CPMDlg : public CDialog +{ +// Construction +public: + void Security(); + ~CPMDlg(); + void SaveRepeatOnceOnlyFields(); + void SaveAgeMeterFields(); + void ClearFields(); + void FillFields(); + bool m_bNoRecord; + void FillRequiredPartsList(); + void FillPartsList(); + void FillPMList(); + void SetCriteria(CString strID); + CString m_strCriteria; + bool m_bClientMode; + void SetMode(bool clientmode); + CPMDlg(CWnd* pParent = NULL); // standard constructor + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool SaveField(CgzCombo* cbControl,CString fldname); + bool SaveField(CButton* ckControl,CString fldname); + bool SaveField(CDateTimeCtrl* dtControl,CString fldname); + bool UpdateModified(); + //------------------------------- + CSpApp* m_pApp; + GZRset* rs; + GZRset* cbrs; + bool m_bAddMode; + CString m_strSelectedPM; +// Dialog Data + //{{AFX_DATA(CPMDlg) + enum { IDD = IDD_PMSCHEDULE }; + CButton m_ckAutoWO; + CEdit m_edAdvance; + CStatic m_lblAdvance; + CgzListBox m_lbParts; + CStatic m_lblQuantity; + CStatic m_lblPartsList; + CButton m_ckRepeat; + CStatic m_lblMeterMonths; + CButton m_ckOnceOnly; + CButton m_ckMeter; + CButton m_ckAge; + CEdit m_edQuantity; + CButton m_btnRemovePart; + CStatic m_lblPMList; + CLabel m_lblPart; + CStatic m_lblNextServiceDate; + CButton m_lblAgeMeter; + CEdit m_edNotes; + CEdit m_edMeterMonths; + CEdit m_edDescription; + CDateTimeCtrl m_dtNextService; + CButton m_ckActive; + CgzCombo m_cbPMList; + CgzCombo m_cbParts; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnAddPart; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPMDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPMDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnBtndone(); + afx_msg void OnBtnremovepart(); + afx_msg void OnBtnaddpart(); + afx_msg void OnBtnadd(); + afx_msg void OnBtndelete(); + afx_msg void OnCloseupCbparts(); + afx_msg void OnCloseupCbpmlist(); + afx_msg void OnCkactive(); + afx_msg void OnDatetimechangeDtnextservice(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKillfocusEddescription(); + afx_msg void OnKillfocusEdmetermonths(); + afx_msg void OnKillfocusEdnotes(); + afx_msg void OnLblpart(); + afx_msg void OnCkage(); + afx_msg void OnCkmeter(); + afx_msg void OnCkonceonly(); + afx_msg void OnCkrepeat(); + afx_msg void OnKillfocusEdadvance(); + afx_msg void OnCkautowo(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PMDLG_H__69649FC2_2BEE_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.cpp new file mode 100644 index 0000000..f58b492 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.cpp @@ -0,0 +1,94 @@ +// PMViewPrompt.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "PMViewPrompt.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPMViewPrompt dialog + +//RETURNS 0=CANCEL,1=SELECTED, 2=MASTER +CPMViewPrompt::CPMViewPrompt(CWnd* pParent /*=NULL*/) + : CDialog(CPMViewPrompt::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPMViewPrompt) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pnReturn=NULL; +} + +BOOL CPMViewPrompt::OnInitDialog() +{ + CDialog::OnInitDialog(); + ASSERT(m_pnReturn!=NULL); + SetWindowText(m_strTitle); + m_lblPrompt.SetWindowText(m_strPrompt); + m_btnCancel.SetFocus(); + return FALSE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CPMViewPrompt::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPMViewPrompt) + DDX_Control(pDX, IDCANCEL, m_btnCancel); + DDX_Control(pDX, IDC_LBLPROMPT, m_lblPrompt); + DDX_Control(pDX, IDC_BTNSELECTEDONLY, m_btnSelectedOnly); + DDX_Control(pDX, IDC_BTNMASTER, m_btnMaster); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPMViewPrompt, CDialog) + //{{AFX_MSG_MAP(CPMViewPrompt) + ON_BN_CLICKED(IDC_BTNSELECTEDONLY, OnBtnselectedonly) + ON_BN_CLICKED(IDC_BTNMASTER, OnBtnmaster) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPMViewPrompt message handlers + +void CPMViewPrompt::OnOK() +{//enter key hack +} + +void CPMViewPrompt::OnCancel() +{ + *m_pnReturn=0; + + CDialog::OnOK(); +} + +void CPMViewPrompt::OnBtnselectedonly() +{ + *m_pnReturn=1; + CDialog::OnOK(); + +} + +void CPMViewPrompt::OnBtnmaster() +{ + *m_pnReturn=2; + CDialog::OnOK(); + +} + + +//RETURNS 0=CANCEL,1=SELECTED, 2=MASTER +void CPMViewPrompt::Setup(/*RETURNS 0=CANCEL,1=SELECTED, 2=MASTER */CString strPrompt, CString strTitle, int * nResult) +{ + m_strPrompt=strPrompt; + m_strTitle=strTitle; + m_pnReturn=nResult; + +} + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.h new file mode 100644 index 0000000..2573b5f --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PMViewPrompt.h @@ -0,0 +1,57 @@ +#if !defined(AFX_PMVIEWPROMPT_H__EC43E182_A380_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PMVIEWPROMPT_H__EC43E182_A380_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PMViewPrompt.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPMViewPrompt dialog + +class CPMViewPrompt : public CDialog +{ +// Construction +public: + int * m_pnReturn; + CString m_strTitle; + void Setup(CString strPrompt, CString strTitle, int* nResult); + CString m_strPrompt; + CPMViewPrompt(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CPMViewPrompt) + enum { IDD = IDD_PMSERIESSINGLEPROMPTER }; + CButton m_btnCancel; + CStatic m_lblPrompt; + CButton m_btnSelectedOnly; + CButton m_btnMaster; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPMViewPrompt) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPMViewPrompt) + virtual void OnOK(); + virtual void OnCancel(); + afx_msg void OnBtnselectedonly(); + afx_msg void OnBtnmaster(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PMVIEWPROMPT_H__EC43E182_A380_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.cpp new file mode 100644 index 0000000..36be6ec --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.cpp @@ -0,0 +1,76 @@ +// PWDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "PWDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPWDlg dialog + + +CPWDlg::CPWDlg(CWnd* pParent /*=NULL*/) + : CDialog(CPWDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPWDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CPWDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPWDlg) + DDX_Control(pDX, IDC_USER, m_edUsername); + DDX_Control(pDX, IDOK, m_btnOK); + DDX_Control(pDX, IDC_PW2, m_edPW2); + DDX_Control(pDX, IDC_PW1, m_edPW1); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPWDlg, CDialog) + //{{AFX_MSG_MAP(CPWDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPWDlg message handlers + +void CPWDlg::PassPWString(CString *pw, CString *user) +{ + strPassword=pw; + strUserName=user; +} + +void CPWDlg::OnOK() +{ + // TODO: Add extra validation here + CString pw1,pw2,usr; + m_edPW1.GetWindowText(pw1); + m_edPW2.GetWindowText(pw2); + m_edUsername.GetWindowText(usr); + + if(usr.IsEmpty()) + { + AfxMessageBox("You must enter a user login name"); + return; + } + + if(pw2.Compare(pw1)!=0) + { + AfxMessageBox("Password and confirmation do not match!"); + return; + + } + strPassword->Format("%s",pw1); + strUserName->Format("%s",usr); + CDialog::OnOK(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.h new file mode 100644 index 0000000..c2d11eb --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PWDlg.h @@ -0,0 +1,53 @@ +#if !defined(AFX_PWDLG_H__BAEA8B21_1776_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PWDLG_H__BAEA8B21_1776_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PWDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPWDlg dialog + +class CPWDlg : public CDialog +{ +// Construction +public: + void PassPWString(CString* pw, CString *user); + CPWDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CPWDlg) + enum { IDD = IDD_PWDLG }; + CEdit m_edUsername; + CButton m_btnOK; + CEdit m_edPW2; + CEdit m_edPW1; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPWDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPWDlg) + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + CString * strUserName; + CString * strPassword; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PWDLG_H__BAEA8B21_1776_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.cpp new file mode 100644 index 0000000..12d825e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.cpp @@ -0,0 +1,253 @@ +#include "stdafx.h" +#include +#include "parseit.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + + +/////////////////////////////////////////////////////////////////////////// +// Desc: default constructor just set some default values +// params: +// returns: +/////////////////////////////////////////////////////////////////////////// +CParseIt::CParseIt(BOOL Strip) +{ + strcpy(Seperator,","); + StripQuotes=Strip; + NumFields=0; + TheData=NULL; +} + +/////////////////////////////////////////////////////////////////////////// +// Desc: construct object to parse data using sep for the list of seperators +// params: +// returns: +/////////////////////////////////////////////////////////////////////////// +CParseIt::CParseIt(LPCSTR Data,LPCSTR Sep,BOOL Strip) +{ + NumFields=0; + StripQuotes=Strip; + TheData=new char[strlen(Data)+1]; + strcpy(TheData,Data); + strncpy(Seperator,Sep,9); + Parse(); + +} +/////////////////////////////////////////////////////////////////////////// +// Desc: destructor: free all allocated memory variables and free up the +// data stored in the pointer array +// params: +// returns: +/////////////////////////////////////////////////////////////////////////// +CParseIt::~CParseIt() +{ + CParseField* pData; + if(TheData!=NULL) + delete[] TheData; + for(int y=0;y < TheFields.GetSize();++y) + { + pData=(CParseField*)TheFields[y]; + delete pData; + } +} + +void CParseIt::ReSet() +{ + CParseField* pData; + if(TheData!=NULL) + { + delete[] TheData; + TheData=NULL; + } + for(int y=0;y < TheFields.GetSize();++y) + { + pData=(CParseField*)TheFields[y]; + delete pData; + } + TheFields.RemoveAll(); + +} + +/////////////////////////////////////////////////////////////////////////// +// Desc: parse the string data using sep as a seperator list +// params: data=string to parse sep= list of seperators +// returns:TRUE if all is well else FALSE if error occours +/////////////////////////////////////////////////////////////////////////// +BOOL CParseIt::Parse(LPCSTR Data,LPCSTR Sep,BOOL Strip) +{ + if(TheData!=NULL) + return FALSE; + StripQuotes=Strip; + strncpy(Seperator,Sep,9); + TheData=new char[strlen(Data)+1]; + strcpy(TheData,Data); + return Parse(); +} +/////////////////////////////////////////////////////////////////////////// +// Desc: Called to do actual parsing of data +// params: none +// returns:TRUE if OK else FALSE +/////////////////////////////////////////////////////////////////////////// +BOOL CParseIt::Parse() +{ + if(TheData==NULL) + return FALSE; + + for(int p=0;p < TheFields.GetSize();++p) + { + CParseField* pData=(CParseField*)TheFields[p]; + delete pData; + } + TheFields.RemoveAll(); + + NumFields=0; + CString t; + t.Empty(); + for(int y=0;y < (int)strlen(TheData);++y) + { + if( !IsSeperator(TheData[y])) + { + if(StripQuotes) + { + if(TheData[y] !='\"') + t+=TheData[y]; + } + else + t+=TheData[y]; + } + else + { + CParseField* pData=new CParseField; + *pData=t; + TheFields.Add(pData); + t.Empty(); + ++NumFields; + } + } + CParseField* pData=new CParseField; + *pData=t; + TheFields.Add(pData); + ++NumFields; + return TRUE; +} +/////////////////////////////////////////////////////////////////////////// +// Desc: determines if the given cahracter is in the list of seperators +// params: The character in question +// returns:TRUE if the cahr is a seperator else FALSE +/////////////////////////////////////////////////////////////////////////// +BOOL CParseIt::IsSeperator(char s) +{ + for(int x=0;x < (int) strlen(Seperator);++x) + { + if(s==Seperator[x]) + return TRUE; + } + return FALSE; +} +/////////////////////////////////////////////////////////////////////////// +// Desc: returns field n in the cstring buff (1 based not zero based +// params: The field number (1..nun fields) and a CString reference +// returns:TRUE if OK else FALSE (out of bounds index) +/////////////////////////////////////////////////////////////////////////// +BOOL CParseIt::GetField(int N,CString& Buff) +{ + if(N <= TheFields.GetSize() && N > 0) + { + Buff=(LPCSTR)*(CParseField*)TheFields[--N]; + return TRUE; + } + Buff.Empty(); + return FALSE; +} +/////////////////////////////////////////////////////////////////////////// +// Desc: returns field n in the string buff (1 based not zero based +// params: The field number (1..nun fields) and a pointer to a string +// returns:TRUE if OK else FALSE (out of bounds index) +/////////////////////////////////////////////////////////////////////////// +BOOL CParseIt::GetField(int N,LPSTR Buff) +{ + if(N <= TheFields.GetSize() && N > 0) + { + strcpy(Buff,(LPCSTR)*(CParseField*)TheFields[--N]); + return TRUE; + } + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////// +// Desc: returns the CParseField object for the indicated field ( 1 based) +// params: the 1 based index of the field +// returns:A CparseField object ( this can be cast to a string,long,double or int) +/////////////////////////////////////////////////////////////////////////// +CParseField CParseIt::GetField(int N) +{ + CParseField p; + if(N <= TheFields.GetSize() && N > 0) + { + --N; + return *(CParseField*)TheFields[N]; + } + return p; +} + +/////////////////////////////////////////////////////////////////////////// +// Desc: Protected function to load data from a disk file +// params: The filename +// returns:TRUE if all OK else FALSE +/////////////////////////////////////////////////////////////////////////// +BOOL CParseIt::LoadFile(LPCSTR lpzFileName) +{ + CFileException e; + int res; + + if(TheData != NULL) + return FALSE; + CFile* TheFile=new CFile; + char* buffer =new char[2048]; + + TRY + { + res=TheFile->Open(lpzFileName,CFile::modeReadWrite,&e); + } + CATCH( CFileException, e ) + { + #ifdef _DEBUG + afxDump << "File " << lpzFileName << " does not exist or cannot be opened\n"; + #endif + } + END_CATCH + + if(e.m_cause==CFileException::none) + { + int numRead=TheFile->Read((void *)buffer,2048); + TheData=new char[numRead+1]; + memset((void*)TheData,'\0',numRead+1); + strncpy(TheData,buffer,numRead); + delete[] buffer; + delete TheFile; + return numRead > 0 ? TRUE:FALSE; + } + delete[] buffer; + delete TheFile; + return FALSE; +} + + +/////////////////////////////////////////////////////////////////////////// +// Desc: Parse a file loaded from disk. +// params: The filename and a list of seperators (default is ,) +// returns:TRUE if all OK else FALSE +/////////////////////////////////////////////////////////////////////////// +BOOL CParseIt::ParseFile(LPCSTR lpzFileName,LPCSTR Sep) +{ + strncpy(Seperator,Sep,9); + if(LoadFile(lpzFileName)) + return Parse(); + return FALSE; +} + + + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.h new file mode 100644 index 0000000..293f4e4 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Parseit.h @@ -0,0 +1,98 @@ +#ifndef __PARSEIT_H_ +#define __PARSEIT_H_ + +//#include "stdafx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// class definition for the ParseField class +/////////////////////////////////////////////////////////////////////////////////// +// this class is just a CString with some assignment and cast operators +// it is used to store a parsed field value and allow the data to be accessed +// thru casting the result to the wanted datatype +// ************************** ALLOWED OPERATIONS ********************************* +// CParseField p; +// p="1234.12" // assignment to LPCSTR +// CStrinf e=(LPCSTR)p;// operator (LPCSTR) +// double d=(double)p; // d=1234.12 operator double +// int n=(int)p; // n=1234 operator int +////////////////////////////////////////////////////////////////////////////////// +class CParseField{ +public: + CParseField() {}; + ~CParseField() {}; + + operator int() { return atoi(TheData);}; + operator long() { return atol(TheData);}; + operator double() { return atof(TheData);}; + operator LPCSTR() { return (LPCSTR) TheData;}; const + CParseField& operator =(LPCSTR s) {TheData=s;return *this;}; + CParseField& operator =(CString& s) {TheData=s;return *this;}; + CParseField& operator =(CParseField& s) {TheData=s.TheData;return *this;}; + +// Implementation +protected: + CString TheData; +}; +/////////////////////////////////////////////////////////////////////////////////// +// END OF CparseField DEFINITION AND CODE ( ALL FUNCTIONS HERE) +/////////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////////// +// class definition for the Parsing class +/////////////////////////////////////////////////////////////////////////////////// +class CParseIt +{ +public: + CParseIt(BOOL Strip=FALSE); + CParseIt(LPCSTR Data,LPCSTR Sep=",",BOOL Strip=FALSE); + ~CParseIt(); + + // use default constructoe then call this function to open and use a file contaimning + // the data + BOOL ParseFile(LPCSTR lpzFileName,LPCSTR Sep=","); +// Attributes +public: +// Operations +protected: + BOOL IsSeperator(char s); + BOOL LoadFile(LPCSTR lpzFileName); +public: + // returns the one based number of fields if 0 there are no fields + int GetNumFields() {return NumFields;}; + // returns the list of seperators + LPCSTR GetSeperator() {return Seperator;}; + // sets the seperator list IE "|,*" + void SetSeperator(LPCSTR Sep) {strncpy(Seperator,Sep,9);}; + // parse a object constructed bt the second constructor (data,sep); + BOOL Parse(); + // parse a object created by the default constructor will call Parse(); + BOOL Parse(LPCSTR Data,LPCSTR Sep=",",BOOL Strip=FALSE); + // returns the 1 based field in a cstring or a string + BOOL GetField(int nFNum,CString& Buff); + BOOL GetField(int nFNum,LPSTR Buff); + // will return the cparsefield object. This can be cast to the desired type + // by (int) (long) (double) (lpcstr) + CParseField GetField(int n); + +// Implementation +public: + void ReSet(); + +protected: + BOOL StripQuotes; + char Seperator[10]; + int NumFields; + CPtrArray TheFields; + LPSTR TheData; + +}; + + + + +#endif diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.cpp new file mode 100644 index 0000000..b8a3225 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.cpp @@ -0,0 +1,801 @@ +// PartsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "PartsDlg.h" +#include "NonClientsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPartsDlg dialog + + +CPartsDlg::CPartsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CPartsDlg::IDD, pParent) +, m_strCurrentVendorID(_T("")) +{ + //{{AFX_DATA_INIT(CPartsDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bAddMode=false; + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Parts dialog"); + rs->SetConnect(m_pApp->strConnectString); + + cbrs=new GZRset("Error: Parts dialog combo box recordset\r\n"); + cbrs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + + + + rs=m_pApp->rsPool->GetRS("CPartsDlg (RS)"); + cbrs=m_pApp->rsPool->GetRS("CPartsDlg (CBRS)"); + rsPrint=m_pApp->rsPool->GetRSPrint("CPartsDlg (rsPrint)"); + + + cfm = new CgzCurrencyFormatter; + m_pstrReturnValue=NULL; + m_strSelectedPart.Empty(); + m_bNoRecord=true; + +} + + +CPartsDlg::~CPartsDlg() +{ + rs->Close(); + cbrs->Close(); + rsPrint->Close(); + delete cfm; +} + +void CPartsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPartsDlg) + DDX_Control(pDX, IDC_LBLMODIFIED, m_lblModified); + DDX_Control(pDX, IDC_LBLPART, m_lblPart); + DDX_Control(pDX, IDC_EDRETAIL, m_edRetail); + DDX_Control(pDX, IDC_EDPARTNUM, m_edPartNumber); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_EDDESCRIPTION, m_edDescription); + DDX_Control(pDX, IDC_EDCOST, m_edCost); + DDX_Control(pDX, IDC_CKACTIVE, m_ckActive); + DDX_Control(pDX, IDC_CBREPLACEDBY, m_cbReplacedBy); + DDX_Control(pDX, IDC_CBPARTS, m_cbParts); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNDELETE, m_btnDelete); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_LBL_VENDORS, m_lblVendors); + DDX_Control(pDX, IDC_CBVENDORS, m_cbVendors); +} + + +BEGIN_MESSAGE_MAP(CPartsDlg, CDialog) + //{{AFX_MSG_MAP(CPartsDlg) + ON_EN_KILLFOCUS(IDC_EDRETAIL, OnKillfocusEdretail) + ON_EN_KILLFOCUS(IDC_EDPARTNUM, OnKillfocusEdpartnum) + ON_EN_KILLFOCUS(IDC_EDNOTES, OnKillfocusEdnotes) + ON_EN_KILLFOCUS(IDC_EDDESCRIPTION, OnKillfocusEddescription) + ON_EN_KILLFOCUS(IDC_EDCOST, OnKillfocusEdcost) + ON_BN_CLICKED(IDC_CKACTIVE, OnCkactive) + ON_CBN_CLOSEUP(IDC_CBREPLACEDBY, OnCloseupCbreplacedby) + ON_CBN_CLOSEUP(IDC_CBPARTS, OnCloseupCbparts) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete) + ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) + ON_BN_CLICKED(IDC_BTNPRINT, OnBtnprint) + //}}AFX_MSG_MAP + ON_STN_CLICKED(IDC_LBL_VENDORS, OnStnClickedLblVendors) + ON_CBN_CLOSEUP(IDC_CBVENDORS, OnCbnCloseupCbvendors) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPartsDlg message handlers +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CPartsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE GZCOMBO CONTROL FIELD +//************************************************************ +bool CPartsDlg::SaveField(CgzCombo *cbControl,CString fldname) +{ + + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + CString str; + long lData; + str=cbControl->GetCurrentRowID(); + if(str.IsEmpty()) return false;//shouldn't happen but... + lData=atol(str); + rs->UpdateField(fldname,&lData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CPartsDlg::SaveField(CButton *ckControl,CString fldname) +{ + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + + +//************************************************ +//UPDATE MODIFIED DATA +//************************************************* +bool CPartsDlg::UpdateModified() +{ + //updates modified by and modified on fields + rs->UpdateField("modifier",&m_pApp->m_lusrID); + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + rs->SaveRecord(); + + + return true; +} + + + +//************************************************************ +//SAVE Currency in an edit CONTROL FIELD +//************************************************************ +bool CPartsDlg::SaveCurrencyField(CEdit *crControl,CString fldname) +{ + if(m_bAddMode || m_bNoRecord) return true;//dont attempt to update + CString str; + COleCurrency crData; + crControl->GetWindowText(str); + if(str.IsEmpty()) + str="0"; + + if(crData.ParseCurrency(str)!=TRUE) + { + AfxMessageBox("Could not interpret your entry in one or more currency fields\r\n" + "I can't save those fields until they are changed."); + return false; + } + rs->UpdateField(fldname,&crData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + + + +void CPartsDlg::OnKillfocusEdretail() +{ + SaveCurrencyField(&m_edRetail,"retail"); +} + +void CPartsDlg::OnKillfocusEdpartnum() +{ + SaveField(&m_edPartNumber,"partnumber",false); + if(!m_bAddMode) + FillList(); + +} + +void CPartsDlg::OnKillfocusEdnotes() +{ + SaveField(&m_edNotes,"notes",true); + +} + +void CPartsDlg::OnKillfocusEddescription() +{ + SaveField(&m_edDescription,"description",true); + if(!m_bAddMode) + FillList(); + +} + +void CPartsDlg::OnKillfocusEdcost() +{ + SaveCurrencyField(&m_edCost,"avgcost"); + +} + +void CPartsDlg::OnCkactive() +{ + SaveField(&m_ckActive,"active"); + +} + +void CPartsDlg::OnCloseupCbreplacedby() +{ + SaveField(&m_cbReplacedBy,"supersededby"); + +} + +void CPartsDlg::OnCbnCloseupCbvendors() +{ + SaveField(&m_cbVendors,"supplier"); + m_strCurrentVendorID=m_cbVendors.GetCurrentRowID(); +} + +//************************************* +void CPartsDlg::OnCloseupCbparts() +{ + //FILL FIELDS + CString strData,q; + bool bData; + COleCurrency crData; + + //added Nov 19th 2000 + COleDateTime dtModified; + + long lData; + strData=m_cbParts.GetCurrentRowID(); + if(strData=="0") + { + ClearFields(); + m_bNoRecord=true; + return; + } + m_bNoRecord=false; + q.Format("SELECT parts.* FROM parts " + "WHERE (((parts.id)=%s));",m_cbParts.GetCurrentRowID()); + + rs->Query(q); + if(rs->IsEmpty()) + { + m_bNoRecord=true; + return; + } + + + //REPLACED BY + rs->FetchField("supersededby",&lData); + strData.Format("%u",lData); + m_cbReplacedBy.Select(strData); + + //ACTIVE + rs->FetchField("active",&bData); + m_ckActive.SetCheck(bData ? TRUE : FALSE); + + //COST + rs->FetchField("avgcost",&crData); + m_edCost.SetWindowText(cfm->Format(crData)); + + //RETAIL + rs->FetchField("retail",&crData); + m_edRetail.SetWindowText(cfm->Format(crData)); + + //DESCRIPTION + rs->FetchField("description",&strData); + m_edDescription.SetWindowText(strData); + + //NOTES + rs->FetchField("notes",&strData); + m_edNotes.SetWindowText(strData); + + //PART NUMBER + rs->FetchField("partnumber",&strData); + m_edPartNumber.SetWindowText(strData); + + //added Nov 19th 2000 + //LAST MODIFIED + rs->FetchField("modified",&dtModified); + m_lblModified.SetWindowText(dtModified.Format()); + + rs->FetchField("supplier",&lData); + m_strCurrentVendorID.Format("%u",lData); + m_cbVendors.Select(lData); + + + + + m_strSelectedPart=m_cbParts.GetCurrentRowID(); + + +} + + +//************************************* +void CPartsDlg::OnBtndone() +{ + if(m_pstrReturnValue!=NULL) + *m_pstrReturnValue=m_strSelectedPart; + CDialog::OnOK(); +} + +//*********************************** +void CPartsDlg::OnBtndelete() +{ + CString q; + + if(m_bAddMode) + { + m_bAddMode=false; + m_lblPart.ShowWindow(TRUE); + m_cbParts.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_btnAdd.SetWindowText("Add"); + m_btnDone.ShowWindow(TRUE); + m_strSelectedPart.Empty(); + FillList(); + return; + + } + + //DELETE..... + + //can't delete the built in sn... + if(m_strSelectedPart=="0") + { + + return; + } + + //check if unused and deletable + //IN PMPARTS??? + q.Format("SELECT pmparts.partnum FROM pmparts " + "WHERE (((pmparts.partnum)=%s));",m_strSelectedPart); + cbrs->Query(q); + if(!cbrs->IsEmpty()) + { + AfxMessageBox("DATA INTEGRITY PROTECTION:\r\n" + "This part appears in one or more\r\n" + "Preventive Maintenance schedules\r\n" + "and cannot be deleted at this time."); + return; + + + } + + + //IN WOPARTS??? + q.Format("SELECT woparts.partnum FROM woparts " + "WHERE (((woparts.partnum)=%s));",m_strSelectedPart); + cbrs->Query(q); + if(!cbrs->IsEmpty()) + { + AfxMessageBox("DATA INTEGRITY PROTECTION:\r\n" + "This part appears in one or more workorders\r\n" + "and cannot be deleted at this time."); + return; + + + } + + //IN PARTS as a supersede??? + q.Format("SELECT parts.supersededby FROM parts " + "WHERE ((( parts.supersededby)=%s));",m_strSelectedPart); + cbrs->Query(q); + if(!cbrs->IsEmpty()) + { + AfxMessageBox("DATA INTEGRITY PROTECTION:\r\n" + "This part appears in one or more other part\r\n" + "records as a replacement part number\r\n" + "and cannot be deleted at this time."); + return; + + + } + + + + if(AfxMessageBox("Permanently delete part?",MB_YESNO)==IDYES) + { + q.Format("DELETE parts.*, parts.id " + "FROM parts WHERE (((parts.id)=%s));",m_strSelectedPart); + rs->Ex(q); + m_strSelectedPart=""; + FillList(); + } + + + +} + + +//***************************************************** +void CPartsDlg::OnBtnadd() +{ + CString strData,newpn; + bool bData; + long lData; + COleCurrency crCost,crRetail; + + if(!m_bAddMode) + { //go add mode + DisableAll(false); + m_bAddMode=true; + m_btnDelete.SetWindowText("CANCEL"); + m_btnAdd.SetWindowText("SAVE"); + m_btnDone.ShowWindow(FALSE); + m_lblPart.ShowWindow(FALSE); + m_cbParts.ShowWindow(FALSE); + ClearFields(); + return; + + + } + else + {//SAVE Record + + + m_edPartNumber.GetWindowText(newpn); + if(newpn.IsEmpty()) + { + AfxMessageBox("A part number is required to proceed"); + return; + } + + + + //SCAN CURRENCY FIELDS + + //COST + m_edCost.GetWindowText(strData); + if(strData.IsEmpty()) + strData="0"; + + if(crCost.ParseCurrency(strData)!=TRUE) + { + AfxMessageBox("I don't understand your entry in the cost field\r\n" + "Please change it to a valid currency value."); + return; + } + + //RETAIL + m_edRetail.GetWindowText(strData); + if(strData.IsEmpty()) + strData="0"; + + if(crRetail.ParseCurrency(strData)!=TRUE) + { + AfxMessageBox("I don't understand your entry in the retail price field\r\n" + "Please change it to a valid currency value."); + return; + } + + //hack as keeps saying recordset is not open + rs->Query("SELECT parts.* from parts WHERE parts.id = 0;"); + + if(!rs->AddNewRecord()) + return; + + //SAVE PARTNUMBER + rs->UpdateField("partnumber",&newpn); + + + //SAVE CREATOR INFO + COleDateTime dtData; + rs->UpdateField("creator",&m_pApp->m_lusrID); + rs->UpdateField("modifier",&m_pApp->m_lusrID); + + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("created",&dtData); + rs->UpdateField("modified",&dtData); + + //REPLACED BY + strData=m_cbReplacedBy.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("supersededby",&lData); + + //Vendor + strData=m_cbVendors.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("supplier",&lData); + + //ACTIVE + bData=(m_ckActive.GetCheck() ? true : false); + rs->UpdateField("active",&bData); + + //COST / RETAIL + rs->UpdateField("avgcost",&crCost); + rs->UpdateField("retail",&crRetail); + + //DESCRIPTION + m_edDescription.GetWindowText(strData); + rs->UpdateField("description",&strData); + + //NOTES + m_edNotes.GetWindowText(strData); + rs->UpdateField("notes",&strData); + + //ATTEMPT TO SAVE + if(!rs->SaveRecord()) + return; + + m_bAddMode=false; + m_lblPart.ShowWindow(TRUE); + m_cbParts.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_btnAdd.SetWindowText("Add"); + m_btnDone.ShowWindow(TRUE); + //hack as keeps saying recordset is not open + rs->Query("SELECT parts.* from parts;"); + + FillList(); + //m_cbParts.SelectString(-1,newpn); + //OnCloseupCbparts(); + return; + } + +} + + + + +//**************************************************** + +//Fill list box with items +void CPartsDlg::FillList() +{ + + CString strData; + CString strIndex; + long lData; + m_cbParts.Clear(); + m_cbReplacedBy.Clear(); + + + strData="< No replacement >"; + m_cbReplacedBy.AddRow(strData,strIndex); + + cbrs->Query("SELECT parts.id, [partnumber] & \" - \" " + "& [description] AS name FROM parts " + "ORDER BY parts.partnumber;"); + + + if(cbrs->IsEmpty()) + { + DisableAll(true); + return; + } + + + cbrs->MoveFirst(); + + do + { + cbrs->FetchField("name",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbParts.AddRow(strData,strIndex); + m_cbReplacedBy.AddRow(strData,strIndex); + }while(cbrs->MoveForward()); + + + //pretend user has selected so that other fields get filled in + if(m_strSelectedPart.IsEmpty()) //first time in + { + m_cbParts.SetCurSel(0); + m_strSelectedPart=m_cbParts.GetCurrentRowID(); + + } + else//something valid was selected before so stick with it + m_cbParts.Select(m_strSelectedPart); + m_cbReplacedBy.Select("0"); + + OnCloseupCbparts(); +} + +BOOL CPartsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + + //FUTURE: Add a search by description ability + + //make a "hyperlink" + m_lblVendors.SetTextColor(RGB(0,0,255)); + m_lblVendors.SetFontUnderline(TRUE); + m_lblVendors.SetLink(TRUE); + m_lblVendors.SetLinkCursor(m_pApp->hcHand); + //empty url means it will not launch explorer + //and can be used as a button instead + m_lblVendors.SetLinkURL(""); + + //added 02/06/2002 + m_edDescription.SetLimitText(50); + m_edPartNumber.SetLimitText(50); + FillList(); + FillVendorList(); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CPartsDlg::ClearFields() +{ + m_cbReplacedBy.Select("0"); + m_ckActive.SetCheck(TRUE); + m_edCost.SetWindowText("0"); + m_edDescription.SetWindowText(""); + m_edNotes.SetWindowText(""); + m_edPartNumber.SetWindowText(""); + m_edRetail.SetWindowText("0"); +} + +void CPartsDlg::SetReturnValue(CString *str) +{ + m_pstrReturnValue=str; +} + +void CPartsDlg::DisableAll(bool disable) +{ + BOOL e=disable ? FALSE : TRUE; + m_btnDelete.EnableWindow(e); + m_cbParts.EnableWindow(e); + m_cbReplacedBy.EnableWindow(e); + m_ckActive.EnableWindow(e); + m_edCost.EnableWindow(e); + m_edDescription.EnableWindow(e); + m_edNotes.EnableWindow(e); + m_edPartNumber.EnableWindow(e); + m_edRetail.EnableWindow(e); + + +} + +void CPartsDlg::Security() +{ + + //m_bReadOnly=false; + int x=m_pApp->Allowed(RPARTS,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + // m_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_cbReplacedBy.EnableWindow(FALSE); + m_ckActive.EnableWindow(FALSE); + m_edCost.SetReadOnly(TRUE); + m_edDescription.SetReadOnly(TRUE); + m_edNotes.SetReadOnly(TRUE); + m_edPartNumber.SetReadOnly(TRUE); + m_edRetail.SetReadOnly(TRUE); + + + + } +} + +void CPartsDlg::OnBtnprint() +{ + CString q,strReport; + + + + q="SELECT parts.* FROM parts ORDER BY parts.partnumber;"; + + + //dont allow this to creep into a release build +#ifdef _DEBUG + // m_pApp->ShowStuff(q); +#endif + + rsPrint->Query(q); + + + if(!rsPrint->IsEmpty()) + { + +#ifdef _DEBUG + m_pApp->CreateTTX("parts.ttx",rsPrint->RecordSetPointer()); +#endif + + m_pApp->PrintCMReportRDC("Parts",rsPrint->RecordSetPointer()); + + } + + else + { + AfxMessageBox("There is no data to print!"); + + } + + rsPrint->Close(); + +} + +void CPartsDlg::OnOK() +{} + + +void CPartsDlg::OnStnClickedLblVendors() +{ + CNonClientsDlg d; + + CString strTempVendor=m_strCurrentVendorID; + if(strTempVendor=="0") strTempVendor.Empty(); + + long ltype=3;//manufacturers suppliers + d.SetType(<ype); + d.m_strSelectedContact=strTempVendor; + d.m_pstrReturnValue=&strTempVendor; + //&m_strCurrentVendorID; + d.DoModal(); + FillVendorList(); +} + +void CPartsDlg::FillVendorList(void) +{ + CString q,strData,strIndex; + long lData; + m_cbVendors.Clear(); + //default, no selection + m_cbVendors.AddRow(" ","0"); + + q.Format("SELECT nonclients.*, nonclienttypes.description AS LISTNAME " + "FROM nonclients LEFT JOIN nonclienttypes ON " + "nonclients.type = nonclienttypes.id " + "WHERE (((nonclients.type)=3)) " + "ORDER BY nonclients.company_person;"); + if(!cbrs->QueryReadOnly(q)) return; + //v1.9.4.4 change from a return to just skip over if no records + //so that the selection will take place of the N/A. default. + if(!cbrs->IsEmpty()) + { + do{ + cbrs->FetchField("company_person",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbVendors.AddRow(strData,strIndex); + + }while(cbrs->MoveForward()); + } + //default on empty (constructed) is zero + if(m_strCurrentVendorID.IsEmpty()) m_strCurrentVendorID="0"; + + m_cbVendors.Select(m_strCurrentVendorID); + +} + + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.h new file mode 100644 index 0000000..bf9ce61 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PartsDlg.h @@ -0,0 +1,105 @@ +#if !defined(AFX_PARTSDLG_H__A8498061_28E8_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PARTSDLG_H__A8498061_28E8_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PartsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPartsDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "gzCurrencyFormatter.h" +#include "label.h" +#include "afxwin.h" + +class CPartsDlg : public CDialog +{ +// Construction +public: + void Security(); + void DisableAll(bool disable); + void SetReturnValue(CString * str); + void ClearFields(); + void FillList(); + CPartsDlg(CWnd* pParent = NULL); // standard constructor + ~CPartsDlg(); + + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool SaveCurrencyField(CEdit *crControl,CString fldname); + bool SaveField(CgzCombo* cbControl,CString fldname); + bool SaveField(CButton* ckControl,CString fldname); + bool UpdateModified(); + //------------------------------- + CSpApp* m_pApp; + CgzCurrencyFormatter* cfm; + GZRset* rs; + GZRset* rsPrint; + GZRset* cbrs; + CString * m_pstrReturnValue; + bool m_bAddMode; + bool m_bNoRecord; + CString m_strSelectedPart; +// Dialog Data + //{{AFX_DATA(CPartsDlg) + enum { IDD = IDD_PARTS }; + CStatic m_lblModified; + CStatic m_lblPart; + CEdit m_edRetail; + CEdit m_edPartNumber; + CEdit m_edNotes; + CEdit m_edDescription; + CEdit m_edCost; + CButton m_ckActive; + CgzCombo m_cbReplacedBy; + CgzCombo m_cbParts; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPartsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CPartsDlg) + afx_msg void OnKillfocusEdretail(); + afx_msg void OnKillfocusEdpartnum(); + afx_msg void OnKillfocusEdnotes(); + afx_msg void OnKillfocusEddescription(); + afx_msg void OnKillfocusEdcost(); + afx_msg void OnCkactive(); + afx_msg void OnCloseupCbreplacedby(); + afx_msg void OnCloseupCbparts(); + afx_msg void OnBtndone(); + afx_msg void OnBtndelete(); + afx_msg void OnBtnadd(); + virtual BOOL OnInitDialog(); + afx_msg void OnBtnprint(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CLabel m_lblVendors; + CgzCombo m_cbVendors; + afx_msg void OnStnClickedLblVendors(); + void FillVendorList(void); + CString m_strCurrentVendorID; + afx_msg void OnCbnCloseupCbvendors(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PARTSDLG_H__A8498061_28E8_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.cpp new file mode 100644 index 0000000..a83ee8d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.cpp @@ -0,0 +1,38 @@ +// CPerfTimer - a simple Win32 performance counter wrapper +// by Dean Wyant dwyant@mindspring.com + +#include "stdafx.h" +#include "PerfTimer.h" + +// Declare and initialize static member vars that get set only once and never change +__int64 CPerfTimer::m_Freq = 0; +__int64 CPerfTimer::m_Adjust = 0; + +// All functions defined inline for speed. After all, the performance counter is +// supposed to be able to time very short events fairly accurately. + + + +BOOL CPerfTimer::IsSupported() +{ // Returns FALSE if performance counter not supported. + // Call after constructing at least one CPerfTimer + return (m_Freq > 1); +} + +const double CPerfTimer::Resolution() +{ // Returns timer resolution in seconds + return 1.0/(double)m_Freq; +} + +const double CPerfTimer::Resolutionms() +{ // Returns timer resolution in milliseconds + return 1000.0/(double)m_Freq; +} + +const double CPerfTimer::Resolutionus() +{ // Returns timer resolution in microseconds + return 1000000.0/(double)m_Freq; +} + + + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.h new file mode 100644 index 0000000..bbd2f9c --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/PerfTimer.h @@ -0,0 +1,403 @@ +// CPerfTimer - a simple Win32 performance counter wrapper +// by Dean Wyant dwyant@mindspring.com + +/* + + This class is simple to use. Just declare a variable(s) as type CPerfTimer, + call Start() to start timimg and call Stop() to stop timimg. You can pause a + timer by calling Stop() and then you can call Start() to resume. Retrieve the + elapsed time by calling an Elapsed..() function. Assignment, addition, + subtraction and comparison are supported. There are a few information calls + available also. All calls except Start and Stop can be performed on a timer + without stopping it. + +*/ + +#ifndef __PERFTIMER_H__ +#define __PERFTIMER_H__ + +class CPerfTimer +{ +public: + CPerfTimer(BOOL bStart = FALSE) {Init(bStart);} + + CPerfTimer(const CPerfTimer& Src); + + virtual ~CPerfTimer() {;} + + void Start(BOOL bReset = FALSE); // Start from current value or optionally from 0 + void Stop(); // Stop timing. Use Start afterwards to continue. + + BOOL IsRunning(); // Returns FALSE if stopped. + + BOOL IsSupported(); // Returns FALSE if performance counter not supported. + // Call after constructing at least one CPerfTimer + + const double Resolution(); // Returns timer resolution in seconds + const double Resolutionms(); // Returns timer resolution in milliseconds + const double Resolutionus(); // Returns timer resolution in microseconds + + const double Elapsed(); // Returns elapsed time in seconds + const double Elapsedms(); // Returns elapsed time in milliseconds + const double Elapsedus(); // Returns elapsed time in microseconds + + const CPerfTimer& operator=(const CPerfTimer& Src); // Assignment operator + + // Math operators + CPerfTimer operator+(const CPerfTimer& Src) const; + CPerfTimer operator-(const CPerfTimer& Src) const; + const CPerfTimer& operator+=(const CPerfTimer& Src); + const CPerfTimer& operator-=(const CPerfTimer& Src); + // For time in seconds + CPerfTimer operator+(const double Secs) const; + CPerfTimer operator-(const double Secs) const; + const CPerfTimer& operator+=(const double Secs); + const CPerfTimer& operator-=(const double Secs); + + // Boolean comparison operators + BOOL operator<(const CPerfTimer& Src); + BOOL operator>(const CPerfTimer& Src); + BOOL operator<=(const CPerfTimer& Src); + BOOL operator>=(const CPerfTimer& Src); + // For time in seconds + BOOL operator<(const double Secs); + BOOL operator>(const double Secs); + BOOL operator<=(const double Secs); + BOOL operator>=(const double Secs); + + virtual void Lock() const {;} // Override for thread safe operation + virtual void Unlock() const {;} // Override for thread safe operation +protected: + void Init(BOOL bStart); + void Copy(const CPerfTimer& Src); + +private: + __int64 m_Start; + static __int64 m_Freq; // does not change while system is running + static __int64 m_Adjust; // Adjustment time it takes to Start and Stop +}; + +class CPerfTimerT : public CPerfTimer +{ // You only need to use types of this class if a timer is going to be shared between threads +public: + CPerfTimerT(BOOL bStart = FALSE) + { + m_hMutex = CreateMutex(NULL,FALSE,""); + Init(bStart); + } + + CPerfTimerT(const CPerfTimerT& Src) + { + m_hMutex = CreateMutex(NULL,FALSE,""); + Copy(Src); + } + + CPerfTimerT(const CPerfTimer& Src) + { + m_hMutex = CreateMutex(NULL,FALSE,""); + Copy(Src); + } + + virtual ~CPerfTimerT() + { CloseHandle(m_hMutex); } + + const CPerfTimerT& operator=(const CPerfTimerT& Src) // Assignment operator + { + Copy(Src); + return *this; + } + + virtual void Lock() const { WaitForSingleObject(m_hMutex,10000); } + virtual void Unlock() const { ReleaseMutex(m_hMutex); } +private: + HANDLE m_hMutex; +}; + +inline void CPerfTimer::Init(BOOL bStart) +{ + if (!m_Freq) + { // Initialization should only run once + QueryPerformanceFrequency((LARGE_INTEGER *)&m_Freq); + if (!m_Freq) + m_Freq = 1; // Timer will be useless but will not cause divide by zero + m_Start = 0; + m_Adjust = 0; + Start(); // Time a Stop + Stop(); + m_Adjust = m_Start; + } + // This is the only part that normally runs + m_Start = 0; + if (bStart) + Start(); +} + +inline CPerfTimer::CPerfTimer(const CPerfTimer& Src) +{ + Copy(Src); +} + +inline void CPerfTimer::Copy(const CPerfTimer& Src) +{ + if (&Src == this) + return; // avoid deadlock if someone tries to copy it to itself + Src.Lock(); + Lock(); + m_Start = Src.m_Start; + Unlock(); + Src.Unlock(); +} + +inline void CPerfTimer::Start(BOOL bReset) +{ // Start from current value or optionally from 0 + __int64 i; + QueryPerformanceCounter((LARGE_INTEGER *)&i); + Lock(); + if ((!bReset) && (m_Start < 0)) + m_Start += i; // We are starting with an accumulated time + else + m_Start = i; // Starting from 0 + Unlock(); +} + +inline void CPerfTimer::Stop() +{ // Stop timing. Use Start afterwards to continue + Lock(); + if (m_Start <= 0) + { + Unlock(); + return; // Was not running + } + __int64 i; + QueryPerformanceCounter((LARGE_INTEGER *)&i); + m_Start += -i; // Stopped timer keeps elapsed timer ticks as a negative + if (m_Start < m_Adjust) // Do not overflow + m_Start -= m_Adjust; // Adjust for time timer code takes to run + else + m_Start = 0; // Stop must have been called directly after Start + Unlock(); +} + +inline BOOL CPerfTimer::IsRunning() +{ // Returns FALSE if stopped. + Lock(); + BOOL bRet = (m_Start > 0); // When < 0, holds elpased clicks + Unlock(); + return bRet; +} + inline const double CPerfTimer::Elapsed() +{ // Returns elapsed time in seconds + CPerfTimer Result(*this); + Result.Stop(); + return (double)(-Result.m_Start)/(double)m_Freq; +} + +inline const double CPerfTimer::Elapsedms() +{ // Returns elapsed time in milliseconds + CPerfTimer Result(*this); + Result.Stop(); + return (-Result.m_Start*1000.0)/(double)m_Freq; +} + +inline const double CPerfTimer::Elapsedus() +{ // Returns elapsed time in microseconds + CPerfTimer Result(*this); + Result.Stop(); + return (-Result.m_Start * 1000000.0)/(double)m_Freq; +} + + +// Assignment operator +inline const CPerfTimer& CPerfTimer::operator=(const CPerfTimer& Src) +{ + Copy(Src); + return *this; +} + + +// Math operators +inline CPerfTimer CPerfTimer::operator+(const CPerfTimer& Src) const +{ + CPerfTimer Result(*this); + Result += Src; + return Result; +} + +inline CPerfTimer CPerfTimer::operator-(const CPerfTimer& Src) const +{ + CPerfTimer Result(*this); + Result -= Src; + return Result; +} + +inline const CPerfTimer& CPerfTimer::operator+=(const CPerfTimer& Src) +{ + CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not stopped + SrcStop.Stop(); + Lock(); + m_Start += SrcStop.m_Start; + Unlock(); + return *this; +} + +inline const CPerfTimer& CPerfTimer::operator-=(const CPerfTimer& Src) +{ + CPerfTimer SrcStop(Src); // Temp is necessary in case Src is not stopped + SrcStop.Stop(); + Lock(); + m_Start -= SrcStop.m_Start; + Unlock(); + return *this; +} + +// For time in seconds +inline CPerfTimer CPerfTimer::operator+(const double Secs) const +{ + CPerfTimer Result(*this); + Result += Secs; + return Result; +} + +inline CPerfTimer CPerfTimer::operator-(const double Secs) const +{ + CPerfTimer Result(*this); + Result += Secs; + return Result; +} + +inline const CPerfTimer& CPerfTimer::operator+=(const double Secs) +{ + Lock(); + m_Start -= (__int64)(Secs*(double)m_Freq); + Unlock(); + return *this; +} + +inline const CPerfTimer& CPerfTimer::operator-=(const double Secs) +{ + Lock(); + m_Start += (__int64)(Secs*(double)m_Freq); + Unlock(); + return *this; +} + + + +// Boolean comparison operators +inline BOOL CPerfTimer::operator<(const CPerfTimer& Src) +{ + BOOL bRet; + CPerfTimer Temp(Src); + Lock(); + if (m_Start <= 0) + { + Temp.Stop(); + bRet = (m_Start > Temp.m_Start); + Unlock(); + return bRet; + } + else + if (Temp.m_Start > 0) + { + bRet = (m_Start < Temp.m_Start); + Unlock(); + return bRet; + } + else + { + Unlock(); + CPerfTimer ThisStop(*this); + ThisStop.Stop(); + return (ThisStop.m_Start > Temp.m_Start); + } +} + +inline BOOL CPerfTimer::operator>(const CPerfTimer& Src) +{ + BOOL bRet; + CPerfTimer Temp(Src); + Lock(); + if (m_Start <= 0) + { + Temp.Stop(); + bRet = (m_Start < Temp.m_Start); + Unlock(); + return bRet; + } + else + if (Temp.m_Start > 0) + { + bRet = (m_Start > Temp.m_Start); + Unlock(); + return bRet; + } + else + { + Unlock(); + CPerfTimer ThisStop(*this); + ThisStop.Stop(); + return (ThisStop.m_Start < Temp.m_Start); + } +} + +inline BOOL CPerfTimer::operator<=(const CPerfTimer& Src) +{ + return !(*this > Src); +} + +inline BOOL CPerfTimer::operator>=(const CPerfTimer& Src) +{ + return !(*this < Src); +} + +// For time in seconds +inline BOOL CPerfTimer::operator<(const double Secs) +{ + BOOL bRet; + Lock(); + if (m_Start <= 0) + { + bRet = (m_Start > (__int64)(-Secs*(double)m_Freq)); + Unlock(); + return bRet; + } + else + { + Unlock(); + CPerfTimer ThisStop(*this); + ThisStop.Stop(); + return (ThisStop.m_Start > (__int64)(-Secs*(double)m_Freq)); + } +} + +inline BOOL CPerfTimer::operator>(const double Secs) +{ + BOOL bRet; + Lock(); + if (m_Start <= 0) + { + bRet = (m_Start < (__int64)(-Secs*(double)m_Freq)); + Unlock(); + return bRet; + } + else + { + Unlock(); + CPerfTimer ThisStop(*this); + ThisStop.Stop(); + return (ThisStop.m_Start < (__int64)(-Secs*(double)m_Freq)); + } +} + +inline BOOL CPerfTimer::operator<=(const double Secs) +{ + return !(*this > Secs); +} + +inline BOOL CPerfTimer::operator>=(const double Secs) +{ + return !(*this < Secs); +} + + +#endif //__PERFTIMER_H__ \ No newline at end of file diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.cpp new file mode 100644 index 0000000..202333a --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.cpp @@ -0,0 +1,342 @@ +// ProbStatDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ProbStatDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CProbStatDlg dialog + + +CProbStatDlg::CProbStatDlg(CWnd* pParent /*=NULL*/) + : CDialog(CProbStatDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CProbStatDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Problem status dialog"); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + rs=m_pApp->rsPool->GetRS("CProbStatDlg"); + m_bAddMode=false; +} + + +void CProbStatDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CProbStatDlg) + DDX_Control(pDX, IDC_BTNCOLOR, m_btnColor); + DDX_Control(pDX, IDC_LBLSAMPLE, m_lblSample); + DDX_Control(pDX, IDC_LBLSTATUSLIST, m_lblStatusList); + DDX_Control(pDX, IDC_EDSTATUSITEM, m_edStatusItem); + DDX_Control(pDX, IDC_CBSTATUSITEMLIST, m_cbStatusItemsList); + DDX_Control(pDX, IDC_BTNDONE, m_BtnDone); + DDX_Control(pDX, IDC_BTNDELETE, m_BtnDelete); + DDX_Control(pDX, IDC_BTNADD, m_BtnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CProbStatDlg, CDialog) + //{{AFX_MSG_MAP(CProbStatDlg) + ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) + ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_CBN_CLOSEUP(IDC_CBSTATUSITEMLIST, OnCloseupCbstatusitemlist) + ON_BN_CLICKED(IDC_BTNCOLOR, OnBtncolor) + ON_EN_KILLFOCUS(IDC_EDSTATUSITEM, OnKillfocusEdstatusitem) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CProbStatDlg message handlers + +void CProbStatDlg::OnBtnadd() +{ + CString q,text; + if(m_bAddMode) + {//save + m_edStatusItem.GetWindowText(text); + if(text.IsEmpty()) + { + AfxMessageBox("You haven't entered any text, click on Cancel if don't want to add an item"); + m_edStatusItem.SetFocus(); + return; + } + q.Format("SELECT probstat.notes " + "FROM probstat WHERE (((probstat.notes)=\"%s\"));",text); + rs->Query(q); + if(!rs->IsEmpty()) + { + AfxMessageBox("There is already an item with this name"); + m_edStatusItem.SetFocus(); + return; + } + else + { + q.Format("INSERT INTO probstat ( notes, red, green, blue ) " + "SELECT \"%s\", %u, %u, %u;",text,m_lRed,m_lGreen,m_lBlue); + rs->Ex(q); + rs->Close(); + } + + + m_cbStatusItemsList.ShowWindow(TRUE); + m_lblStatusList.ShowWindow(TRUE); + m_btnColor.ShowWindow(TRUE); + m_lblSample.ShowWindow(TRUE); + m_BtnDelete.SetWindowText("Delete"); + m_BtnAdd.SetWindowText("Add"); + m_BtnDone.ShowWindow(TRUE); + m_edStatusItem.SetFocus(); + FillList(); + m_bAddMode=false; + + + } + else + {//go to add mode + m_edStatusItem.SetWindowText(""); + m_btnColor.ShowWindow(FALSE); + m_lblSample.ShowWindow(FALSE); + m_cbStatusItemsList.ShowWindow(FALSE); + m_lblStatusList.ShowWindow(FALSE); + m_BtnDelete.SetWindowText("Cancel"); + m_BtnAdd.SetWindowText("Save"); + m_BtnDone.ShowWindow(FALSE); + m_edStatusItem.SetFocus(); + m_bAddMode=true; + } + +} + + + +void CProbStatDlg::OnBtndelete() +{ + CString q; + long count; + + if(m_bAddMode) + { + + m_cbStatusItemsList.ShowWindow(TRUE); + m_lblStatusList.ShowWindow(TRUE); + m_BtnDelete.SetWindowText("Delete"); + m_BtnAdd.SetWindowText("Add"); + m_BtnDone.ShowWindow(TRUE); + m_edStatusItem.SetFocus(); + FillList(); + m_bAddMode=false; + + + } + else + { + if(m_cbStatusItemsList.GetCurrentRowID()=="1") + { + AfxMessageBox("You can't delete this item"); + return; + } + q.Format("SELECT Count(probs.id) AS itemcount " + "FROM probs INNER JOIN probstat ON probs.status = probstat.id " + "GROUP BY probstat.id " + "HAVING (((probstat.id)=%s));",m_cbStatusItemsList.GetCurrentRowID()); + //m_pApp->ShowStuff(q); + rs->Query(q); + + if(!rs->IsEmpty()) + { + rs->FetchField("itemcount",&count); + //v1.9.4.5 changed %s below to %u was causing a crash + q.Format("You can't delete this item.\r\n" + "It's in use on %u workorders in the system.",count); + AfxMessageBox(q); + return; + + } + else + { + if(AfxMessageBox("Delete this status item?",MB_YESNO)==IDYES) + { + q.Format("DELETE probstat.id, probstat.* " + "FROM probstat WHERE (((probstat.id)=%s));",m_cbStatusItemsList.GetCurrentRowID()); + rs->Ex(q); + + FillList(); + + } + + + } + + + } +} + +void CProbStatDlg::OnBtndone() +{ + // TODO: Add your control notification handler code here + CDialog::OnOK(); +} + +void CProbStatDlg::OnOK() +{ + // TODO: Add extra validation here + + +} + +CProbStatDlg::~CProbStatDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CProbStatDlg::FillList() +{ + + CString q,strData,strIndex; + long lData; +//FILL STATUS LIST + m_cbStatusItemsList.Clear(); + rs->Query("SELECT probstat.id, probstat.notes FROM probstat ORDER BY probstat.id;"); + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("notes",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbStatusItemsList.AddRow(strData,strIndex); + }while(rs->MoveForward()); + m_cbStatusItemsList.SetCurSel(0); + OnCloseupCbstatusitemlist(); + } + +} + +BOOL CProbStatDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + m_lblSample.SetFontName("Arial"); + m_lblSample.SetTextColor(RGB(0,0,0)); + m_lblSample.SetBkColor(RGB(255,255,255)); + m_lblSample.SetFontSize(22); + m_lblSample.SetFontBold(TRUE); + + FillList(); + // TODO: Add extra initialization here + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CProbStatDlg::OnCloseupCbstatusitemlist() +{ +CString q; + m_edStatusItem.SetWindowText(m_cbStatusItemsList.GetCurrentRowText()); + + q.Format("SELECT probstat.* FROM probstat " + "WHERE (((probstat.id)=%s));",m_cbStatusItemsList.GetCurrentRowID()); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + rs->FetchField("red",&m_lRed); + rs->FetchField("green",&m_lGreen); + rs->FetchField("blue",&m_lBlue); + + } + else + { + m_lRed=0; + m_lGreen=0; + m_lBlue=0; + } + +m_lblSample.SetTextColor(RGB(m_lRed,m_lGreen,m_lBlue)); + + +//CString id; +//id=m_cbStatusItemsList.GetCurrentRowID(); + + +} + + +//COLOR CHANGE? +void CProbStatDlg::OnBtncolor() +{ + CString q; + + CColorDialog dlg(RGB(255,0,0),CC_SOLIDCOLOR/*|CC_PREVENTFULLOPEN*/); + +if (dlg.DoModal() == IDOK) +{ + COLORREF color = dlg.GetColor(); + + m_lRed=GetRValue(color); + m_lGreen=GetGValue(color); + m_lBlue=GetBValue(color); + + + q.Format("UPDATE probstat SET probstat.red = %u, probstat.green = %u, probstat.blue = %u " + "WHERE (((probstat.id)=%s));", + m_lRed, m_lGreen, m_lBlue, + m_cbStatusItemsList.GetCurrentRowID()); + + rs->Ex(q); + + m_lblSample.SetTextColor(RGB(m_lRed,m_lGreen,m_lBlue)); +} + + +} + +void CProbStatDlg::OnKillfocusEdstatusitem() +{ + CString text,q; + + if(m_bAddMode || m_edStatusItem.GetModify()==FALSE) return; + m_edStatusItem.GetWindowText(text); + if(text.IsEmpty()) + { + AfxMessageBox("You haven't entered any text, this field can not be blank"); + m_edStatusItem.Undo(); + m_edStatusItem.SetFocus(); + return; + } + q.Format("SELECT probstat.notes " + "FROM probstat WHERE (((probstat.notes)=\"%s\"));",text); + rs->Query(q); + if(!rs->IsEmpty()) + { + AfxMessageBox("There is already an item with this name"); + m_edStatusItem.SetFocus(); + return; + } + else + { + q.Format("UPDATE probstat SET probstat.notes = \"%s\" " + "WHERE (((probstat.id)=%s));", text, m_cbStatusItemsList.GetCurrentRowID()); + + rs->Ex(q); + rs->Close(); + } + + m_edStatusItem.SetModify(FALSE); + FillList(); + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.h new file mode 100644 index 0000000..cccfcf2 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProbStatDlg.h @@ -0,0 +1,70 @@ +#if !defined(AFX_PROBSTATDLG_H__D9199E01_7CD5_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PROBSTATDLG_H__D9199E01_7CD5_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ProbStatDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CProbStatDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +class CProbStatDlg : public CDialog +{ +// Construction +public: + bool m_bAddMode; + void FillList(); + ~CProbStatDlg(); + CProbStatDlg(CWnd* pParent = NULL); // standard constructor +GZRset* rs; + CSpApp* m_pApp; +// Dialog Data + //{{AFX_DATA(CProbStatDlg) + enum { IDD = IDD_STATUS_DLG }; + CButton m_btnColor; + CLabel m_lblSample; + CStatic m_lblStatusList; + CEdit m_edStatusItem; + CgzCombo m_cbStatusItemsList; + CButton m_BtnDone; + CButton m_BtnDelete; + CButton m_BtnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CProbStatDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CProbStatDlg) + afx_msg void OnBtnadd(); + afx_msg void OnBtndelete(); + afx_msg void OnBtndone(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnCloseupCbstatusitemlist(); + afx_msg void OnBtncolor(); + afx_msg void OnKillfocusEdstatusitem(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + long m_lRed; + long m_lGreen; + long m_lBlue; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PROBSTATDLG_H__D9199E01_7CD5_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.cpp new file mode 100644 index 0000000..0104cf3 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.cpp @@ -0,0 +1,476 @@ +// ProjectsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ProjectsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CProjectsDlg dialog + + +CProjectsDlg::CProjectsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CProjectsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CProjectsDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bAddMode=false; + + m_pstrSelectedProject=NULL; + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Projects entry screen"); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CProjectsDlg"); +} + + +CProjectsDlg::~CProjectsDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CProjectsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CProjectsDlg) + DDX_Control(pDX, IDC_LIST_LABEL, m_lblList); + DDX_Control(pDX, IDC_PROJECTS_COMBO, m_cbList); + DDX_Control(pDX, IDC_PROJECT_NAME, m_edName); + DDX_Control(pDX, IDC_PROJECT_DESCRIPTION, m_edDescription); + DDX_Control(pDX, IDC_DONE, m_btnDone); + DDX_Control(pDX, IDC_DELETE, m_btnDelete); + DDX_Control(pDX, IDC_ADD, m_btnAdd); + DDX_Control(pDX, IDC_ACTIVE, m_ckActive); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CProjectsDlg, CDialog) + //{{AFX_MSG_MAP(CProjectsDlg) + ON_BN_CLICKED(IDC_ACTIVE, OnActive) + ON_BN_CLICKED(IDC_ADD, OnAdd) + ON_BN_CLICKED(IDC_DELETE, OnDelete) + ON_BN_CLICKED(IDC_DONE, OnDone) + ON_EN_KILLFOCUS(IDC_PROJECT_DESCRIPTION, OnKillfocusProjectDescription) + ON_EN_KILLFOCUS(IDC_PROJECT_NAME, OnKillfocusProjectName) + ON_CBN_CLOSEUP(IDC_PROJECTS_COMBO, OnCloseupProjectsCombo) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CProjectsDlg message handlers + + +BOOL CProjectsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + FillList(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CProjectsDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + UpdateModified(false); + return true; +} + + + + +//************************************************ +//UPDATE MODIFIED DATA +//************************************************* +bool CProjectsDlg::UpdateModified(bool IsNew) +{ + COleDateTime dtData; + //updates modified by and modified on fields + if(IsNew)//update creator and created as well + { + rs->UpdateField("creator",&m_pApp->m_lusrID); + + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("created",&dtData); + } + + rs->UpdateField("modifier",&m_pApp->m_lusrID); + + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + rs->SaveRecord(); + + + return true; +} +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CProjectsDlg::SaveField(CButton *ckControl,CString fldname) +{ + if(m_bAddMode) return true;//dont attempt to update + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + UpdateModified(false); + return true; +} + + + + + + +//************************************** +void CProjectsDlg::OnAdd() +{ + CString strData; + bool bData; + if(!m_bAddMode) + {//go to add mode + EnableEntry(true); + m_bAddMode=true; + m_btnAdd.SetWindowText("Save"); + m_btnDelete.SetWindowText("Cancel"); + m_lblList.ShowWindow(FALSE); + m_cbList.ShowWindow(FALSE); + m_edDescription.SetWindowText(""); + m_edName.SetWindowText(""); + m_ckActive.SetCheck(TRUE); + + + } + else//save and exit add mode + { + m_edName.GetWindowText(strData); + if(strData.IsEmpty()) + { + AfxMessageBox("Project name is required."); + return; + } + + //add the record + if(rs->AddNewRecord()) + { + rs->UpdateField("name",&strData); + + m_edDescription.GetWindowText(strData); + rs->UpdateField("notes",&strData); + + bData=(m_ckActive.GetCheck() ? true : false); + rs->UpdateField("active",&bData); + + + //this will save the record as well + UpdateModified(true); + + m_bAddMode=false; + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + m_lblList.ShowWindow(TRUE); + m_cbList.ShowWindow(TRUE); + FillList(); + + } + + + + } + +} + + + +//**************************************** +void CProjectsDlg::OnDelete() +{ + CString q,strID; + + + if(m_bAddMode)//user pressed cancel button + { + m_bAddMode=false; + m_btnAdd.SetWindowText("Add"); + m_btnDelete.SetWindowText("Delete"); + m_lblList.ShowWindow(TRUE); + m_cbList.ShowWindow(TRUE); + FillList(); + return; + } + + + //USER IS REQUESTING TO DELETE RECORD + //check to see if records exist + strID=m_cbList.GetCurrentRowID(); + + /* Obsolete, uses 0 for no project + if(strID.Compare("1")==0) + { + AfxMessageBox("You can't delete this item\r\nIt's built in."); + return; + } +*/ + + q.Format("SELECT wo.project FROM wo " + "WHERE (((wo.project)=%s));",strID); + rs->Query(q); + if(!rs->IsEmpty()) + { + AfxMessageBox("DATA INTEGRITY PROTECTION:\r\n" + "You can't delete this project at this time.\r\n" + "It is attached to one or more work orders."); + return; + + } + else + { + if(AfxMessageBox("Permanently delete?\r\nAre you sure?",MB_YESNO)==IDYES) + { + q.Format("DELETE projects.*, projects.id " + "FROM projects WHERE (((projects.id)=%s));", + m_cbList.GetCurrentRowID()); + rs->Ex(q); + //a deleted contact can't be selected + m_strSelectedProject=""; + FillList(); + } + + } + + +} + + + +//*********************************** +void CProjectsDlg::OnDone() +{ + //set passed in string to selectedproject + if(m_pstrSelectedProject!=NULL) + *m_pstrSelectedProject=m_strSelectedProject; + CDialog::OnOK(); +} + + + +//******************************** +void CProjectsDlg::OnActive() +{ + SaveField(&m_ckActive,"active"); + +} + + + +//******************************************* +void CProjectsDlg::OnKillfocusProjectDescription() +{ + SaveField(&m_edDescription,"notes",true); +} + + + +//****************************************** +void CProjectsDlg::OnKillfocusProjectName() +{ + SaveField(&m_edName,"name",false); + if(!m_bAddMode) + FillList(); +} + + + +//******************************************* +void CProjectsDlg::OnCloseupProjectsCombo() +{ + + //Fill the fields as this is a simple dialog. + //user has made a selection, update the visible list + CString q; + CString strData; + bool bData; + q.Format("SELECT projects.* FROM projects " + "WHERE (((projects.id)=%s));",m_cbList.GetCurrentRowID()); + rs->Query(q); + if(!rs->IsEmpty()) + { + + //NAME + rs->FetchField("name",&strData); + m_edName.SetWindowText(strData); + + //DESCRIPTION + rs->FetchField("notes",&strData); + m_edDescription.SetWindowText(strData); + + //ACTIVE + rs->FetchField("active",&bData); + m_ckActive.SetCheck(bData ? TRUE : FALSE); + + } + //save current selection so that updates and changes + //will still show what was last selected + m_strSelectedProject=m_cbList.GetCurrentRowID(); + +} + +void CProjectsDlg::FillList() +{ + + CString strData; + CString strIndex; + CString q; + long lData; + m_cbList.Clear(); + + q="SELECT projects.* FROM projects ORDER BY projects.name;"; + rs->Query(q); + if(rs->IsEmpty()) + { + EnableEntry(false); + return; + + } + else + { + EnableEntry(true); + //fill combo box with available projects + rs->MoveFirst(); + + + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbList.AddRow(strData,strIndex); + + while(rs->MoveForward()) + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbList.AddRow(strData,strIndex); + } + + } + + //pretend user has selected so that other fields get filled in + if(m_strSelectedProject.IsEmpty()) //first time in + { + m_cbList.SetCurSel(0); + } + else//something valid was selected before so stick with it + { + //try to choose the selected project, + //if it can't be found then select the first in list + if(m_cbList.Select(m_strSelectedProject)==false) + { + //empty the obviously bad value + m_strSelectedProject.Empty(); + //just set to first in list + m_cbList.SetCurSel(0); + } + + } + + OnCloseupProjectsCombo(); +} + + +void CProjectsDlg::SetPassbackString(CString *pstrPB) +{ + //m_pstrSelectedProject=NULL; + m_pstrSelectedProject=pstrPB; + + //Set selected project to passed if not empty + if(!m_pstrSelectedProject->IsEmpty()) + m_strSelectedProject=*m_pstrSelectedProject; + + //on exit of this class, set passed string to + //selected project. + // +} + +void CProjectsDlg::OnOK() +{ + //this function to avoid pressing enter in a field causing + //dialog to close + + //CDialog::OnOK(); +} + +void CProjectsDlg::EnableEntry(bool bEnable) +{ + + if(m_bReadOnly) return; + BOOL enable = bEnable ? TRUE : FALSE; + m_btnDelete.EnableWindow(enable); + m_cbList.EnableWindow(enable); + m_ckActive.EnableWindow(enable); + m_edDescription.EnableWindow(enable); + m_edName.EnableWindow(enable); + m_lblList.EnableWindow(enable); + +} + +void CProjectsDlg::Security() +{ + m_bReadOnly=false; + int x=m_pApp->Allowed(RPROJECTS,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + m_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_ckActive.EnableWindow(FALSE); + m_edDescription.SetReadOnly(TRUE); + m_edName.SetReadOnly(TRUE); + + + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.h new file mode 100644 index 0000000..fa840a6 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ProjectsDlg.h @@ -0,0 +1,79 @@ +#if !defined(AFX_PROJECTSDLG_H__3A607184_25BE_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_PROJECTSDLG_H__3A607184_25BE_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ProjectsDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CProjectsDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +class CProjectsDlg : public CDialog +{ +// Construction +public: + bool m_bReadOnly; + void Security(); + void EnableEntry(bool bEnable); + CString * m_pstrSelectedProject; + void SetPassbackString(CString* pstrPB); + void FillList(); + CString m_strSelectedProject; + CProjectsDlg(CWnd* pParent = NULL); // standard constructor + ~CProjectsDlg(); + CSpApp* m_pApp; + GZRset* rs; + bool m_bAddMode; + + //Save fields + bool SaveField(CButton *ckControl,CString fldname); + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool UpdateModified(bool IsNew); + //------------------------------- + +// Dialog Data + //{{AFX_DATA(CProjectsDlg) + enum { IDD = IDD_PROJECTS }; + CStatic m_lblList; + CgzCombo m_cbList; + CEdit m_edName; + CEdit m_edDescription; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnAdd; + CButton m_ckActive; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CProjectsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CProjectsDlg) + afx_msg void OnActive(); + afx_msg void OnAdd(); + afx_msg void OnDelete(); + afx_msg void OnDone(); + afx_msg void OnKillfocusProjectDescription(); + afx_msg void OnKillfocusProjectName(); + afx_msg void OnCloseupProjectsCombo(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PROJECTSDLG_H__3A607184_25BE_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.cpp new file mode 100644 index 0000000..be28dae --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.cpp @@ -0,0 +1,1640 @@ +// RPTS.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "RPTS.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +//memory leak debugging help +#define _CRTDBG_MAP_ALLOC +#include +#include +#include ".\rpts.h" +///////////////////////////////////////////////////////////////////////////// +// RPTS + +IMPLEMENT_DYNCREATE(RPTS, CFormView) + +RPTS::RPTS() +: CFormView(RPTS::IDD) +, m_bShowShortdateWarning(false) +{ + //{{AFX_DATA_INIT(RPTS) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + + m_bListByDescription=true; + m_pApp->m_bRefreshReportsScreen=true; +} + +RPTS::~RPTS() +{ + //DeActivate(); +} + +void RPTS::DoDataExchange(CDataExchange* pDX) +{ + CFormView::DoDataExchange(pDX); + //{{AFX_DATA_MAP(RPTS) + + DDX_Control(pDX, IDC_BTNSQL, m_btnSQL); + DDX_Control(pDX, IDC_BTNFIELDS, m_btnFields); + DDX_Control(pDX, IDC_BTNTTX, m_btnTTX); + DDX_Control(pDX, IDC_LBLBYMODEL, m_lblByModel); + DDX_Control(pDX, IDC_LBLBYDESC, m_lblByDesc); + DDX_Control(pDX, IDC_LBLMODEL, m_lblModel); + DDX_Control(pDX, IDC_LBLMANUFACTURER, m_lblManufacturer); + DDX_Control(pDX, IDC_CBMODEL, m_cbModel); + DDX_Control(pDX, IDC_CBMANUFACTURER, m_cbManufacturer); + DDX_Control(pDX, IDC_LBLZONE, m_lblZone); + DDX_Control(pDX, IDC_CBZONE, m_cbZone); + DDX_Control(pDX, IDC_LBLUNIT, m_lblUnit); + DDX_Control(pDX, IDC_LBLTECH, m_lblTech); + DDX_Control(pDX, IDC_LBLRATE, m_lblRate); + DDX_Control(pDX, IDC_LBLPROJECT, m_lblProject); + DDX_Control(pDX, IDC_LBLPART, m_lblPart); + DDX_Control(pDX, IDC_LBLNONCLIENT, m_lblNonClient); + DDX_Control(pDX, IDC_LBLDATERANGE, m_lblDateRange); + DDX_Control(pDX, IDC_LBLCLIENT, m_lblClient); + DDX_Control(pDX, IDC_LBLCATEGORY, m_lblCategory); + DDX_Control(pDX, IDC_LBLBETWEEN, m_lblBetween); + DDX_Control(pDX, IDC_LBLAND, m_lblAnd); + DDX_Control(pDX, IDC_DTSTART, m_dtStart); + DDX_Control(pDX, IDC_DTEND, m_dtEnd); + DDX_Control(pDX, IDC_CBUNIT, m_cbUnit); + DDX_Control(pDX, IDC_CBTECH, m_cbTech); + DDX_Control(pDX, IDC_CBREPORT, m_cbReport); + DDX_Control(pDX, IDC_CBRATE, m_cbRate); + DDX_Control(pDX, IDC_CBPROJECT, m_cbProject); + DDX_Control(pDX, IDC_CBPART, m_cbPart); + DDX_Control(pDX, IDC_CBNONCLIENT, m_cbNonClient); + DDX_Control(pDX, IDC_CBDATERANGE, m_cbDateRange); + DDX_Control(pDX, IDC_CBCLIENT, m_cbClient); + DDX_Control(pDX, IDC_CBCATEGORY, m_cbCategory); + DDX_Control(pDX, IDC_BTNREPORT, m_btnReport); + //}}AFX_DATA_MAP + +} + + +BEGIN_MESSAGE_MAP(RPTS, CFormView) + //{{AFX_MSG_MAP(RPTS) + ON_BN_CLICKED(IDC_LBLBYMODEL, OnLblbymodel) + ON_BN_CLICKED(IDC_LBLBYDESC, OnLblbydesc) + ON_CBN_CLOSEUP(IDC_CBREPORT, OnCloseupCbreport) + ON_BN_CLICKED(IDC_BTNREPORT, OnBtnreport) + ON_CBN_CLOSEUP(IDC_CBDATERANGE, OnCloseupCbdaterange) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTEND, OnDatetimechangeDtend) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTSTART, OnDatetimechangeDtstart) + ON_BN_CLICKED(IDC_BTNTTX, OnBtnttx) + ON_BN_CLICKED(IDC_BTNFIELDS, OnBtnfields) + ON_BN_CLICKED(IDC_BTNREFRESH, OnBtnrefresh) + ON_BN_CLICKED(IDC_BTNSQL, OnBtnsql) + //}}AFX_MSG_MAP + ON_WM_HELPINFO() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// RPTS diagnostics + +#ifdef _DEBUG +void RPTS::AssertValid() const +{ + CFormView::AssertValid(); +} + +void RPTS::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// RPTS message handlers + +void RPTS::Activate() +{ + /* + if(rs==NULL) + { //open with client side cursor due to crystal + //reports bug resulting in blank memo fields + //when using a server side cursor + rs=new GZRset("Error in Reports RS:",true); + rs->SetConnect(m_pApp->strConnectString); + } + */ + //Initialize recordset pointer + + //rsPRINT: + CString strTemp; + rs=m_pApp->rsPool->GetRSPrint("RPTS"); + + FillLists(false); + + char chBuff[50]; + memset(chBuff,0,sizeof(int)); + + + //short date format + if(m_bShowShortdateWarning)//to avoid showing on program startup + { + if(GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_ICENTURY ,chBuff,50)) + { + strTemp.Format("%s",chBuff); + if(strTemp=="0")//not 4 digit century + { + m_pApp->ShowStuff( + + "WARNING: Reports that use date ranges may not print what you expect.\r\n\r\n" + + "Windows on this computer is incorrectly set to display 2 digit centuries\r\n" + "instead of full 4 digit centuries as required for Y2K readiness.\r\n\r\n" + + "This reports screen uses the years 1900 and 2500 to indicate all dates\r\n" + "should be used when you select which will appear incorrectly\r\n" + "to both be the year 2000 because only the last two digits of the century\r\n" + "are displayed on this computer due to the Windows short date format\r\n" + "display setting.\r\n\r\n" + + "To make this message go away and avoid potential problems with not only \r\n" + "reports in AyaNova but other post-y2k applications used on this computer, \r\n" + "set Windows to use 4 digit centuries in the Windows Control panel's \r\n" + "Regional Settings Short Date format as described in the \r\n\r\n" + "\"Getting started -> Installation and configuration\"\r\n\r\n" + "section of the AyaNova in-program help"); + + + } + + + } + } + else + m_bShowShortdateWarning=true;//Potentially show, not guranteed to show (if their settings are OK for example + + +} + +void RPTS::DeActivate() +{ + //switch focus in case a combo has it + //this way the switch wont fire a close up + //and error on a nonvalid recordset + m_btnReport.SetFocus(); + if(rs!=NULL) + { + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + rs=NULL; + } +} + +void RPTS::FillLists(bool bFillModelsOnly) +{ + + if(!m_pApp->m_bRefreshReportsScreen) + return; + m_pApp->m_bRefreshReportsScreen=false; + //Fill clients + CString strData, strIndex, q; + long lData; + + + + //Fillmodels + m_cbModel.Clear(); + m_cbModel.AddRow(" ","0"); + if(m_bListByDescription) + { + rs->QueryReadOnly("SELECT [company_person] & \" \" & [description] & \" \" & [model] AS item, unitmodels.id " + "FROM unitmodels LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "ORDER BY [company_person] & \" \" & [description] & \" \" & [model];"); + + } + else + { + rs->QueryReadOnly("SELECT [model] & \" \" & [company_person] & \" \" & [description] AS item, unitmodels.id " + "FROM unitmodels LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " + "ORDER BY [company_person] & \" \" & [description] & \" \" & [model];"); + + } + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("item",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbModel.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + m_cbModel.SetCurSel(0); + + + + //this function doubles as a fill model list + //only option since user can select how to display + //the model list by # or full description + if(bFillModelsOnly==true) return; +bool bHO=false; + m_cbClient.Clear(); + m_cbClient.AddRow(" < All Clients >","0"); + q.Format("SELECT clients.id, clients.company AS compname, isheadoffice FROM clients " + "ORDER BY clients.company;"); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("isheadoffice",&bHO); + + + VERIFY(rs->FetchField("compname",&strData)); + if(bHO) + strData=strData+" (head office)"; + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbClient.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + m_cbClient.SetCurSel(0); + + + //fill techs + m_cbTech.Clear(); + m_cbTech.AddRow(" < All Techs >","0"); + q="SELECT users.id, [last] & \", \" & [first] AS fullname FROM users WHERE (((users.tech)=True)) ORDER BY users.last;"; + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("fullname",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbTech.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + m_cbTech.SetCurSel(0); + + + + //fill projects + m_cbProject.Clear(); + m_cbProject.AddRow(" < All Projects >","0"); + q="SELECT projects.id, projects.name FROM projects ORDER BY projects.name;"; + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("name",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbProject.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + m_cbProject.Select(0); + + + + //fill categories + m_cbCategory.Clear(); + m_cbCategory.AddRow(" < All Categories >","0"); + q="SELECT wotypes.id, wotypes.category FROM wotypes ORDER BY wotypes.category;"; + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("category",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbCategory.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + m_cbCategory.SetCurSel(0); + + + + + //fill units + m_cbUnit.Clear(); + m_cbUnit.AddRow(" < All Units >","0"); + q="SELECT units.id, [sn] & \" - \" & [company_person] & \" \" & [unitmodels].[description] & \" \" & [unitmodels].[model] AS name " + "FROM (units LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id;"; + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("name",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbUnit.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + m_cbUnit.SetCurSel(0); + + + //fill parts + m_cbPart.Clear(); + m_cbPart.AddRow(" < All Parts >","0"); + q="SELECT parts.id, [partnumber] & \" - \" & [description] AS name FROM parts " + "ORDER BY [partnumber] & \" - \" & [description];"; + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("name",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbPart.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + m_cbPart.SetCurSel(0); + + + + //fill rates + m_cbRate.Clear(); + m_cbRate.AddRow(" < All Rates >","0"); + q="SELECT rates.id, rates.name FROM rates ORDER BY rates.name;"; + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("name",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbRate.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + m_cbRate.SetCurSel(0); + + + //fill daterange + //instead of using date range inquery, this will + //set the appropriate dates in the date boxes + m_cbDateRange.Clear(); + m_cbDateRange.AddRow(" ","0"); + m_cbDateRange.AddRow("Between dates...","1"); + m_cbDateRange.AddRow("This month","2"); + m_cbDateRange.AddRow("Last month","3"); + m_cbDateRange.AddRow("Last 6 months","4"); + m_cbDateRange.AddRow("Last 12 months","5"); + m_cbDateRange.AddRow("This year","6"); + m_cbDateRange.AddRow("Last year","7"); + m_cbDateRange.SetCurSel(0); + + + + //FillManufacturers + m_cbManufacturer.Clear(); + m_cbManufacturer.AddRow(" < All Manufacturers >","0"); + rs->QueryReadOnly("SELECT nonclients.* " + "FROM nonclients " + "WHERE (((nonclients.type)=3)) " + "ORDER BY nonclients.company_person;"); + + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("company_person",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbManufacturer.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + m_cbManufacturer.SetCurSel(0); + + //fill ZONES + m_cbZone.Clear(); + m_cbZone.AddRow(" < All Zones >","0"); + q="SELECT zones.id, zones.name FROM zones ORDER BY zones.name;"; + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("name",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbZone.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + m_cbZone.SetCurSel(0); + + //fill REPORTS + m_cbReport.Clear(); + q= "SELECT rptsmaster.virtualname, rptsmaster.id " + "FROM rptsmaster " + "WHERE (((rptsmaster.x)=True)) " + "ORDER BY rptsmaster.virtualname;"; + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + VERIFY(rs->FetchField("virtualname",&strData)); + VERIFY(rs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbReport.AddRow(strData,strIndex); + }while(rs->MoveForward()); + m_cbReport.SetCurSel(0); + } + + OnCloseupCbdaterange(); + OnCloseupCbreport(); + + m_cbReport.SetFocus(); + +} + + + + + + + + + + + + +void RPTS::ActivateCriteria() +{ + CString q; + long lValue; + + //FETCH criteria here based on id + q.Format("SELECT rptsmaster.criteriafields, rptsmaster.query, rptsmaster.filename " + "FROM rptsmaster " + "WHERE (((rptsmaster.id)=%s));",m_cbReport.GetCurrentRowID()); + + rs->QueryReadOnly(q); + rs->FetchField("query",&m_strRawSQL); + rs->FetchField("criteriafields",&lValue); + rs->FetchField("filename",&m_strReportFileName); + + m_cbZone.EnableWindow(FALSE); + m_lblZone.EnableWindow(FALSE); + m_cbDateRange.EnableWindow(FALSE); + m_lblDateRange.EnableWindow(FALSE); + m_lblBetween.EnableWindow(FALSE); + m_lblAnd.EnableWindow(FALSE); + m_dtStart.EnableWindow(FALSE); + m_dtEnd.EnableWindow(FALSE); + m_cbNonClient.EnableWindow(FALSE); + m_lblNonClient.EnableWindow(FALSE); + m_cbRate.EnableWindow(FALSE); + m_lblRate.EnableWindow(FALSE); + m_cbPart.EnableWindow(FALSE); + m_lblPart.EnableWindow(FALSE); + m_cbUnit.EnableWindow(FALSE); + m_lblUnit.EnableWindow(FALSE); + m_cbCategory.EnableWindow(FALSE); + m_lblCategory.EnableWindow(FALSE); + m_cbProject.EnableWindow(FALSE); + m_lblProject.EnableWindow(FALSE); + m_cbClient.EnableWindow(FALSE); + m_lblClient.EnableWindow(FALSE); + m_cbTech.EnableWindow(FALSE); + m_lblTech.EnableWindow(FALSE); + + m_cbModel.EnableWindow(FALSE); + m_lblModel.EnableWindow(FALSE); + m_cbManufacturer.EnableWindow(FALSE); + m_lblManufacturer.EnableWindow(FALSE); + + if(lValue & TECH) + { + m_cbTech.EnableWindow(TRUE); + m_lblTech.EnableWindow(TRUE); + } + + if(lValue & CLIENT) + { + m_cbClient.EnableWindow(TRUE); + m_lblClient.EnableWindow(TRUE); + } + + if(lValue & PROJECT) + { + m_cbProject.EnableWindow(TRUE); + m_lblProject.EnableWindow(TRUE); + } + + if(lValue & CATEGORY) + { + m_cbCategory.EnableWindow(TRUE); + m_lblCategory.EnableWindow(TRUE); + } + + if(lValue & UNIT) + { + m_cbUnit.EnableWindow(TRUE); + m_lblUnit.EnableWindow(TRUE); + } + + if(lValue & PART) + { + m_cbPart.EnableWindow(TRUE); + m_lblPart.EnableWindow(TRUE); + } + + if(lValue & RATE) + { + m_cbRate.EnableWindow(TRUE); + m_lblRate.EnableWindow(TRUE); + } + + if(lValue & NONCLIENT) + { + m_cbNonClient.EnableWindow(TRUE); + m_lblNonClient.EnableWindow(TRUE); + } + if(lValue & DATE) + { + m_cbDateRange.EnableWindow(TRUE); + m_lblDateRange.EnableWindow(TRUE); + m_lblBetween.EnableWindow(TRUE); + m_lblAnd.EnableWindow(TRUE); + m_dtStart.EnableWindow(TRUE); + m_dtEnd.EnableWindow(TRUE); + } + + if(lValue & ZONE) + { + m_cbZone.EnableWindow(TRUE); + m_lblZone.EnableWindow(TRUE); + } + + if(lValue & MODEL) + { + m_cbModel.EnableWindow(TRUE); + m_lblModel.EnableWindow(TRUE); + } + + + if(lValue & MANUFACTURER) + { + m_cbManufacturer.EnableWindow(TRUE); + m_lblManufacturer.EnableWindow(TRUE); + } + + +} + + + + + + + +void RPTS::OnLblbymodel() +{ + if(m_bListByDescription==false) + return; + m_bListByDescription=false; + m_pApp->m_bRefreshReportsScreen=true; + FillLists(true); + m_lblByDesc.SetTextColor(RGB(0,0,255)); + m_lblByModel.SetTextColor(RGB(0,0,0)); + m_lblByDesc.SetFontUnderline(TRUE); + m_lblByModel.SetFontUnderline(FALSE); + + +} + +void RPTS::OnLblbydesc() +{ + if(m_bListByDescription==true) + return; + m_bListByDescription=true; + m_pApp->m_bRefreshReportsScreen=true; + FillLists(true); + m_lblByDesc.SetTextColor(RGB(0,0,0)); + m_lblByModel.SetTextColor(RGB(0,0,255)); + m_lblByDesc.SetFontUnderline(FALSE); + m_lblByModel.SetFontUnderline(TRUE); + + +} + +void RPTS::OnInitialUpdate() +{ + CFormView::OnInitialUpdate(); + + // m_strChosenReport.Empty(); + + m_lblByDesc.SetTextColor(RGB(0,0,0)); + m_lblByDesc.SetFontUnderline(FALSE); + m_lblByDesc.SetLink(TRUE); + m_lblByDesc.SetLinkCursor(m_pApp->hcHand); + m_lblByDesc.SetLinkURL(""); + + m_lblByModel.SetTextColor(RGB(0,0,255)); + m_lblByModel.SetFontUnderline(TRUE); + m_lblByModel.SetLink(TRUE); + m_lblByModel.SetLinkCursor(m_pApp->hcHand); + m_lblByModel.SetLinkURL(""); + + + + + if(m_pApp->m_lusrID==1) + { + m_btnTTX.ShowWindow(TRUE); + m_btnFields.ShowWindow(TRUE); + m_btnSQL.ShowWindow(TRUE); + } + + + + // set initial date to match default in date + //range combo + COleDateTime dtData(1900, 1, 1, 0, 0, 0); + m_dtStart.SetTime(dtData); + dtData.SetDateTime(2500,1,1,0,0,0); + m_dtEnd.SetTime(dtData); + + Activate(); + DeActivate(); + +} + +void RPTS::OnCloseupCbreport() +{ + /*CString strRpt; + strRpt=m_cbReport.GetCurrentRowID(); + if(strRpt==m_strChosenReport) return; + else + m_strChosenReport=strRpt; + */ + + ActivateCriteria(); + +} + +void RPTS::BuildCriteria() +{ + CString strData; + long lData=0; + + + + if(m_cbClient.GetCurrentRowID()!="0") + lData=lData | CLIENT; + if(m_cbTech.GetCurrentRowID()!="0") + lData=lData | TECH; + if(m_cbProject.GetCurrentRowID()!="0") + lData=lData | PROJECT; + if(m_cbCategory.GetCurrentRowID()!="0") + lData=lData | CATEGORY; + if(m_cbUnit.GetCurrentRowID()!="0") + lData=lData | UNIT; + if(m_cbPart.GetCurrentRowID()!="0") + lData=lData | PART; + if(m_cbRate.GetCurrentRowID()!="0") + lData=lData | RATE; + if(m_cbNonClient.GetCurrentRowID()!="0") + lData=lData | NONCLIENT; + if(m_cbDateRange.GetCurrentRowID()!="0") + lData=lData | DATE; + if(m_cbZone.GetCurrentRowID()!="0") + lData=lData | ZONE; + if(m_cbManufacturer.GetCurrentRowID()!="0") + lData=lData | MANUFACTURER; + if(m_cbModel.GetCurrentRowID()!="0") + lData=lData | MODEL; + strData.Format("Criteria: %u",lData); + AfxMessageBox(strData); +} + +void RPTS::OnBtnreport() +{ + // BuildCriteria(); + CWaitCursor cw; + CString q; + long lReport=atol(m_cbReport.GetCurrentRowID()); + if(lReport==0) return; + //Setup sql for selected report then open it + BuildSql();//substitute criteria tokens in query + cw.Restore(); +#ifdef _DEBUG + //m_pApp->ShowStuff(m_strSQL); + +#endif + //open report + rs->QueryReadOnly(m_strSQL); + if(rs->IsEmpty()) + { + if(m_strSQL.Find("woparts")!=-1 || m_strSQL.Find("hours")!=-1) + AfxMessageBox("There is no data to report.\r\n\r\n" + "If you are trying to print a report that \r\n" + "contains work order information\r\n" + "such as parts or labor you will get this error if\r\n" + "there are no work orders within your criteria choices\r\n" + "that have parts or labor charges on them."); + else + AfxMessageBox("There is no data that matches\r\n" + "your criteria choices"); + } + else + { + //AfxMessageBox(m_strSQL); + m_pApp->PrintCMReportRDC(m_cbReport.GetCurrentRowText(),rs->RecordSetPointer()); + //m_pApp->CreateTTX("gzmonthly.ttx",rs->RecordSetPointer()); + + + } + + cw.Restore(); + + + +} + + +/* +#define CLIENT 1 CUST +#define TECH 2 TECH +#define PROJECT 4 PROJ +#define CATEGORY 8 CAT_ + +#define UNIT 16 UNIT +#define PART 32 PART +#define RATE 64 RATE +#define NONCLIENT 128 + +#define DATE 256 STRT & END_ +#define ZONE 512 ZONE + +#define MANUFACTURER 1024 MANU +#define MODEL 2048 MODL +Additional criteria: +CUSTNAME +TECHNAME +PROJNAME +CAT_NAME +UNITNAME +PARTNAME +RATENAME +ZONENAME +MANUNAME +MODLNAME +USERNAME +DATERANGE +CRITERIA + + +*/ + +void RPTS::BuildSql() +{ + + //Added June 24th 2003 to automatically + //morph query to work with head office if one selected + //also sets m_strProcessedSQL to contents of m_strRawSQL + //so can not be removed as rest now relies on m_strProcessedSQL + SubHeadOffice(); + + CString strData,token,txt,strSubString, strTemp; + + COleDateTime dtData; + int len=m_strProcessedSQL.GetLength(); + int x=0; + int nEndOfToken,nCharsToFetch; + + m_strSQL.Empty(); + //loop through m_strSQL + for(x=0;xm_strCurrentUserName; + m_strSQL+="\""+strData+"\"";; + + + goto DONE; + } + + //DATERANGE + if(token=="DATERANGE") + { + + m_cbDateRange.GetWindowText(strData); + m_strSQL+="\""+strData+"\"";; + + + goto DONE; + } + + //CRITERIA + //added 08/03/2001 makes a descriptive string of all criteria + //selected + if(token=="CRITERIA") + { + + //go through all controls and build a descriptive string + strData.Empty(); + + //dates + if(m_cbDateRange.IsWindowEnabled()) + { + //DATE + m_cbDateRange.GetWindowText(strTemp); + if(strTemp.Find("Any")==-1) + { + strData+=" "; + + } + else + strData += strTemp + " "; + } + //client + if(m_cbClient.IsWindowEnabled()) + { + m_cbClient.GetWindowText(strTemp); + if(strTemp.Find("All Clients")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + + //project + if(m_cbProject.IsWindowEnabled()) + { + m_cbProject.GetWindowText(strTemp); + if(strTemp.Find("All Projects")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + //rate + if(m_cbRate.IsWindowEnabled()) + { + m_cbRate.GetWindowText(strTemp); + if(strTemp.Find("All Rate")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + //zone + if(m_cbZone.IsWindowEnabled()) + { + m_cbZone.GetWindowText(strTemp); + if(strTemp.Find("All Zone")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + //tech + if(m_cbTech.IsWindowEnabled()) + { + m_cbTech.GetWindowText(strTemp); + if(strTemp.Find("All Tech")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + //category + if(m_cbCategory.IsWindowEnabled()) + { + m_cbCategory.GetWindowText(strTemp); + if(strTemp.Find("All Categor")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + //part + if(m_cbPart.IsWindowEnabled()) + { + m_cbPart.GetWindowText(strTemp); + if(strTemp.Find("All Part")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + //unit + if(m_cbUnit.IsWindowEnabled()) + { + m_cbUnit.GetWindowText(strTemp); + if(strTemp.Find("All Unit")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + //manufacturer + if(m_cbManufacturer.IsWindowEnabled()) + { + m_cbManufacturer.GetWindowText(strTemp); + if(strTemp.Find("All Manufact")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + //model + if(m_cbModel.IsWindowEnabled()) + { + m_cbModel.GetWindowText(strTemp); + if(strTemp.Find("All model")==-1) + { + strData+=" "; + + } + else + strData+=strTemp + " "; + } + + + + + + + + + + + + m_strSQL+="\""+strData+"\"";; + goto DONE; + } + + } + else + m_strSQL+=txt; + +DONE: + ; + + } + +#ifdef _DEBUG + // m_pApp->ShowStuff(m_strSQL); +#endif + + //AfxMessageBox(m_strSQL); + +} + +void RPTS::OnCloseupCbdaterange() +{ + /* + m_cbDateRange.AddRow(" ","0"); + m_cbDateRange.AddRow("Between dates...","1"); + m_cbDateRange.AddRow("This month","2"); + m_cbDateRange.AddRow("Last month","3"); + m_cbDateRange.AddRow("Last 6 months","4"); + m_cbDateRange.AddRow("Last 12 months","5"); + m_cbDateRange.AddRow("This year","6"); + m_cbDateRange.AddRow("Last year","7"); + m_cbDateRange.SetCurSel(0); + */ + + CString strData; + int x; + COleDateTime dtStart,dtEnd,dtNow; + dtNow=COleDateTime::GetCurrentTime(); + x=atoi(m_cbDateRange.GetCurrentRowID()); + + switch(x) + { + case 0://Anytime + dtStart.SetDateTime(1900,1,1,0,0,0); + dtEnd.SetDateTime(2500,1,1,0,0,0); + break; + case 1://between dates + return; + //do nothing + break; + case 2://this month + dtStart.SetDate(dtNow.GetYear(),dtNow.GetMonth(),1); + dtEnd=dtStart; + GetMonthEnd(&dtEnd); + break; + case 3://last month + dtStart=dtNow; + GetFirstDayLastMonth(&dtStart); + dtEnd=dtStart; + GetMonthEnd(&dtEnd); + break; + case 4://last 6 months + dtStart=dtEnd=dtNow; + GetDateXMonthsAgo(&dtStart,6); + break; + case 5://last 12 months + dtStart=dtEnd=dtNow; + GetDateXMonthsAgo(&dtStart,12); + break; + case 6://this year + dtStart.SetDate(dtNow.GetYear(),1,1);//jan 1st this year + dtEnd.SetDate(dtNow.GetYear(),12,31);//dec 31st this year + break; + case 7://last year + dtStart.SetDate(dtNow.GetYear()-1,1,1);//jan 1st this year + dtEnd.SetDate(dtNow.GetYear()-1,12,31);//dec 31st this year + break; + + + } + + + m_dtStart.SetTime(dtStart); + m_dtEnd.SetTime(dtEnd); + +} + + +//Modifies passed COleDateTime object +//to = last day of month that was +//originally stored in the date time object +void RPTS::GetMonthEnd(COleDateTime *dtData) +{ + COleDateTimeSpan span; + COleDateTime dt=*dtData; + int x=0; + int curmonth; + + //add 1 day until the month changes + curmonth=dtData->GetMonth(); + while(dt.GetMonth()==curmonth) + { + x++; + span.SetDateTimeSpan(x,0,0,0); + dt=*dtData+span; + } + + span.SetDateTimeSpan(-1,0,0,0); + *dtData=dt+span; +} + + +//Modifies passed in COleDateTime object +//to equal the 1st of the previous month +void RPTS::GetFirstDayLastMonth(COleDateTime *dtData) +{ + COleDateTimeSpan span; + COleDateTime dt=*dtData; + int x=0; + int curmonth; + + //add 1 day until the month changes + curmonth=dtData->GetMonth(); + while(dt.GetMonth()==curmonth) + { + x--; + span.SetDateTimeSpan(x,0,0,0); + dt=*dtData+span; + } + + + + dtData->SetDate(dt.GetYear(),dt.GetMonth(),1); + +} + + + + +void RPTS::GetDateXMonthsAgo(COleDateTime* dtData, int iMonths) +{ + ASSERT(iMonths>0); + if(iMonths<1) return; + int iNewYear=dtData->GetYear(); + int iDays = dtData->GetDay(); + int iNewMonths ; + div_t div_result = div(iMonths, 12); + iNewYear = dtData->GetYear() - div_result.quot; + iNewMonths=dtData->GetMonth()-div_result.rem; + if(iNewMonths<1) + { + iNewMonths=12+iNewMonths; + iNewYear--; + + } + + + dtData->SetDate(iNewYear,iNewMonths,iDays); + + + while (dtData->GetStatus() == COleDateTime::invalid && iDays>28) { + iDays--; + dtData->SetDate(iNewYear, iNewMonths, iDays); + } + + return; +} + + +void RPTS::OnDatetimechangeDtend(NMHDR* pNMHDR, LRESULT* pResult) +{ + // TODO: Add your control notification handler code here + //OnCloseupCbdaterange(); + m_cbDateRange.Select(1);//between + *pResult = 0; +} + +void RPTS::OnDatetimechangeDtstart(NMHDR* pNMHDR, LRESULT* pResult) +{ + // TODO: Add your control notification handler code here + //OnCloseupCbdaterange(); + m_cbDateRange.Select(1);//between + *pResult = 0; +} + +void RPTS::OnBtnttx() +{ + + // BuildCriteria(); + CString q, strData; + long lReport=atol(m_cbReport.GetCurrentRowID()); + if(lReport==0) return; + //Setup sql for selected report then open it + BuildSql();//substitute criteria tokens in query + + //open report + rs->QueryReadOnly(m_strSQL); + if(rs->IsEmpty()) + AfxMessageBox("There is no data that matches\r\n" + "your criteria choices"); + else + { + strData=m_strReportFileName; + strData=strData.Left(strData.GetLength()-4); + strData=strData+".ttx"; + //AfxMessageBox(m_strSQL); + //m_pApp->PrintCMReport(m_cbReport.GetCurrentRowText(),rs->RecordSetPointer()); + m_pApp->CreateTTX(strData,rs->RecordSetPointer()); + + + } + + + + + + +} + +void RPTS::OnBtnfields() +{ + BuildCriteria(); +#ifdef _DEBUG + //BuildSql(); +#endif +} + + + +void RPTS::OnBtnrefresh() +{ + m_pApp->m_bRefreshReportsScreen=true; + FillLists(false); + +} + +void RPTS::OnBtnsql() +{ + CString strDisplay; + long lReport=atol(m_cbReport.GetCurrentRowID()); + if(lReport==0) return; + //Setup sql for selected report then show + BuildSql();//substitute criteria tokens in query + strDisplay="\r\n\r\n"+ + m_strRawSQL; + + if(m_strRawSQL!=m_strProcessedSQL)//subs have been made + strDisplay += + "\r\n\r\n\r\n\r\n< Head office was selected, master query changed to this>\r\n\r\n"+ + m_strProcessedSQL; + + strDisplay += + "\r\n\r\n\r\n\r\n\r\n\r\n"+ + m_strSQL + "\r\n"; + + m_pApp->ShowStuff(strDisplay); +} + +BOOL RPTS::OnHelpInfo(HELPINFO* pHelpInfo) +{ + + WinHelp (0x00020000 + IDD_RPTS_FORM,HELP_CONTEXT); + return TRUE; +} + + + +// Substitute head offices in query if one was selected as criteria +void RPTS::SubHeadOffice(void) +{ + //start afresh + m_strProcessedSQL=m_strRawSQL; + + CString strClient; + strClient=m_cbClient.GetCurrentRowID(); + + //See if it's an "" selection which doesn't require processing. + if(strClient=="0") + return; + + //See if there is a cust token to bother continuing + if(m_strProcessedSQL.Find("~CUST")==-1) + return; + + //Next see if it's a head office + CString q; + bool bHeadOffice=false; + q.Format("SELECT clients.isheadoffice FROM clients WHERE (((clients.id)=%s));",strClient); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + rs->FetchField("isheadoffice",&bHeadOffice); + } + + //Not a head office? Then bail + if(false==bHeadOffice) + return; + + //OK, it is a head office, now see if there is anything that can + //be done with the query and substitute if so.. + + if(m_strProcessedSQL.Find("JOIN clients")!=-1 || m_strProcessedSQL.Find("clients.")!=-1 + || m_strProcessedSQL.Find("[clients]")!=-1) + { + //yes we have a join to clients so start substituting + m_strProcessedSQL.Replace("(wo.client)~CUST","(clients.headoffice)~CUST"); + m_strProcessedSQL.Replace("(clients.id)~CUST","(clients.headoffice)~CUST"); + + //versions with spaces in case user hand typed it in + m_strProcessedSQL.Replace("(wo.client) ~CUST","(clients.headoffice)~CUST"); + m_strProcessedSQL.Replace("(clients.id) ~CUST","(clients.headoffice)~CUST"); + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.h new file mode 100644 index 0000000..87cc708 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RPTS.h @@ -0,0 +1,167 @@ +#if !defined(AFX_RPTS_H__B3971462_FC37_11D3_964F_00C0F02C4B69__INCLUDED_) +#define AFX_RPTS_H__B3971462_FC37_11D3_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// RPTS.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// RPTS form view + +#ifndef __AFXEXT_H__ +#include +#endif + + +//these defines are used to set bits +//for which criteria selectors should be +//enabled depending upon the report +//Use bitwise OR | to add up values +//and use bitwise AND to See if a bit is set or not + +//so CLIENT | TECH = 3 anding client or tech will +//result in nonzero so if(value & CLIENT) will be +//true if client exists in bitfield +//largest possible number for these 10 items would be +//512, 15 items would be 32767 +#define CLIENT 1 +#define TECH 2 +#define PROJECT 4 +#define CATEGORY 8 + +#define UNIT 16 +#define PART 32 +#define RATE 64 +#define NONCLIENT 128 + +#define DATE 256 +#define ZONE 512 + +#define MANUFACTURER 1024 +#define MODEL 2048 + + +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +#include "afxwin.h" +class RPTS : public CFormView +{ +public: + RPTS(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(RPTS) + GZRset* rs; + CSpApp* m_pApp; +// Form Data +public: + //{{AFX_DATA(RPTS) + enum { IDD = IDD_RPTS_FORM }; + CButton m_btnSQL; + CButton m_btnFields; + CButton m_btnTTX; + CLabel m_lblByModel; + CLabel m_lblByDesc; + CStatic m_lblModel; + CStatic m_lblManufacturer; + CgzCombo m_cbModel; + CgzCombo m_cbManufacturer; + CStatic m_lblZone; + CgzCombo m_cbZone; + CStatic m_lblUnit; + CStatic m_lblTech; + CStatic m_lblRate; + CStatic m_lblProject; + CStatic m_lblPart; + CStatic m_lblNonClient; + CStatic m_lblDateRange; + CStatic m_lblClient; + CStatic m_lblCategory; + CStatic m_lblBetween; + CStatic m_lblAnd; + CDateTimeCtrl m_dtStart; + CDateTimeCtrl m_dtEnd; + CgzCombo m_cbUnit; + CgzCombo m_cbTech; + CgzCombo m_cbReport; + CgzCombo m_cbRate; + CgzCombo m_cbProject; + CgzCombo m_cbPart; + CgzCombo m_cbNonClient; + CgzCombo m_cbDateRange; + CgzCombo m_cbClient; + CgzCombo m_cbCategory; + CButton m_btnReport; + //}}AFX_DATA + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(RPTS) + public: + virtual void OnInitialUpdate(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +public: + + //CString m_strChosenReport; + CString m_strReportFileName; + void GetDateXMonthsAgo(COleDateTime* dtData, int iMonths); + void GetFirstDayLastMonth(COleDateTime* dtData); + void GetMonthEnd(COleDateTime* dtData); + void BuildSql(); + + CString m_strSQL; + CString m_strRawSQL; + CString m_strProcessedSQL;//added June 24th 2003 to handle head offices and preserve original raw sql + + void BuildCriteria(); + bool m_bListByDescription; + void ActivateCriteria(); + void FillLists(bool bFillModelsOnly); + void DeActivate(); + void Activate(); + virtual ~RPTS(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(RPTS) + afx_msg void OnLblbymodel(); + afx_msg void OnLblbydesc(); + afx_msg void OnCloseupCbreport(); + afx_msg void OnBtnreport(); + afx_msg void OnCloseupCbdaterange(); + afx_msg void OnDatetimechangeDtend(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDatetimechangeDtstart(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnBtnttx(); + afx_msg void OnBtnfields(); + afx_msg void OnBtnrefresh(); + afx_msg void OnBtnsql(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + + bool m_bShowShortdateWarning; +private: + // Substitute head offices in query if one was selected as criteria + void SubHeadOffice(void); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RPTS_H__B3971462_FC37_11D3_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.cpp new file mode 100644 index 0000000..af8371b --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.cpp @@ -0,0 +1,650 @@ +// RatesDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "RatesDlg.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CRatesDlg dialog + + +CRatesDlg::CRatesDlg(CWnd* pParent /*=NULL*/) +: CDialog(CRatesDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CRatesDlg) + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Rates entry screen error:"); + rs->SetConnect(m_pApp->strConnectString); +*/ + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CRatesDlg"); + + cfm = new CgzCurrencyFormatter; + m_strReturnValue=NULL; +} + +CRatesDlg::~CRatesDlg() //destructor +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + delete cfm; +} +void CRatesDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CRatesDlg) + DDX_Control(pDX, IDC_TRAVELRATE, m_ckTravel); + DDX_Control(pDX, IDC_ADD, m_btnAdd); + DDX_Control(pDX, IDC_EXPIRYDATE, m_dtExpiry); + DDX_Control(pDX, IDC_ACTIVE, m_ckActive); + DDX_Control(pDX, IDOK, m_btnDone); + DDX_Control(pDX, IDC_COST, m_edCost); + DDX_Control(pDX, IDC_DELETE, m_btnDelete); + DDX_Control(pDX, IDC_FLATRATE, m_ckFlat); + DDX_Control(pDX, IDC_PARTNUMBER, m_edPartNumber); + DDX_Control(pDX, IDC_RATE, m_edCharge); + DDX_Control(pDX, IDC_RATENAME, m_edRateName); + DDX_Control(pDX, IDC_RATELISTLABEL, m_lblRates); + DDX_Control(pDX, IDC_RATELIST, m_cbRates); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CRatesDlg, CDialog) +//{{AFX_MSG_MAP(CRatesDlg) +ON_CBN_CLOSEUP(IDC_RATELIST, OnCloseupRatelist) +ON_BN_CLICKED(IDC_ADD, OnAdd) +ON_EN_KILLFOCUS(IDC_COST, OnKillfocusCost) +ON_BN_CLICKED(IDC_ACTIVE, OnActive) +ON_BN_CLICKED(IDC_DELETE, OnDelete) +ON_BN_CLICKED(IDC_FLATRATE, OnFlatrate) +ON_EN_KILLFOCUS(IDC_PARTNUMBER, OnKillfocusPartnumber) +ON_EN_KILLFOCUS(IDC_RATE, OnKillfocusRate) +ON_EN_KILLFOCUS(IDC_RATENAME, OnKillfocusRatename) +ON_NOTIFY(DTN_DATETIMECHANGE, IDC_EXPIRYDATE, OnDatetimechangeExpirydate) + ON_BN_CLICKED(IDC_TRAVELRATE, OnTravelrate) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CRatesDlg message handlers +//***************************************** +void CRatesDlg::FillRateList() +{ + CString strData; + CString strIndex; + long lData; + m_cbRates.Clear(); + rs->Query("SELECT rates.* FROM rates ORDER BY rates.name;"); + if(!rs->IsEmpty()) + { + //fill combo box with available zones + rs->MoveFirst(); + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbRates.AddRow(strData,strIndex); + while(rs->MoveForward()) + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbRates.AddRow(strData,strIndex); + } + + + + //pretend user has selected so that other fields get filled in + if(m_strSelectedRate.IsEmpty()) //first time in + { + m_cbRates.SetCurSel(0); + if(m_strReturnValue!=NULL) + m_strReturnValue->Format("%s",m_cbRates.GetCurrentRowID()); + + + } + else//something valid was selected before so stick with it + m_cbRates.Select(m_strSelectedRate); + + FillFields(); + } + else + DisableAll(true); + return; +} + + +//***************************************** +BOOL CRatesDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + m_bAddMode=false; + FillRateList(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +//***************************************** +void CRatesDlg::FillFields() +{ + CString q,strData,strCurrencySymbol; + bool bData; + COleCurrency crData; + COleDateTime dtData; + + + q.Format("SELECT rates.* FROM rates WHERE (((rates.id)=%s));",m_cbRates.GetCurrentRowID()); + rs->Query(q); + if(!rs->IsEmpty()) + { + rs->FetchField("name",&strData); + m_edRateName.SetWindowText(strData); + + //RATE + rs->FetchField("rate",&crData); + m_edCharge.SetWindowText(cfm->Format(crData)); + + //COST + rs->FetchField("cost",&crData); + m_edCost.SetWindowText(cfm->Format(crData)); + + rs->FetchField("active",&bData); + m_ckActive.SetCheck(bData ? TRUE:FALSE); + + rs->FetchField("travelrate",&bData); + m_ckTravel.SetCheck(bData ? TRUE:FALSE); + + rs->FetchField("expires",&dtData); + m_dtExpiry.SetTime(dtData); + + rs->FetchField("flatrate",&bData); + m_ckFlat.SetCheck(bData ? TRUE:FALSE); + + rs->FetchField("partnum",&strData); + m_edPartNumber.SetWindowText(strData); + + + } +} + +void CRatesDlg::SetReturnString(CString *ret) +{ + m_strReturnValue=ret; +} + +void CRatesDlg::OnCloseupRatelist() +{ + FillFields(); + if(m_strReturnValue!=NULL) + m_strReturnValue->Format("%s",m_cbRates.GetCurrentRowID()); + +} + +void CRatesDlg::OnAdd() +{ + if(!m_bAddMode)//go into add mode + { + DisableAll(false); + m_btnAdd.SetWindowText("SAVE"); + m_lblRates.ShowWindow(FALSE); + m_cbRates.ShowWindow(FALSE); + m_btnDelete.SetWindowText("CANCEL"); + + m_ckActive.SetCheck(TRUE); + m_ckFlat.SetCheck(FALSE); + m_ckTravel.SetCheck(FALSE); + m_btnDone.ShowWindow(FALSE); + m_edCharge.SetWindowText(""); + //FIX:ADD ONE YEAR TO DATE + m_dtExpiry.SetTime(COleDateTime::GetCurrentTime()); + + m_edCharge.SetWindowText(""); + m_edCost.SetWindowText(""); + m_edPartNumber.SetWindowText(""); + m_edRateName.SetWindowText(""); + m_bAddMode=true; + } + else + { + + //save everything + if(AddRecord()!=true) + return; + m_bAddMode=false; + m_btnAdd.SetWindowText("Add"); + m_lblRates.ShowWindow(TRUE); + m_cbRates.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_ckActive.SetCheck(TRUE); + m_ckFlat.SetCheck(TRUE); + m_btnDone.ShowWindow(TRUE); + FillRateList(); + + } +} + + + +//************************************************************* +void CRatesDlg::OnKillfocusCost() +{ + + COleCurrency crData; + if(!m_bAddMode) + { + if(SaveCurrencyField(&m_edCost,"cost")) + { + rs->FetchField("cost",&crData); + m_edCost.SetWindowText(cfm->Format(crData)); + + } + } +} +//************************************************************* +void CRatesDlg::OnActive() +{ + SaveField(&m_ckActive,"active"); + +} +//************************************************************* +void CRatesDlg::OnDelete() +{ + + //if in add mode then this is the cancel button + //not the delete button + if(m_bAddMode) + { + m_btnAdd.SetWindowText("Add"); + m_lblRates.ShowWindow(TRUE); + m_cbRates.ShowWindow(TRUE); + m_btnDelete.SetWindowText("Delete"); + m_ckActive.SetCheck(TRUE); + m_ckFlat.SetCheck(TRUE); + m_btnDone.ShowWindow(TRUE); + FillRateList(); + m_bAddMode=false; + return; + } + + + CString q,strData; + q.Format("SELECT * FROM labor WHERE (rate = %s );",m_cbRates.GetCurrentRowID()); + + + + rs->Query(q); + if(rs->IsEmpty())//no clients in that zone + { + + q.Format("DELETE rates.*, rates.id FROM rates WHERE (((rates.id)=%s));",m_cbRates.GetCurrentRowID()); + if(AfxMessageBox("Are you sure?",MB_YESNO)==IDYES) + { + rs->Ex(q); + //a deleted zone can't be selected + m_strSelectedRate=""; + } + } + else + { + q="DATA INTEGRITY PROTECTION:\r\nYou cannot delete this rate because\r\n" + "there are one or more workorders using it.\r\n" + "\r\nYou can set it to inactive instead\r\n" + "For more help press F1 from the rates screen"; + + + AfxMessageBox(q); + } + FillRateList(); + +} + +//************************************************************* +void CRatesDlg::OnFlatrate() +{ + SaveField(&m_ckFlat,"flatrate"); + +} + + +//************************************************************* +void CRatesDlg::OnKillfocusPartnumber() +{ + SaveField(&m_edPartNumber,"partnum",true); +} + + +//************************************************************* +void CRatesDlg::OnKillfocusRate() +{ + + CString str; + COleCurrency crData; + m_edCharge.GetWindowText(str); + if(str.IsEmpty()) + { + AfxMessageBox("A chargeout rate is mandatory"); + m_edCharge.SetFocus(); + + } + else + { + if(!m_bAddMode) + { + if(SaveCurrencyField(&m_edCharge,"rate")) + { + rs->FetchField("rate",&crData); + m_edCharge.SetWindowText(cfm->Format(crData)); + } + } + } + +} + + +//************************************************************* +void CRatesDlg::OnKillfocusRatename() +{ + SaveField(&m_edRateName,"name",false); + +} + + +//************************************************************* +void CRatesDlg::OnDatetimechangeExpirydate(NMHDR* pNMHDR, LRESULT* pResult) +{ + SaveField(&m_dtExpiry,"expires"); + + *pResult = 0; +} + + +//************************************************************* +void CRatesDlg::OnOK() +{ + // TODO: Add extra validation here + + CDialog::OnOK(); +} + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CRatesDlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty) +{ + + if(m_bAddMode) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rs->UpdateField(fldname,&str); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE GZCOMBO CONTROL FIELD +//************************************************************ +bool CRatesDlg::SaveField(CgzCombo *cbControl,CString fldname) +{ + + if(m_bAddMode) return true;//dont attempt to update + CString str; + long lData; + str=cbControl->GetCurrentRowID(); + if(str.IsEmpty()) return false;//shouldn't happen but... + lData=atol(str); + rs->UpdateField(fldname,&lData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CRatesDlg::SaveField(CButton *ckControl,CString fldname) +{ + if(m_bAddMode) return true;//dont attempt to update + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rs->UpdateField(fldname,&bData); + rs->SaveRecord(); + UpdateModified(); + return true; +} +//************************************************************ +//SAVE DateTimePicker CONTROL FIELD +//************************************************************ +bool CRatesDlg::SaveField(CDateTimeCtrl *dtControl,CString fldname) +{ + if(m_bAddMode) return true;//dont attempt to update + COleDateTime dtData; + dtControl->GetTime(dtData); + rs->UpdateField(fldname,&dtData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE Currency in an edit CONTROL FIELD +//************************************************************ +bool CRatesDlg::SaveCurrencyField(CEdit *crControl,CString fldname) +{ + if(m_bAddMode) return true;//dont attempt to update + CString str; + COleCurrency crData; + crControl->GetWindowText(str); + if(str.IsEmpty()) + str="0"; + + if(crData.ParseCurrency(str)!=TRUE) + { + AfxMessageBox("Could not interpret your entry in one or more currency fields\r\n" + "I can't save those fields until they are changed."); + return false; + } + rs->UpdateField(fldname,&crData); + rs->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************* +bool CRatesDlg::UpdateModified() +{ + //updates modified by and modified on fields + rs->UpdateField("modifier",&m_pApp->m_lusrID); + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + rs->SaveRecord(); + + + return true; +} + + + +bool CRatesDlg::AddRecord() +{ + + CString q; + CString strData; + bool bData; + COleDateTime dtData,now; + COleCurrency crRate,crCost; + + m_edCharge.GetWindowText(strData); + m_edRateName.GetWindowText(q); + + //make sure there is at least a charge and rate name + if(q.IsEmpty() || strData.IsEmpty()) + { + AfxMessageBox("You must enter at minimum a rate name and Rate/Charge amount to proceed"); + return false; + } + + + + m_dtExpiry.GetTime(dtData); + now=COleDateTime::GetCurrentTime(); + if(now.GetYear()==dtData.GetYear() && now.GetMonth()==dtData.GetMonth()) + { + AfxMessageBox("You must select a rate expiry date.\r\n" + "If you don't want this rate to expire,\r\n" + "set the expiry date far into the future\r\n" + "(100 years is a nice round figure)\r\n\r\n" + "You can't leave it set to today as that would cause\r\n" + "rate expiry warnings whenever you tried to use it;\r\n" + "which would be very annoying.\r\n\r\n" + "If your thinking to yourself:\r\n" + "\"what is this rate expiry date thing anyway?\"\r\n" + "click on it so it's selected and press F1 for more info.\r\n"); + return false; + + } + + //do this here because it falls under the validation + //part of things + m_edCharge.GetWindowText(strData); + if(crRate.ParseCurrency(strData)!=TRUE) + { + AfxMessageBox("Could not interpret your entry in the Charge/Rate field.\r\n" + "Please enter a valid currency amount."); + return false; + } + + m_edCost.GetWindowText(strData); + //empty is ok for the cost some people may not use it. + if(strData.IsEmpty()) + strData="0"; + + + if(crCost.ParseCurrency(strData)!=TRUE) + { + AfxMessageBox("Could not interpret your entry in the Cost field.\r\n" + "Please enter a valid currency amount."); + return false; + } + + + q.Format("SELECT rates.* FROM rates;"); + rs->Query(q); + rs->AddNewRecord(); + + //Start a'savin' + m_edRateName.GetWindowText(strData); + rs->UpdateField("name",&strData); + + //save the two currency fields + rs->UpdateField("rate",&crRate); + rs->UpdateField("cost",&crCost); + + bData = m_ckActive.GetCheck() ? true : false; + rs->UpdateField("active",&bData); + + rs->UpdateField("expires",&dtData); + + bData = m_ckFlat.GetCheck() ? true : false; + rs->UpdateField("flatrate",&bData); + + bData = m_ckTravel.GetCheck() ? true : false; + rs->UpdateField("travelrate",&bData); + + + m_edPartNumber.GetWindowText(strData); + rs->UpdateField("partnum",&strData); + + rs->UpdateField("creator",&m_pApp->m_lusrID); + rs->UpdateField("modifier",&m_pApp->m_lusrID); + + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + rs->UpdateField("created",&dtData); + + return rs->SaveRecord(); + + + + +} + +void CRatesDlg::DisableAll(bool disable) +{ + BOOL e = disable ? FALSE : TRUE; + m_btnDelete.EnableWindow(e); + m_cbRates.EnableWindow(e); + m_ckActive.EnableWindow(e); + m_ckFlat.EnableWindow(e); + m_ckTravel.EnableWindow(e); + m_dtExpiry.EnableWindow(e); + m_edCharge.EnableWindow(e); + m_edCost.EnableWindow(e); + m_edPartNumber.EnableWindow(e); + m_edRateName.EnableWindow(e); + +} + +void CRatesDlg::Security() +{ +//m_bReadOnly=false; + int x=m_pApp->Allowed(RRATES,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + //m_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + m_ckActive.EnableWindow(FALSE); + m_ckFlat.EnableWindow(FALSE); + m_ckTravel.EnableWindow(FALSE); + m_dtExpiry.EnableWindow(FALSE); + m_edCharge.SetReadOnly(TRUE); + m_edCost.SetReadOnly(TRUE); + m_edPartNumber.SetReadOnly(TRUE); + m_edRateName.SetReadOnly(TRUE); + + + + } +} + +void CRatesDlg::OnTravelrate() +{ +SaveField(&m_ckTravel,"travelrate"); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.h new file mode 100644 index 0000000..dc69810 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RatesDlg.h @@ -0,0 +1,95 @@ +#if !defined(AFX_RATESDLG_H__9E6B12A1_19D6_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_RATESDLG_H__9E6B12A1_19D6_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// RatesDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CRatesDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +#include "gzCurrencyFormatter.h" + +class CRatesDlg : public CDialog +{ +// Construction +public: + void Security(); + void DisableAll(bool disable); + bool AddRecord(); + void SetReturnString(CString* ret); + void FillFields(); + CString m_strSelectedRate; + CString * m_strReturnValue; + bool m_bAddMode; + void FillRateList(); + CRatesDlg(CWnd* pParent = NULL); // standard constructor + ~CRatesDlg(); //destructor + GZRset* rs; + CSpApp* m_pApp; + CgzCurrencyFormatter* cfm; + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty); + bool SaveField(CgzCombo* cbControl,CString fldname); + bool SaveField(CButton* ckControl,CString fldname); + bool SaveField(CDateTimeCtrl* dtControl,CString fldname); + bool SaveCurrencyField(CEdit *crControl,CString fldname); + + bool UpdateModified(); + //------------------------------- +// Dialog Data + //{{AFX_DATA(CRatesDlg) + enum { IDD = IDD_RATES }; + CButton m_ckTravel; + CButton m_btnAdd; + CDateTimeCtrl m_dtExpiry; + CButton m_ckActive; + CButton m_btnDone; + CEdit m_edCost; + CButton m_btnDelete; + CButton m_ckFlat; + CEdit m_edPartNumber; + CEdit m_edCharge; + CEdit m_edRateName; + CStatic m_lblRates; + CgzCombo m_cbRates; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CRatesDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CRatesDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnCloseupRatelist(); + afx_msg void OnAdd(); + afx_msg void OnKillfocusCost(); + afx_msg void OnActive(); + afx_msg void OnDelete(); + afx_msg void OnFlatrate(); + afx_msg void OnKillfocusPartnumber(); + afx_msg void OnKillfocusRate(); + afx_msg void OnKillfocusRatename(); + virtual void OnOK(); + afx_msg void OnDatetimechangeExpirydate(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnTravelrate(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RATESDLG_H__9E6B12A1_19D6_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReadMe.txt b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReadMe.txt new file mode 100644 index 0000000..5fc8a72 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReadMe.txt @@ -0,0 +1,114 @@ +======================================================================== + MICROSOFT FOUNDATION CLASS LIBRARY : sp +======================================================================== + + +AppWizard has created this sp application for you. This application +not only demonstrates the basics of using the Microsoft Foundation classes +but is also a starting point for writing your application. + +This file contains a summary of what you will find in each of the files that +make up your sp application. + +sp.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +sp.h + This is the main header file for the application. It includes other + project specific headers (including Resource.h) and declares the + CSpApp application class. + +sp.cpp + This is the main application source file that contains the application + class CSpApp. + +sp.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +sp.clw + This file contains information used by ClassWizard to edit existing + classes or add new classes. ClassWizard also uses this file to store + information needed to create and edit message maps and dialog data + maps and to create prototype member functions. + +res\sp.ico + This is an icon file, which is used as the application's icon. This + icon is included by the main resource file sp.rc. + +res\sp.rc2 + This file contains resources that are not edited by Microsoft + Visual C++. You should place all resources not editable by + the resource editor in this file. + + + +///////////////////////////////////////////////////////////////////////////// + +For the main frame window: + +MainFrm.h, MainFrm.cpp + These files contain the frame class CMainFrame, which is derived from + CFrameWnd and controls all SDI frame features. + +///////////////////////////////////////////////////////////////////////////// + +AppWizard creates one document type and one view: + +spDoc.h, spDoc.cpp - the document + These files contain your CSpDoc class. Edit these files to + add your special document data and to implement file saving and loading + (via CSpDoc::Serialize). + +spView.h, spView.cpp - the view of the document + These files contain your CSpView class. + CSpView objects are used to view CSpDoc objects. + + +///////////////////////////////////////////////////////////////////////////// + +Help Support: + +hlp\sp.hpj + This file is the Help Project file used by the Help compiler to create + your application's Help file. + +hlp\*.bmp + These are bitmap files required by the standard Help file topics for + Microsoft Foundation Class Library standard commands. + +hlp\*.rtf + This file contains the standard help topics for standard MFC + commands and screen objects. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named sp.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +If your application uses MFC in a shared DLL, and your application is +in a language other than the operating system's current language, you +will need to copy the corresponding localized resources MFC42XXX.DLL +from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, +and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. +For example, MFC42DEU.DLL contains resources translated to German.) If you +don't do this, some of the UI elements of your application will remain in the +language of the operating system. + +///////////////////////////////////////////////////////////////////////////// diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.cpp new file mode 100644 index 0000000..4382c34 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.cpp @@ -0,0 +1,4371 @@ +//////////////////////////////////////////////////////////////////////////// +// File: CReportCtrl.cpp +// Version: 1.1.0 +// +// Author: Maarten Hoeben +// E-mail: maarten.hoeben@nwn.com +// +// Implementation of the CReportCtrl and associated classes. +// +// This code may be used in compiled form in any way you desire. This +// file may be redistributed unmodified by any means PROVIDING it is +// not sold for profit without the authors written consent, and +// providing that this notice and the authors name and all copyright +// notices remains intact. +// +// An email letting me know how you are using it would be nice as well. +// +// This file is provided "as is" with no expressed or implied warranty. +// The author accepts no liability for any damage/loss of business that +// this product may cause. +// +// Version history +// +// 1.0.1 - Initial release. +// 1.1.0 - Changed copyright notice. +// - Added RVN_LAYOUTCHANGED notification message. +// - Fixed SB_THUMBPOSITION and SB_THUMBTRACK problems. +// - Removed IDC_HEADERCTRL and IDC_REPORTCTRL definitions. +// Now hardcoded because conflicts with some implementations. +// - Added SortAllColumns(), contributed by Roger Parkinson. +// - Added Chris Hambleton's suggestion to sort on image. +// indices when the (sub)item does not have text. +// - Fixed DeleteAllItems(), as suggested by Paul Leung. +// - Fixed DeleteAllItems() focus problem, as suggested by Dmitry ??. +// - Fixed DeleteItem(), as noted by Eugenio Ciceri. +// - Added fixes and suggestions of Serge Weinstock: +// - Fixed GetNextSelectedItem(). +// - Fixed "no items to show" position. +// - Added support for WS_BORDER style. +// - Added RVN_ITEMDELETED notification. +// - Added mouse-wheel support. +// - Added extended horizontal grid style and changed regular +// horizontal grid style. +// - Fixed selection inversion using space key. +// - Fixed focus selection using ctrl key. +// - Fixed focus on deleted items. +// - Added RVS_OWNERDATA style. +// - Changed notification structure to facilitate +// RVS_OWNERDATA style. +// - Changed hit test info structure to facilitate +// RVS_FOCUSSUBITEMS style. +// - Added RVS_FOCUSSUBITEMS style to enable focus on individual +// subitems to facilitate subitem editing. +// - Added dialog control ID to WPARAM of notification messages. +// - Added subitem editing functionality. +// - Added CReportEditCtrl edit control. +// - Added CReportComboCtrl edit control. +// - Added support for RVIM_TEXT on empty strings (required for +// editing). +// - Added RVIS_READONLY state. +// - Added rect member to RVHITTESTINFO structure. +// - Added RVS_EXPANDSUBITEMS style. +// - Added CReportTipCtrl, based on code by Zafir Anjum. +// - Added background image support, based on code contributed by +// Ernest Laurentin. +// +//////////////////////////////////////////////////////////////////////////// + +// ReportCtrl.cpp : implementation file +// + +#include "stdafx.h" +#include "ReportCtrl.h" + +#include "MemDC.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +TCHAR* g_szSeparator = _T("|"); + +#define IsShiftDown() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0 ) +#define IsCtrlDown() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 ) + +///////////////////////////////////////////////////////////////////////////// +// CReportData + +CReportData::CReportData() +{ +} + +CReportData::~CReportData() +{ +} + +BOOL CReportData::New(INT iSubItems) +{ + for(INT i=0;i=0;i++,iPos++) + iPos = Find(g_szSeparator, iPos); + + if(iPos<0) + return FALSE; + + LPTSTR lpsz = GetBuffer(0); + lpsz = &lpsz[iPos]; + VERIFY(_stscanf(lpsz, _T("(%d,%d,%d,%d)"), lpiImage, lpiCheck, lpiColor, &iText)); + + if(iText < 0) + { + *lpiTextMax = -1; + return TRUE; + } + + lpsz = _tcspbrk(lpsz, _T(")"))+1; + if(lpsz && lpszText) + { + for(INT iTextSize=0;iTextSize<(*lpiTextMax)-1 && *lpsz!=g_szSeparator[0];iTextSize++) + lpszText[iTextSize] = *lpsz++; + + lpszText[iTextSize] = 0; + } + + return TRUE; +} + +BOOL CReportData::SetSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText) +{ + if(!InsertSubItem(iSubItem, iImage, iCheck, iColor, lpszText)) + return FALSE; + + if(!DeleteSubItem(iSubItem+1)) + return FALSE; + + return TRUE; +} + +BOOL CReportData::InsertSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText) +{ + INT i, iPos, iText; + + for(i=0,iPos=0;i=0;i++,iPos++) + iPos = Find(g_szSeparator, iPos); + + if(iPos<0) + return FALSE; + + if(lpszText == NULL) + { + lpszText = _T(""); + iText = -1; + } + else + iText = _tcslen(lpszText); + + CString str; + str.Format("(%d,%d,%d,%d)%s%s", iImage, iCheck, iColor, iText, lpszText, g_szSeparator); + + Insert(iPos, str); + return TRUE; +} + +BOOL CReportData::DeleteSubItem(INT iSubItem) +{ + INT i, iPos1, iPos2; + + for(i=0,iPos1=0;i=0;i++,iPos1++) + iPos1 = Find(g_szSeparator, iPos1); + + if(iPos1<0) + return FALSE; + + iPos2 = Find(g_szSeparator, iPos1); + if(iPos2++<0) + return FALSE; + + Delete(iPos1, iPos2-iPos1); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportView + +IMPLEMENT_DYNCREATE(CReportView, CView) + +CReportView::CReportView() +{ + m_bCreated = FALSE; +} + +CReportView::~CReportView() +{ +} + +void CReportView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + if(!m_bCreated) + { + CRect rect; + GetClientRect(rect); + if(m_wndReportCtrl.Create(WS_CHILD|WS_TABSTOP|WS_VISIBLE, rect, this, 0) == NULL) + AfxThrowMemoryException(); + + m_bCreated = TRUE; + } +} + +BEGIN_MESSAGE_MAP(CReportView, CView) + //{{AFX_MSG_MAP(CReportView) + ON_WM_SIZE() + ON_WM_SETFOCUS() + ON_WM_ERASEBKGND() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CReportView drawing + +void CReportView::OnDraw(CDC* pDC) +{ + ; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportView diagnostics + +#ifdef _DEBUG +void CReportView::AssertValid() const +{ + CView::AssertValid(); +} + +void CReportView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CReportView attributes + +CReportCtrl& CReportView::GetReportCtrl() +{ + return m_wndReportCtrl; +} + +CReportCtrl* CReportView::GetReportCtrlPtr() +{ + return &m_wndReportCtrl; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportView implementation + +BOOL CReportView::OnEraseBkgnd(CDC* pDC) +{ + return TRUE; +} + +void CReportView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + if(m_wndReportCtrl.GetSafeHwnd()) + { + CRect rect; + GetClientRect(rect); + m_wndReportCtrl.MoveWindow(rect); + } +} + +void CReportView::OnSetFocus(CWnd* pOldWnd) +{ + m_wndReportCtrl.SetFocus(); +} + +///////////////////////////////////////////////////////////////////////////// +// CReportCtrl + +IMPLEMENT_DYNCREATE(CReportCtrl, CWnd) + +CReportCtrl::CReportCtrl() +{ + // Register the window class if it has not already been registered. + WNDCLASS wndclass; + HINSTANCE hInst = AfxGetInstanceHandle(); + + if(!(::GetClassInfo(hInst, REPORTCTRL_CLASSNAME, &wndclass))) + { + // Otherwise we need to register a new class + wndclass.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wndclass.lpfnWndProc = ::DefWindowProc; + wndclass.cbClsExtra = wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor(hInst, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)COLOR_WINDOW; + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = REPORTCTRL_CLASSNAME; + + if (!AfxRegisterClass(&wndclass)) + AfxThrowResourceException(); + } + + m_bSubclassFromCreate = FALSE; + + m_bDoubleBuffer = TRUE; + m_iSpacing = 6; + m_nRowsPerWheelNotch = GetMouseScrollLines(); + + m_dwStyle = 0; + + // Initially use the system message font for the ReportCtrl font + NONCLIENTMETRICS ncm; + ncm.cbSize = sizeof(NONCLIENTMETRICS); + VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)); + m_font.CreateFontIndirect(&(ncm.lfMessageFont)); + + m_pImageList = NULL; + m_sizeImage.cx = 0; + m_sizeImage.cy = 0; + m_sizeCheck.cx = 8; + m_sizeCheck.cy = 8; + + GetSysColors(); + + m_arrayColors.SetSize(0, 8); + + m_iGridStyle = PS_SOLID; + + m_strNoItems = _T("There are no items to show in this view."); + + m_iDefaultWidth = 200; + m_iDefaultHeight = 10; + m_iVirtualWidth = 0; + m_iVirtualHeight = 0; + + m_arraySubItems.SetSize(0, 8); + m_arrayItems.SetSize(0, 128); + + m_bColumnsReordered = FALSE; + m_arrayColumns.SetSize(0, 8); + + m_bFocus = FALSE; + m_iFocusRow = RVI_EDIT; + m_iFocusColumn = -1; + m_iSelectRow = 0; + m_arrayRows.SetSize(0, 128); + + INT m_iEditItem = RVI_INVALID; + INT m_iEditSubItem = -1; + m_hEditWnd = NULL; + + m_lprclc = NULL; + m_lpfnrvc = NULL; +} + +CReportCtrl::~CReportCtrl() +{ + m_wndHeader.DestroyWindow(); + m_wndTip.DestroyWindow(); + + if(m_palette.m_hObject) + m_palette.DeleteObject(); + if( m_bitmap.m_hObject != NULL ) + m_bitmap.DeleteObject(); + + if(m_font.m_hObject) + m_font.DeleteObject(); + if(m_fontBold.m_hObject) + m_fontBold.DeleteObject(); +} + +INT CReportCtrl::PreviewHeight(CFont* pFont, UINT nLines) +{ + INT iHeight = -1; + + ASSERT(pFont != NULL); + + CDC* pDC = GetDC(); + if(pDC) + { + CFont* pDCFont = pDC->SelectObject(pFont); + TEXTMETRIC tm; + pDC->GetTextMetrics(&tm); + pDC->SelectObject(pDCFont); + ReleaseDC(pDC); + + iHeight = (tm.tmHeight + tm.tmExternalLeading)*nLines; + } + + return iHeight; +} + +INT CReportCtrl::PreviewHeight(CFont* pFont, LPCTSTR lpszText, LPRECT lpRect) +{ + INT iHeight = -1; + + ASSERT(pFont != NULL); + + CDC* pDC = GetDC(); + if(pDC) + { + CRect rect( 0, 0, m_iVirtualWidth, 0); + if(lpRect != NULL) + rect = *lpRect; + + CFont* pDCFont = pDC->SelectObject(pFont); + iHeight = pDC->DrawText( lpszText, -1, rect, DT_CALCRECT|DT_EXPANDTABS|DT_WORDBREAK|DT_NOCLIP ); + ReleaseDC(pDC); + } + + return iHeight; +} + +BOOL CReportCtrl::Create() +{ + CRect rect(0, 0, 0, 0); + DWORD dwStyle = HDS_HORZ|HDS_BUTTONS|HDS_FULLDRAG|HDS_DRAGDROP|CCS_TOP; + if(!m_wndHeader.Create(dwStyle, rect, this, 0)) + return FALSE; + + if(!m_wndTip.Create(this)) + return FALSE; + + CWnd* pWnd = GetParent(); + if(pWnd) + { + CFont* pFont = pWnd->GetFont(); + if(pFont) + { + LOGFONT lf; + pFont->GetLogFont(&lf); + + m_font.DeleteObject(); + m_font.CreateFontIndirect(&lf); + } + } + + OnSetFont((WPARAM)((HFONT)m_font), FALSE); + m_wndHeader.SetFont(&m_font, FALSE); + + GetClientRect(rect); + Layout(rect.Width(), rect.Height()); + + m_dwStyle = GetStyle(); + if(m_dwStyle&RVS_FOCUSSUBITEMS) + m_iFocusColumn = 0; + + return TRUE; +} + +BOOL CReportCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) +{ + m_bSubclassFromCreate = TRUE; + + if(!CWnd::Create(REPORTCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID, pContext)) + return FALSE; + + return Create(); +} + +void CReportCtrl::PreSubclassWindow() +{ + CWnd::PreSubclassWindow(); + + if(!m_bSubclassFromCreate) + if(!Create()) + AfxThrowMemoryException(); +} + +void CReportCtrl::OnDestroy() +{ + DeleteAllItems(); + CWnd::OnDestroy(); +} + +BEGIN_MESSAGE_MAP(CReportCtrl, CWnd) + //{{AFX_MSG_MAP(CReportCtrl) + ON_WM_DESTROY() + ON_WM_SIZE() + ON_WM_ERASEBKGND() + ON_WM_PAINT() + ON_WM_SYSCOLORCHANGE() + ON_WM_SETTINGCHANGE() + ON_NOTIFY(HDN_ITEMCHANGED, 0, OnHdnItemChanged) + ON_NOTIFY(HDN_ITEMCLICK, 0, OnHdnItemClick) + ON_NOTIFY(HDN_BEGINDRAG, 0, OnHdnBeginDrag) + ON_NOTIFY(HDN_ENDDRAG, 0, OnHdnEndDrag) + ON_NOTIFY(RVN_ENDITEMEDIT, 0, OnRvnEndItemEdit) + ON_WM_HSCROLL() + ON_WM_VSCROLL() + ON_WM_LBUTTONDOWN() + ON_WM_SETCURSOR() + ON_WM_KEYDOWN() + ON_WM_GETDLGCODE() + ON_WM_LBUTTONDBLCLK() + ON_WM_QUERYNEWPALETTE() + ON_WM_PALETTECHANGED() + ON_WM_SETFOCUS() + ON_WM_KILLFOCUS() + ON_WM_NCCALCSIZE() + ON_WM_NCPAINT() + ON_WM_MOUSEWHEEL() + ON_WM_CHAR() + ON_WM_MOUSEMOVE() + //}}AFX_MSG_MAP + ON_MESSAGE(WM_SETFONT, OnSetFont) + ON_MESSAGE(WM_GETFONT, OnGetFont) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CReportCtrl attributes + +BOOL CReportCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam) +{ + switch(wParam) + { + case RVP_SPACING: + m_iSpacing = (INT)lParam; + break; + + case RVP_CHECK: + m_sizeCheck.cx = LOWORD(lParam); + m_sizeCheck.cy = HIWORD(lParam); + break; + + case RVP_NOITEMTEXT: + m_strNoItems = (LPCTSTR)lParam; + break; + + case RVP_GRIDSTYLE: + switch(wParam) + { + case RVP_GRIDSTYLE_DOT: m_iGridStyle = PS_DOT; break; + case RVP_GRIDSTYLE_DASH: m_iGridStyle = PS_DASH; break; + case RVP_GRIDSTYLE_SOLID: m_iGridStyle = PS_SOLID; break; + default: + return FALSE; + } + break; + + default: + return FALSE; + } + + CRect rect; + GetClientRect(rect); + Layout(rect.Width(), rect.Height()); + + return TRUE; +} + +INT CReportCtrl::ActivateColumn(INT iColumn, INT iOrder) +{ + ASSERT(iColumn>=0); + ASSERT(iColumn= 0) + { + m_iVirtualWidth += subitem.iWidth; + + HDITEMEX hditemex; + hditemex.nStyle = (subitem.nFormat&RVCF_EX_MASK)>>16; + hditemex.iMinWidth = subitem.iMinWidth; + hditemex.iMaxWidth = subitem.iMaxWidth; + + if(hditemex.nStyle&HDF_EX_TOOLTIP) + hditemex.strToolTip.Format(_T("Sort by %s"), subitem.strText); + + m_wndHeader.SetItemEx(iResult, &hditemex); + + hdi.mask = HDI_WIDTH; + m_wndHeader.GetItem(iResult, &hdi); + subitem.iWidth = hdi.cxy; + + m_bColumnsReordered = TRUE; + + ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ)); + } + } + catch(CMemoryException* e) + { + e->Delete(); + if(iResult >= 0) + m_wndHeader.DeleteItem(iResult); + } + } + + return iResult; +} + +BOOL CReportCtrl::DeactivateColumn(INT iColumn) +{ + ASSERT(iColumn>=0); + ASSERT(iColumn0); // At least one column must be active + + BOOL bResult = m_wndHeader.DeleteItem(iItem); + + m_iVirtualWidth -= hdi.cxy; + m_bColumnsReordered = TRUE; + + ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ)); + return bResult; +} + +BOOL CReportCtrl::IsActiveColumn(INT iColumn) +{ + INT iHeaderItems = m_arrayColumns.GetSize(); + + HDITEM hdi; + hdi.mask = HDI_LPARAM; + + for(INT iItem=0;iItemiItem > RVI_INVALID); + ASSERT(lprvi->iItem < GetItemCount()); // Specify item + ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize()); // Specify subitem + + UINT nMask = lprvi->nMask; + INT iTextMax = lprvi->iTextMax; + ITEM item = GetItemStruct(lprvi->iItem, lprvi->iSubItem, nMask); + + lprvi->nMask = 0; + lprvi->nPreview = item.nPreview; + if(lprvi->nPreview > 0) + lprvi->nMask |= RVIM_PREVIEW; + + lprvi->iBkColor = item.iBkColor; + if(lprvi->iBkColor >= 0) + lprvi->nMask |= RVIM_BKCOLOR; + + lprvi->lpszText = nMask&RVIM_TEXT ? lprvi->lpszText:NULL; + item.rdData.GetSubItem(lprvi->iSubItem, &lprvi->iImage, &lprvi->iCheck, &lprvi->iTextColor, lprvi->lpszText, &iTextMax); + if(lprvi->lpszText && iTextMax >= 0) + lprvi->nMask |= RVIM_TEXT; + + if(lprvi->iImage >= 0) + lprvi->nMask |= RVIM_IMAGE; + if(lprvi->iCheck >= 0) + lprvi->nMask |= RVIM_CHECK; + if(lprvi->iTextColor >= 0) + lprvi->nMask |= RVIM_TEXTCOLOR; + + lprvi->nMask |= RVIM_STATE|RVIM_LPARAM; + lprvi->nState = item.nState; + lprvi->lParam = item.lParam; + + return TRUE; +} + +BOOL CReportCtrl::SetItem(LPRVITEM lprvi) +{ + if(m_dwStyle&RVS_OWNERDATA) + return FALSE; + // Not supported when using this style + ASSERT(!(lprvi->iItem != RVI_EDIT && m_dwStyle&RVS_OWNERDATA)); + + + m_wndTip.Hide(); + + TCHAR szText[REPORTCTRL_MAX_TEXT]; + + RVITEM rvi; + rvi.iItem = lprvi->iItem; + rvi.iSubItem = lprvi->iSubItem; + rvi.lpszText = szText; + rvi.iTextMax = REPORTCTRL_MAX_TEXT; + rvi.nMask = RVIM_TEXT|RVIM_STATE; + VERIFY(GetItem(&rvi)); + + if(lprvi->nMask&RVIM_TEXT) + { + if(lprvi->lpszText != NULL) + { + _tcsncpy(rvi.lpszText, lprvi->lpszText, REPORTCTRL_MAX_TEXT-1); + rvi.lpszText[REPORTCTRL_MAX_TEXT-1] = 0; + } + else + rvi.lpszText = NULL; + } + else if(!(rvi.nMask&RVIM_TEXT)) + rvi.lpszText = NULL; + + if(lprvi->nMask&RVIM_TEXTCOLOR) + rvi.iTextColor = lprvi->iTextColor; + + if(lprvi->nMask&RVIM_IMAGE) + rvi.iImage = lprvi->iImage; + + if(lprvi->nMask&RVIM_CHECK) + rvi.iCheck = lprvi->iCheck; + + if(lprvi->nMask&RVIM_BKCOLOR) + rvi.iBkColor = lprvi->iBkColor; + + ASSERT(!(lprvi->iItem == RVI_EDIT && lprvi->nMask&RVIM_PREVIEW)); // Preview not supported on edit row + if(lprvi->nMask&RVIM_PREVIEW) + rvi.nPreview = lprvi->nPreview; + + // Note: focus and selection cannot be changed through this function + if(lprvi->nMask&RVIM_STATE) + { + rvi.nState &= RVIS_FOCUSED|RVIS_SELECTED; + rvi.nState |= lprvi->nState&~(RVIS_FOCUSED|RVIS_SELECTED); + } + + if(lprvi->nMask&RVIM_LPARAM) + rvi.lParam = lprvi->lParam; + + ITEM item = GetItemStruct(rvi.iItem, rvi.iSubItem); + + VERIFY(item.rdData.InsertSubItem(rvi.iSubItem, rvi.iImage, rvi.iCheck, rvi.iTextColor, rvi.lpszText)); + VERIFY(item.rdData.DeleteSubItem(rvi.iSubItem+1)); + + item.iBkColor = rvi.iBkColor; + item.nPreview = rvi.nPreview; + item.nState = rvi.nState; + item.lParam = rvi.lParam; + SetItemStruct(rvi.iItem, item); + + ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT)); + + RedrawItems(rvi.iItem); + return TRUE; +} + +INT CReportCtrl::GetItemText(INT iItem, INT iSubItem, LPTSTR lpszText, INT iLen) +{ + RVITEM rvi; + rvi.nMask = RVIM_TEXT; + rvi.iItem = iItem; + rvi.iSubItem = iSubItem; + rvi.lpszText = lpszText; + rvi.iTextMax = iLen; + return GetItem(&rvi) ? _tcslen(rvi.lpszText):0; +} + +CString CReportCtrl::GetItemText(INT iItem, INT iSubItem) +{ + CString str; + TCHAR szText[REPORTCTRL_MAX_TEXT]; + + if(GetItemText(iItem, iSubItem, szText, REPORTCTRL_MAX_TEXT)) + str = szText; + + return str; +} + +BOOL CReportCtrl::SetItemText(INT iItem, INT iSubItem, LPCTSTR lpszText) +{ + RVITEM rvi; + rvi.nMask = RVIM_TEXT; + rvi.iItem = iItem; + rvi.iSubItem = iSubItem; + rvi.lpszText = (LPTSTR)lpszText; + return SetItem(&rvi); +} + +INT CReportCtrl::GetItemImage(INT iItem, INT iSubItem) +{ + RVITEM rvi; + rvi.nMask = RVIM_IMAGE; + rvi.iItem = iItem; + rvi.iSubItem = iSubItem; + return GetItem(&rvi) ? rvi.iImage:-1; +} + +BOOL CReportCtrl::SetItemImage(INT iItem, INT iSubItem, INT iImage) +{ + RVITEM rvi; + rvi.nMask = RVIM_IMAGE; + rvi.iItem = iItem; + rvi.iSubItem = iSubItem; + rvi.iImage = iImage; + return SetItem(&rvi); +} + +INT CReportCtrl::GetItemCheck(INT iItem, INT iSubItem) +{ + RVITEM rvi; + rvi.nMask = RVIM_CHECK; + rvi.iItem = iItem; + rvi.iSubItem = iSubItem; + return GetItem(&rvi) ? rvi.iCheck:-1; +} + +BOOL CReportCtrl::SetItemCheck(INT iItem, INT iSubItem, INT iCheck) +{ + RVITEM rvi; + rvi.nMask = RVIM_CHECK; + rvi.iItem = iItem; + rvi.iSubItem = iSubItem; + rvi.iCheck = iCheck; + return SetItem(&rvi); +} + +DWORD CReportCtrl::GetItemData(INT iItem) +{ + RVITEM rvi; + rvi.nMask = RVIM_LPARAM; + rvi.iItem = iItem; + return GetItem(&rvi) ? rvi.lParam:0; +} + +BOOL CReportCtrl::SetItemData(INT iItem, DWORD dwData) +{ + RVITEM rvi; + rvi.nMask = RVIM_LPARAM; + rvi.iItem = iItem; + rvi.lParam = dwData; + return SetItem(&rvi); +} + +BOOL CReportCtrl::GetItemRect(INT iItem, INT iSubItem, LPRECT lpRect, UINT nCode) +{ + INT iRow = GetRowFromItem(iItem); + INT iColumn = GetColumnFromSubItem(iSubItem); + + // Select a visible sub-item + if(iColumn == -1 && nCode != RVIR_BOUNDS) + return FALSE; + + INT iFirst, iLast; + + if(iRow != RVI_EDIT) + { + iFirst = GetScrollPos32(SB_VERT); + + GetVisibleRows(TRUE, &iFirst, &iLast); + + // Select a visible item + if(iFirst > iRow || iLast < iRow) + return FALSE; + + *lpRect = m_rectReport; + for(;iFirsttop += m_iDefaultHeight + GetItemStruct(GetItemFromRow(iFirst), -1).nPreview; + } + else + *lpRect = m_rectEdit; + + lpRect->bottom = lpRect->top + m_iDefaultHeight; + + INT iPos = GetScrollPos32(SB_HORZ); + + lpRect->left -= iPos; + lpRect->right -= iPos; + + if(iSubItem == -1) + return TRUE; + + HDITEM hdi; + hdi.mask = HDI_WIDTH|HDI_LPARAM; + for(iFirst=0;iFirstleft += hdi.cxy; + } + + m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi); + lpRect->right = lpRect->left + hdi.cxy; + + RVITEM rvi; + rvi.iItem = iItem; + rvi.iSubItem = iSubItem; + GetItem(&rvi); + + switch(nCode) + { + case RVIR_BOUNDS: + return TRUE; + + case RVIR_IMAGE: + if(!(rvi.nMask&RVIM_IMAGE)) + return FALSE; + + lpRect->left += m_iSpacing; + if(lpRect->left + m_sizeImage.cx > lpRect->right - m_iSpacing) + return FALSE; + + lpRect->right = lpRect->left + m_sizeImage.cx; + return TRUE; + + case RVIR_CHECK: + if(!(rvi.nMask&RVIM_CHECK)) + return FALSE; + + lpRect->left += m_iSpacing + (rvi.nMask&RVIM_IMAGE ? m_sizeImage.cx+m_iSpacing:0); + if(lpRect->left + m_sizeCheck.cx > lpRect->right - m_iSpacing) + return FALSE; + + lpRect->right = lpRect->left + m_sizeCheck.cx; + return TRUE; + + case RVIR_TEXT: + lpRect->left += m_iSpacing + + (rvi.nMask&RVIM_IMAGE ? m_sizeImage.cx+m_iSpacing:0) + + (rvi.nMask&RVIM_CHECK ? m_sizeCheck.cx+m_iSpacing:0); + + if(lpRect->left > lpRect->right - m_iSpacing) + return FALSE; + + lpRect->right -= m_iSpacing; + return TRUE; + + default: + return FALSE; + } +} + +void CReportCtrl::SetItemHeight(INT iHeight) +{ + m_iDefaultHeight = iHeight; + + CRect rect; + GetClientRect(rect); + Layout(rect.Width(), rect.Height()); +} + +INT CReportCtrl::GetVisibleCount(BOOL bUnobstructed) +{ + return GetVisibleRows(bUnobstructed); +} + +INT CReportCtrl::GetItemCount() +{ + return m_dwStyle&RVS_OWNERDATA ? m_iVirtualHeight:m_arrayItems.GetSize(); +} + +void CReportCtrl::SetItemCount(INT iCount) +{ + ASSERT(m_dwStyle&RVS_OWNERDATA); // Only supported when using RVS_OWNERDATA style + ASSERT(iCount >= 0); + + m_iVirtualHeight = iCount; + m_iFocusRow = m_iFocusRow>=m_iVirtualHeight ? m_iVirtualHeight-1:m_iFocusRow; + + RedrawItems(RVI_EDIT, RVI_LAST); + ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT)); +} + +INT CReportCtrl::GetFirstSelectedItem() +{ + return GetNextSelectedItem(RVI_INVALID); +} + +INT CReportCtrl::GetNextSelectedItem(INT iItem) +{ + RVITEM rvi; + rvi.nMask = RVIM_STATE; + + INT iItems = GetItemCount(); + + for(rvi.iItem=iItem+1;rvi.iItem RVI_INVALID && iItem < GetItemCount()); + + INT iRow = GetRowFromItem(iItem); + SelectRows(iRow, iRow, TRUE, bKeepSelection, FALSE, FALSE); +} + +void CReportCtrl::SetSelection(LPINT lpiItems, INT iCount, BOOL bKeepSelection) +{ + INT i, iRow; + + for(i=0;i RVI_INVALID && lpiItems[i] < GetItemCount()); + + iRow = GetRowFromItem(lpiItems[i]); + SelectRows(iRow, iRow, TRUE, bKeepSelection|(i != 0), FALSE, FALSE); + } +} + +BOOL CReportCtrl::SetImageList(CImageList* pImageList) +{ + m_pImageList = pImageList; + m_wndHeader.SetImageList(pImageList); + + IMAGEINFO info; + if(pImageList->GetImageInfo(0, &info)) + { + m_sizeImage.cx = info.rcImage.right - info.rcImage.left; + m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top; + + m_iDefaultHeight = m_sizeImage.cy>m_iDefaultHeight ? m_sizeImage.cy:m_iDefaultHeight; + + Invalidate(); + return TRUE; + } + else + return FALSE; +} + +CImageList* CReportCtrl::GetImageList(void) +{ + return m_pImageList; +} + +BOOL CReportCtrl::SetBkImage(UINT nIDResource) +{ + return SetBkImage( (LPCTSTR)nIDResource ); +} + +BOOL CReportCtrl::SetBkImage(LPCTSTR lpszResourceName) +{ + if(m_bitmap.m_hObject != NULL) + m_bitmap.DeleteObject(); + + HBITMAP hBitmap = (HBITMAP)::LoadImage( AfxGetInstanceHandle(), + lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION ); + + Invalidate(); + + if(hBitmap == NULL) + return FALSE; + + m_bitmap.Attach(hBitmap); + + BITMAP bitmap; + m_bitmap.GetBitmap(&bitmap); + m_sizeBitmap.cx = bitmap.bmWidth; + m_sizeBitmap.cy = bitmap.bmHeight; + + CreatePalette(); + return TRUE; +} + +BOOL CReportCtrl::HasFocus() +{ + return m_bFocus; +} + +CFlatHeaderCtrl* CReportCtrl::GetHeaderCtrl() +{ + return &m_wndHeader; +} + +BOOL CReportCtrl::SetReportColumnListCtrl(CReportColumnListCtrl* lprclc) +{ + if(m_lprclc != NULL) + { + m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, NULL); + m_lprclc->SetReportCtrl(NULL); + } + + m_lprclc = lprclc; + if(m_lprclc != NULL) + { + m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, (LPARAM)m_lprclc->m_hWnd); + m_lprclc->SetReportCtrl(this); + } + + return TRUE; +} + +CReportColumnListCtrl* CReportCtrl::GetReportColumnListCtrl() +{ + return m_lprclc; +} + +BOOL CReportCtrl::SetSortCallback(LPFNRVCOMPARE lpfnrvc) +{ + m_lpfnrvc = lpfnrvc; + return TRUE; +} + +LPFNRVCOMPARE CReportCtrl::GetSortCallback() +{ + return m_lpfnrvc; +} + + + +//********************************************** +//************************************************ +//************************************************ +//create a profile string for saving +BOOL CReportCtrl::WriteProfile(CString* strpProfile) +{ + CString str, strProfile; + + INT i; + INT iSubItems = m_arraySubItems.GetSize(); + INT iColumns = m_arrayColumns.GetSize(); + + strProfile.Format(_T("(%d,%d)"), iSubItems, iColumns); + + for(i=0;ilpszText != NULL); // Must supply (descriptive) text for subitem selector + ASSERT(_tcslen(lprvc->lpszText) < FLATHEADER_TEXT_MAX); + + try + { + SUBITEM subitem; + + subitem.nFormat = lprvc->nFormat; + subitem.iWidth = lprvc->iWidth<0 ? m_iDefaultWidth:lprvc->iWidth; + subitem.iMinWidth = lprvc->iMinWidth; + subitem.iMaxWidth = lprvc->iMaxWidth; + subitem.iImage = lprvc->nFormat&RVCF_IMAGE ? lprvc->iImage:0; + subitem.strText = lprvc->lpszText; + + m_arraySubItems.InsertAt(iColumn, subitem); + + HDITEM hdi; + hdi.mask = HDI_LPARAM; + + INT iHeaderItems = m_arrayColumns.GetSize(); + for(i=0;i= iColumn) + { + hdi.lParam++; + m_wndHeader.SetItem(i, &hdi); + } + + VERIFY(m_itemEdit.rdData.InsertSubItem(iColumn, -1, -1, -1, NULL)); + + if(!(m_dwStyle&RVS_OWNERDATA)) + { + INT iItems = GetItemCount(); + for(i=0;iUpdateList(); + + return iColumn; + } + catch(CMemoryException* e) + { + e->Delete(); + return -1; + } +} + +BOOL CReportCtrl::UndefineColumn(INT iColumn) +{ + ASSERT(iColumn >= 0); + ASSERT(iColumn < m_arraySubItems.GetSize()); // Specify a valid column + + VERIFY(!DeactivateColumn(iColumn)); + m_arraySubItems.RemoveAt(iColumn); + + HDITEM hdi; + hdi.mask = HDI_LPARAM; + + INT i; + INT iHeaderItems = m_arrayColumns.GetSize(); + for(i=0;i iColumn) + { + hdi.lParam--; + m_wndHeader.SetItem(i, &hdi); + } + + VERIFY(m_itemEdit.rdData.DeleteSubItem(iColumn)); + + if(!(m_dwStyle&RVS_OWNERDATA)) + { + INT iItems = GetItemCount(); + for(i=0;iUpdateList(); + + return TRUE; +} + + +INT CReportCtrl::InsertItem(INT iItem, LPTSTR lpszText, INT iImage, INT iCheck, INT iTextColor) +{ + RVITEM rvi; + rvi.nMask = RVIM_TEXT; + rvi.iItem = iItem; + rvi.iSubItem = 0; + rvi.lpszText = lpszText; + + rvi.iTextColor = iTextColor; + rvi.iImage = iImage; + rvi.iCheck = iCheck; + + if(iTextColor >= 0) + rvi.nMask |= RVIM_TEXTCOLOR; + + if(iImage >= 0) + rvi.nMask |= RVIM_IMAGE; + + if(iCheck >= 0) + rvi.nMask |= RVIM_CHECK; + + return InsertItem(&rvi); +} + +INT CReportCtrl::InsertItem(LPRVITEM lprvi) +{ + if(m_dwStyle&RVS_OWNERDATA) // Use set SetItemCount() when using this style + return RVI_INVALID; + + ASSERT(lprvi->iItem >= 0); // Use SetItem to set Edit row item + ASSERT(lprvi->iItem <= GetItemCount()); + ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize()); + + BOOL bInserted = FALSE; + + try + { + ITEM item; + item.rdData.New(m_arraySubItems.GetSize()); + + m_arrayItems.InsertAt(lprvi->iItem, item); bInserted = TRUE; + m_arrayRows.InsertAt(lprvi->iItem, INT_MIN); + + INT iItems = m_arrayRows.GetSize(); + for(INT i=0;i=lprvi->iItem) + m_arrayRows[i]++; + + m_arrayRows[lprvi->iItem] = lprvi->iItem; + + m_iVirtualHeight++; + + VERIFY(SetItem(lprvi)); + + ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT)); + return lprvi->iItem; + } + catch(CMemoryException* e) + { + if(bInserted) + m_arrayItems.RemoveAt(lprvi->iItem); + + e->Delete(); + return RVI_INVALID; + } +} + +BOOL CReportCtrl::DeleteItem(INT iItem) +{ + ASSERT(iItem <= GetItemCount()); + + if(m_dwStyle&RVS_OWNERDATA) // Use set SetItemCount() when using this style + return FALSE; + + RVITEM rvi; + rvi.nMask = RVIM_LPARAM; + rvi.iItem = iItem; + GetItem(&rvi); + Notify(RVN_ITEMDELETED, iItem, 0, 0, rvi.lParam); + + m_arrayItems.RemoveAt(iItem); + + INT iRows = m_arrayRows.GetSize(); + for(INT i=0;i iItem) + m_arrayRows[i]--; + } + + m_iVirtualHeight--; + m_iFocusRow = m_iFocusRow >= m_iVirtualHeight ? m_iVirtualHeight-1 : m_iFocusRow; + + INT iItems = GetItemCount(); + INT iFirst = GetScrollPos32(SB_VERT), iLast; + GetVisibleRows(TRUE, &iFirst, &iLast); + + if(iItem<=iFirst || iLast>=iItems-1) + GetVisibleRows(TRUE, &iFirst, &iLast, TRUE); + + ScrollWindow(SB_VERT, iFirst); + return TRUE; +} + +BOOL CReportCtrl::DeleteAllItems() +{ + if(m_dwStyle&RVS_OWNERDATA) // Use set SetItemCount() when using this style + return FALSE; + + RVITEM rvi; + for (int iItem = 0; iItem < GetItemCount(); iItem++) + { + rvi.nMask = RVIM_LPARAM; + rvi.iItem = iItem; + GetItem(&rvi); + Notify(RVN_ITEMDELETED, iItem, 0, 0, rvi.lParam); + } + + m_arrayRows.RemoveAll(); + m_arrayItems.RemoveAll(); + m_iVirtualHeight = 0; + m_iFocusRow = RVI_INVALID; + + ScrollWindow(SB_VERT, 0); + return TRUE; +} + +void CReportCtrl::RedrawItems(INT iFirst, INT iLast) +{ + // TODO: Optimize to redraw indivual rows + // taking into account that the row height + // may have changed. Redrawing everything + // will work as well :) + + if(iFirst == RVI_EDIT) + InvalidateRect(m_rectEdit); + + InvalidateRect(m_rectReport); +} + +BOOL CReportCtrl::EnsureVisible(INT iItem, BOOL bUnobstructed) +{ + INT iFirst = GetScrollPos32(SB_VERT), iLast; + INT iRow = GetRowFromItem(iItem); + if(iRow < 0) + return FALSE; + + GetVisibleRows(bUnobstructed, &iFirst, &iLast); + + if(iRowiLast) + { + iLast = iRow; + GetVisibleRows(bUnobstructed, &iFirst, &iLast, TRUE); + ScrollWindow(SB_VERT, iFirst); + } + + return TRUE; +} + +INT CReportCtrl::InsertColor(INT iIndex, COLORREF crColor) +{ + try + { + m_arrayColors.InsertAt(iIndex, crColor); + if(CreatePalette()) + return iIndex; + + return -1; + } + catch(CMemoryException* e) + { + e->Delete(); + return -1; + } +} + +BOOL CReportCtrl::DeleteColor(INT iIndex) +{ + if(iIndex >= m_arrayColors.GetSize()) + return FALSE; + + m_arrayColors.RemoveAt(iIndex); + CreatePalette(); + + return TRUE; +} + +INT CReportCtrl::HitTest(LPRVHITTESTINFO lprvhti) +{ + ASSERT(lprvhti); + + lprvhti->nFlags = 0; + lprvhti->iItem = RVI_INVALID; + lprvhti->iSubItem = -1; + + lprvhti->iRow = RVI_INVALID; + lprvhti->iColumn = -1; + + CRect rectItem = m_rectEdit; + rectItem.bottom -= GetSystemMetrics(SM_CYFIXEDFRAME)*2; + + if( + rectItem.PtInRect(lprvhti->point) || + m_rectReport.PtInRect(lprvhti->point) + ) { + INT iHPos = GetScrollPos32(SB_HORZ); + INT iFirst = GetScrollPos32(SB_VERT), iLast; + + BOOL bCheckItem = FALSE; + + if(rectItem.PtInRect(lprvhti->point)) + { + lprvhti->iItem = RVI_EDIT; + lprvhti->nFlags |= RVHT_ONITEMEDIT; + + bCheckItem = TRUE; + } + else if(!bCheckItem && GetVisibleRows(FALSE, &iFirst, &iLast)) + { + ITEM item; + rectItem.SetRect( + m_rectReport.left-iHPos, m_rectReport.top, + m_rectReport.left-iHPos+m_iVirtualWidth, m_rectReport.top + ); + + for(;iFirst<=iLast;iFirst++) + { + GetItemFromRow(iFirst, item); + rectItem.bottom += m_iDefaultHeight+item.nPreview; + + if(rectItem.PtInRect(lprvhti->point)) + break; + + rectItem.top = rectItem.bottom; + } + + if(iFirst<=iLast) + { + lprvhti->iItem = GetItemFromRow(iFirst); + lprvhti->iRow = iFirst; + + if(item.nPreview) + { + CRect rectPreview(rectItem); + rectPreview.top += m_iDefaultHeight; + + if(rectPreview.PtInRect(lprvhti->point)) + { + lprvhti->nFlags |= RVHT_ONITEMPREVIEW; + return lprvhti->iItem; + } + } + + bCheckItem = TRUE; + } + } + + if(bCheckItem) + { + INT iHeaderItem; + INT iHeaderItems = m_arrayColumns.GetSize(); + + HDITEM hdi; + hdi.mask = HDI_WIDTH|HDI_LPARAM; + + rectItem.right = rectItem.left; + + for(iHeaderItem=0;iHeaderItempoint)) + break; + + rectItem.left = rectItem.right; + } + + lprvhti->iSubItem = hdi.lParam; + lprvhti->iColumn = iHeaderItem; + + if(iHeaderItemiSubItem; + GetItem(&rvi); + + lprvhti->rect = rectItem; + lprvhti->rect.bottom = rectItem.top + m_iDefaultHeight; + + rectItem.right = rectItem.left+m_iSpacing; + if(rvi.nMask&RVIM_IMAGE) + { + rectItem.right += m_sizeImage.cx+m_iSpacing; + if(lprvhti->point.x < rectItem.right) + { + lprvhti->nFlags |= RVHT_ONITEMIMAGE; + return lprvhti->iItem; + } + } + + if(rvi.nMask&RVIM_CHECK) + { + rectItem.right += m_sizeCheck.cx+m_iSpacing; + if(lprvhti->point.x < rectItem.right) + { + lprvhti->nFlags |= RVHT_ONITEMCHECK; + return lprvhti->iItem; + } + } + + lprvhti->nFlags |= RVHT_ONITEMTEXT; + } + else + lprvhti->nFlags = RVHT_NOWHERE; + } + else + lprvhti->nFlags = RVHT_NOWHERE; + } + else + { + lprvhti->nFlags |= lprvhti->point.ynFlags |= lprvhti->point.y>m_rectReport.bottom ? RVHT_BELOW:0; + lprvhti->nFlags |= lprvhti->point.xnFlags |= lprvhti->point.x>m_rectReport.right ? RVHT_TORIGHT:0; + } + + return lprvhti->iItem; +} + +BOOL CReportCtrl::SortItems(INT iColumn, BOOL bAscending) +{ + INT iHeaderColumn = FindColumnInHeader(iColumn); + if(iHeaderColumn < 0 || m_dwStyle&RVS_OWNERDATA) + return FALSE; // Can't sort on columns that are not active + // Can't sort if data is managed by owner + + INT iFocusItem = GetItemFromRow(m_iFocusRow); + + INT iRows = m_arrayRows.GetSize(); + if(iRows>1) + { + for(INT i=0;i0) || + (!bAscending && iSort<0)) + { + INT iItem = m_arrayRows[i]; + m_arrayRows[i] = m_arrayRows[j]; + m_arrayRows[j] = iItem; + } + } + } + } + + m_wndHeader.SetSortColumn(m_arrayColumns[iHeaderColumn], bAscending); + + if(iFocusItem>=0) + { + m_iFocusRow = GetRowFromItem(iFocusItem); + + INT iFirst = m_iFocusRow, iLast; + GetVisibleRows(TRUE, &iFirst, &iLast); + GetVisibleRows(TRUE, &iFirst, &iLast, TRUE); + + ScrollWindow(SB_VERT, iFirst); + } + + Invalidate(); + + return TRUE; +} + +BOOL CReportCtrl::SortAllColumns(BOOL bAscending /*=TRUE*/) +{ + if(m_dwStyle&RVS_OWNERDATA) + return FALSE; // Can't sort if data is managed by owner + + // Save current position + INT iFocusItem = GetItemFromRow(m_iFocusRow); + + // Scan all the rows. + INT iRows = m_arrayRows.GetSize(); + if(iRows>1) + { + for(INT i=0;i0) || + (!bAscending && iSort<0)) + { + INT iItem = m_arrayRows[i]; + m_arrayRows[i] = m_arrayRows[j]; + m_arrayRows[j] = iItem; + } + + break; + } + } + } + } + + if(iFocusItem>=0) + { + m_iFocusRow = GetRowFromItem(iFocusItem); + + INT iFirst = m_iFocusRow, iLast; + GetVisibleRows(TRUE, &iFirst, &iLast); + GetVisibleRows(TRUE, &iFirst, &iLast, TRUE); + + ScrollWindow(SB_VERT, iFirst); + } + + Invalidate(); + + return TRUE; + +} + +INT CReportCtrl::CompareItems(INT iColumn, INT iItem1, INT iItem2) +{ + ASSERT(!(m_dwStyle&RVS_OWNERDATA)); // Can't sort if data is managed by owner + + if(m_lpfnrvc == NULL) + { + RVITEM rvi1, rvi2; + + TCHAR szText1[REPORTCTRL_MAX_TEXT], szText2[REPORTCTRL_MAX_TEXT]; + + rvi1.nMask = RVIM_TEXT; + rvi1.iItem = iItem1; + rvi1.iSubItem = iColumn; + rvi1.lpszText = szText1; + rvi1.iTextMax = REPORTCTRL_MAX_TEXT; + VERIFY(GetItem(&rvi1)); + + rvi2.nMask = RVIM_TEXT; + rvi2.iItem = iItem2; + rvi2.iSubItem = iColumn; + rvi2.lpszText = szText2; + rvi2.iTextMax = REPORTCTRL_MAX_TEXT; + VERIFY(GetItem(&rvi2)); + + if((!_tcslen(szText1)) && (!_tcslen(szText2))) + { + if(rvi1.iImage < rvi2.iImage) + return -1; + else if(rvi1.iImage > rvi2.iImage) + return 1; + else + return 0; + } + else + return _tcscmp(szText1, szText2); + } + else + return m_lpfnrvc(iColumn, iItem1, iItem2); +} + +///////////////////////////////////////////////////////////////////////////// +// CReportCtrl implementation + +void CReportCtrl::GetSysColors() +{ + m_crBackground = GetSysColor(COLOR_WINDOW); + m_crBkSelected = GetSysColor(COLOR_HIGHLIGHT); + m_crBkSelectedNoFocus = GetSysColor(COLOR_BTNFACE); + m_crText = GetSysColor(COLOR_WINDOWTEXT); + m_crTextSelected = GetSysColor(COLOR_HIGHLIGHTTEXT); + m_crTextSelectedNoFocus = GetSysColor(COLOR_WINDOWTEXT); + m_crGrid = GetSysColor(COLOR_BTNFACE); + m_cr3DFace = GetSysColor(COLOR_3DFACE); + m_cr3DHiLight = GetSysColor(COLOR_3DHILIGHT); + m_cr3DDkShadow = GetSysColor(COLOR_3DDKSHADOW); +} + +UINT CReportCtrl::GetMouseScrollLines() +{ + UINT nScrollLines = 3; // Reasonable default + HKEY hKey; + + if(RegOpenKeyEx( + HKEY_CURRENT_USER, _T("Control Panel\\Desktop"), + 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS + ) { + TCHAR szData[128]; + DWORD dwKeyDataType; + DWORD dwDataBufSize = sizeof(szData); + + if(RegQueryValueEx( + hKey, _T("WheelScrollLines"), NULL, &dwKeyDataType, + (LPBYTE) &szData, &dwDataBufSize) == ERROR_SUCCESS + ) + nScrollLines = _tcstoul(szData, NULL, 10); + + RegCloseKey(hKey); + } + + return nScrollLines; +} + +BOOL CReportCtrl::CreatePalette() +{ + if(m_palette.m_hObject) + m_palette.DeleteObject(); + + INT iUserColors = m_arrayColors.GetSize(); + INT iBitmapColors = 0; + + DIBSECTION ds; + BITMAPINFOHEADER &bmInfo = ds.dsBmih; + + if( (HBITMAP)m_bitmap != NULL ) + { + m_bitmap.GetObject( sizeof(ds), &ds ); + iBitmapColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount; + } + + INT iColors = iUserColors + iBitmapColors; + + if( !iColors ) + return FALSE; + + CClientDC cdc(NULL); + if( iColors <= 256 ) + { + UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * iColors); + LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; + + pLP->palVersion = 0x300; + pLP->palNumEntries = iColors; + + INT i; + for( i=0;ipalPalEntry[i].peRed = GetRValue(m_arrayColors[i]); + pLP->palPalEntry[i].peGreen = GetGValue(m_arrayColors[i]); + pLP->palPalEntry[i].peBlue = GetBValue(m_arrayColors[i]); + pLP->palPalEntry[i].peFlags = 0; + } + + if( iBitmapColors > 0 ) + { + // Create the palette + RGBQUAD *pRGB = new RGBQUAD[iBitmapColors]; + + CDC dc; + dc.CreateCompatibleDC(&cdc); + + dc.SelectObject( &m_bitmap ); + ::GetDIBColorTable( dc, 0, iColors, pRGB ); + + for( INT i=0;ipalPalEntry[iUserColors+i].peRed = pRGB[i].rgbRed; + pLP->palPalEntry[iUserColors+i].peGreen = pRGB[i].rgbGreen; + pLP->palPalEntry[iUserColors+i].peBlue = pRGB[i].rgbBlue; + pLP->palPalEntry[iUserColors+i].peFlags = 0; + } + + delete[] pRGB; + } + + m_palette.CreatePalette( pLP ); + + delete[] pLP; + } + else + m_palette.CreateHalftonePalette( &cdc ); + + return TRUE; +} + +BOOL CReportCtrl::Notify(UINT nCode, INT iItem, INT iSubItem, UINT nState, LPARAM lParam) +{ + NMREPORTVIEW nmrv; + nmrv.hdr.hwndFrom = GetSafeHwnd(); + nmrv.hdr.idFrom = GetDlgCtrlID(); + nmrv.hdr.code = nCode; + + nmrv.iItem = iItem; + nmrv.iSubItem = iSubItem; + nmrv.nState = nState; + + nmrv.lParam = lParam; + + CWnd* pWnd = GetParent(); + if(pWnd) + return pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrv); + + return FALSE; +} + +BOOL CReportCtrl::Notify(UINT nCode, UINT nKeys, LPRVHITTESTINFO lprvhti) +{ + NMREPORTVIEW nmrv; + nmrv.hdr.hwndFrom = GetSafeHwnd(); + nmrv.hdr.idFrom = GetDlgCtrlID(); + nmrv.hdr.code = nCode; + + nmrv.nKeys = nKeys; + nmrv.point = lprvhti->point; + nmrv.nFlags = lprvhti->nFlags; + + nmrv.iItem = lprvhti->iItem; + nmrv.iSubItem = lprvhti->iSubItem; + + if(lprvhti->iItem >= 0 && (!(m_dwStyle&RVS_OWNERDATA))) + nmrv.lParam = GetItemStruct(lprvhti->iItem, -1).lParam; + + CWnd* pWnd = GetParent(); + if(pWnd) + return pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrv); + + return FALSE; +} + +void CReportCtrl::Layout(INT cx, INT cy) +{ + HDLAYOUT hdl; + WINDOWPOS wpos; + + hdl.prc = &m_rectReport; + hdl.pwpos = &wpos; + + m_rectReport.SetRect(0, 0, cx, cy); + + if(IsWindow(m_wndHeader.GetSafeHwnd())) + { + m_wndTip.Hide(); + + if(!(m_dwStyle&RVS_NOHEADER)) + { + VERIFY(m_wndHeader.SendMessage(HDM_LAYOUT, 0, (LPARAM)&hdl)); + + m_rectHeader.SetRect(wpos.x, wpos.y, wpos.x+wpos.cx, wpos.y+wpos.cy); + } + else + m_rectHeader.SetRect(0, 0, cx, 0); + + m_rectTop = m_rectHeader; + + if(m_dwStyle&RVS_SHOWEDITROW) + { + UINT nFrameHeight = GetSystemMetrics(SM_CYFIXEDFRAME); + m_rectTop.bottom += m_iDefaultHeight + 2*nFrameHeight; + m_rectReport.top += m_iDefaultHeight + 2*nFrameHeight; + + m_rectEdit = m_rectTop; + m_rectEdit.top = m_rectHeader.bottom; + } + else + m_rectEdit.SetRectEmpty(); + + ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ)); + ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT)); + } +} + +CReportCtrl::ITEM& CReportCtrl::GetItemStruct(INT iItem, INT iSubItem, UINT nMask) +{ + if(m_dwStyle&RVS_OWNERDATA) + { + INT iSubItems = m_arraySubItems.GetSize(); + + ITEM item; + item.rdData.New(iSubItems); + + CWnd* pWnd = GetParent(); + if(pWnd) + { + NMRVITEMCALLBACK nmrvic; + nmrvic.hdr.hwndFrom = GetSafeHwnd(); + nmrvic.hdr.idFrom = GetDlgCtrlID(); + nmrvic.hdr.code = RVN_ITEMCALLBACK; + + nmrvic.item.iItem = iItem; + nmrvic.item.iSubItem = iSubItem; + nmrvic.item.nMask = nMask; + + TCHAR szText[REPORTCTRL_MAX_TEXT+1]; + memset(szText, 0, sizeof(szText)); + + if(iSubItem >= 0) + { + nmrvic.item.nMask |= RVIM_TEXT; + nmrvic.item.lpszText = szText; + nmrvic.item.iTextMax = REPORTCTRL_MAX_TEXT; + } + + pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvic); + + INT iColor = nmrvic.item.nMask&RVIM_TEXTCOLOR ? nmrvic.item.iTextColor:-1; + INT iImage = nmrvic.item.nMask&RVIM_IMAGE ? nmrvic.item.iImage:-1; + INT iCheck = nmrvic.item.nMask&RVIM_CHECK ? nmrvic.item.iCheck:-1; + + if(iSubItem >= 0) + item.rdData.SetSubItem(iSubItem, iImage, iCheck, iColor, szText); + + item.iBkColor = nmrvic.item.nMask&RVIM_BKCOLOR ? nmrvic.item.iBkColor:-1; + item.nPreview = nmrvic.item.nMask&RVIM_PREVIEW ? nmrvic.item.nPreview:0; + item.nState = nmrvic.item.nMask&RVIM_STATE ? nmrvic.item.nState:0; + } + + m_itemCache = item; + return m_itemCache; + } + + return iItem == RVI_EDIT ? m_itemEdit:m_arrayItems[iItem]; +} + +void CReportCtrl::SetItemStruct(INT iItem, ITEM& item) +{ + if(m_dwStyle&RVS_OWNERDATA) + return; + + if(iItem == RVI_EDIT) + m_itemEdit = item; + else + m_arrayItems[iItem] = item; +} + +INT CReportCtrl::GetItemFromRow(INT iRow) +{ + if(m_dwStyle&RVS_OWNERDATA) + return iRow; + + if(iRow == RVI_INVALID) + return RVI_INVALID; + + return iRow == RVI_EDIT ? RVI_EDIT:m_arrayRows[iRow]; +} + +INT CReportCtrl::GetItemFromRow(INT iRow, ITEM& item) +{ + if(m_dwStyle&RVS_OWNERDATA) + return iRow; + + if(iRow == RVI_INVALID) + return RVI_INVALID; + + INT iItem = GetItemFromRow(iRow); + item = GetItemStruct(iItem, -1); + return iItem; +} + +INT CReportCtrl::GetRowFromItem(INT iItem) +{ + if(iItem == RVI_EDIT || m_dwStyle&RVS_OWNERDATA) + return iItem; + + INT iRows = m_arrayRows.GetSize(); + for(INT iRow=0;iRow0;iRow++,iRows++) + { + iHeight -= m_iDefaultHeight + GetItemStruct(GetItemFromRow(iRow), -1).nPreview; + if(bUnobstructed && iHeight<=0) + break; + } + + if(lpiLast) + *lpiLast = iRow-1; + } + else + { + ASSERT(lpiFirst); + ASSERT(lpiLast); + + for(*lpiFirst=*lpiLast;*lpiFirst>=0&&iHeight>0;*lpiFirst-=1,iRows++) + { + iHeight -= m_iDefaultHeight+GetItemStruct(GetItemFromRow(*lpiFirst), -1).nPreview; + if(bUnobstructed && iHeight<=0) + break; + } + + *lpiFirst += 1; + } + + return iRows; +} + +void CReportCtrl::SelectRows(INT iFirst, INT iLast, BOOL bSelect, BOOL bKeepSelection, BOOL bInvert, BOOL bNotify) +{ + INT i; + + if(m_dwStyle&RVS_SINGLESELECT) + { + iLast = iFirst; + bKeepSelection = FALSE; + } + + if(m_iFocusRow > RVI_INVALID && iFirst != m_iFocusRow) + { + SetState(m_iFocusRow, 0, RVIS_FOCUSED); + RedrawItems(m_iFocusRow); + } + + m_iFocusRow = iFirst; + SetState(iFirst, RVIS_FOCUSED, RVIS_FOCUSED); + + if(iFirst > iLast) + { + iLast += iFirst; + iFirst = iLast - iFirst; + iLast -= iFirst; + } + + if(bSelect) + { + for(i=iFirst;i<=iLast;i++) + { + INT iItem = GetItemFromRow(i); + UINT nOldState, nNewState; + + nOldState = nNewState = GetState(i); + + if(bInvert) + nNewState ^= RVIS_SELECTED; + else + nNewState |= RVIS_SELECTED; + + if(nNewState != nOldState) + { + if(bNotify && Notify(RVN_SELECTIONCHANGING, iItem, -1, nNewState)) + continue; + + SetState(i, nNewState, RVIS_SELECTED); + + if(bNotify) + Notify(RVN_SELECTIONCHANGED, iItem, -1, nNewState); + } + } + + RedrawItems(iFirst, iLast); + } + else + RedrawItems(iFirst); + + + if(!bKeepSelection && bSelect) + { + INT iRows = m_iVirtualHeight; + for(i=RVI_EDIT;iiLast) && nOldState&RVIS_SELECTED) + { + nNewState &= ~RVIS_SELECTED; + + if(nNewState != nOldState) + { + if(bNotify && Notify(RVN_SELECTIONCHANGING, iItem, -1, nNewState)) + continue; + + SetState(i, nNewState, RVIS_SELECTED); + + if(bNotify) + Notify(RVN_SELECTIONCHANGED, iItem, -1, nNewState); + + RedrawItems(i); + } + } + } + } +} + +INT CReportCtrl::GetScrollPos32(INT iBar, BOOL bGetTrackPos) +{ + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + + if(bGetTrackPos) + { + if(GetScrollInfo(iBar, &si, SIF_TRACKPOS)) + return si.nTrackPos; + } + else + { + if(GetScrollInfo(iBar, &si, SIF_POS)) + return si.nPos; + } + + return 0; +} + +BOOL CReportCtrl::SetScrollPos32(INT iBar, INT iPos, BOOL bRedraw) +{ + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS; + si.nPos = iPos; + + return SetScrollInfo(iBar, &si, bRedraw); +} + +void CReportCtrl::ScrollWindow(INT iBar, INT iPos) +{ + if(m_rectReport.Width()<=0 || m_rectReport.Height()<=0) + return; + + m_wndTip.Hide(); + + if(iBar == SB_HORZ) + { + SCROLLINFO si; + INT iWidth = m_rectReport.Width(); + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_PAGE|SIF_RANGE|SIF_POS; + si.nPage = iWidth; + si.nMin = 0; + si.nMax = iWidth= 0 && iPos<=iItems); + + INT iFirst = iPos, iLast; + GetVisibleRows(TRUE, &iFirst, &iLast); + + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_PAGE|SIF_RANGE|SIF_POS; + si.nPage = (iLast - iFirst + 1); + si.nMin = 0; + si.nMax = (iLast - iFirst + 1) -1) + { + INT iWidth = m_rectReport.Width(); + INT iPos = GetScrollPos(SB_HORZ); + INT iOffset = 0; + + HDITEM hdi; + hdi.mask = HDI_WIDTH|HDI_LPARAM; + + for(INT i=0;i iPos+iWidth || iOffset < iPos) + ScrollWindow(SB_HORZ, iOffset); + } +} + +void CReportCtrl::DrawCtrl(CDC* pDC) +{ + CRect rectClip; + if (pDC->GetClipBox(&rectClip) == ERROR) + return; + + INT iHPos = GetScrollPos32(SB_HORZ); + INT iVPos = GetScrollPos32(SB_VERT); + + DrawBkgnd(pDC, rectClip, m_crBackground); + + CPen pen(m_iGridStyle, 1, m_crGrid); + CPen* pPen = pDC->SelectObject(&pen); + + CFont* pFont = pDC->SelectObject(GetFont()); + + pDC->SetBkMode(TRANSPARENT); + + CRect rect; + CRect rectRow(m_rectReport.left-iHPos, m_rectReport.top, m_rectReport.left-iHPos+m_iVirtualWidth, m_rectReport.top); + + TCHAR szText[REPORTCTRL_MAX_TEXT]; + RVITEM rvi; + rvi.nMask = RVIM_TEXT; + rvi.lpszText = szText; + rvi.iTextMax = REPORTCTRL_MAX_TEXT; + + NMRVDRAWPREVIEW nmrvdp; + nmrvdp.hdr.hwndFrom = GetSafeHwnd(); + nmrvdp.hdr.idFrom = GetDlgCtrlID(); + nmrvdp.hdr.code = RVN_ITEMDRAWPREVIEW; + nmrvdp.hDC = pDC->m_hDC; + + CWnd* pwndParent = GetParent(); + + INT iRows = m_iVirtualHeight; + INT iColumns = m_wndHeader.GetItemCount(); + + ASSERT(iColumns>0); // Make sure that always one column is active + + if(m_bColumnsReordered) + { + LPINT lpi; + + m_iFocusColumn = m_iFocusColumn >= iColumns ? iColumns-1:m_iFocusColumn; + + m_arrayColumns.SetSize(iColumns, 8); + lpi = m_arrayColumns.GetData(); + if(!m_wndHeader.GetOrderArray(lpi, iColumns)) + return; + + if(m_lprclc != NULL) + m_lprclc->UpdateList(); + + m_bColumnsReordered = FALSE; + } + + if(m_dwStyle&RVS_SHOWEDITROW) + { + GetClientRect(rect); + rect.bottom = m_rectEdit.bottom; + rect.top = rect.bottom - GetSystemMetrics(SM_CYFIXEDFRAME)*2; + pDC->FillSolidRect(rect, m_cr3DFace); + pDC->Draw3dRect(rect, m_cr3DHiLight, m_cr3DDkShadow); + + rvi.iItem = -1; + rvi.nMask = RVIM_TEXT; + GetItem(&rvi); + + rect = m_rectEdit; + rect.bottom -= GetSystemMetrics(SM_CYFIXEDFRAME)*2; + rect.OffsetRect(-iHPos, 0); + + DrawRow(pDC, rect, rectClip, RVI_EDIT, &rvi, FALSE); + + if(m_bFocus && m_hEditWnd == NULL && m_iFocusRow == RVI_EDIT && m_iFocusColumn == -1) + { + if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID)) + rect.DeflateRect(1, 0, 1, 0); + + pDC->SetBkColor(m_crBackground); + pDC->SetTextColor(m_crText); + pDC->DrawFocusRect(rect); + } + } + + if(!iRows) + { + rectRow.top += 2; + rectRow.bottom = rectRow.top + m_iDefaultHeight; + + GetClientRect(rect); + rect.top = rectRow.top; + rect.bottom = rectRow.bottom; + + if(rectRow.Width() < rect.Width()) + rect = rectRow; + + pDC->SetTextColor(m_crText); + pDC->DrawText(m_strNoItems, rect, DT_CENTER|DT_END_ELLIPSIS); + return; + } + + INT iRow = iVPos; + while(iRow= rectClip.top) + { + DrawRow(pDC, rectRow, rectClip, iRow, &rvi, iRow&1); + + if(rvi.nMask&RVIM_PREVIEW && rvi.nPreview && pwndParent) + { + nmrvdp.iItem = rvi.iItem; + nmrvdp.nState = rvi.nState; + nmrvdp.rect = rectRow; + nmrvdp.rect.top += m_iDefaultHeight; + nmrvdp.lParam = rvi.lParam; + + pwndParent->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvdp); + } + + if(m_dwStyle&RVS_SHOWHGRID) + { + pDC->MoveTo(rectRow.left, rectRow.bottom-1); + pDC->LineTo(rectRow.right, rectRow.bottom-1); + } + + if(m_bFocus && m_hEditWnd == NULL && m_iFocusRow == iRow && m_iFocusColumn == -1) + { + if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID)) + rectRow.DeflateRect(1, 0, 1, 1); + + pDC->SetBkColor(m_crBackground); + pDC->SetTextColor(m_crText); + pDC->DrawFocusRect(rectRow); + + if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID)) + rectRow.InflateRect(1, 0, 1, 1); + } + } + + rectRow.top = rectRow.bottom; + iRow++; + } + + rectRow.top = m_rectReport.top; + rectRow.bottom = + m_rectReport.bottomMoveTo(rectRow.left, m_rectReport.top); + pDC->LineTo(rectRow.left, m_rectReport.bottom); + + pDC->MoveTo(rectRow.right-1, m_rectReport.top); + pDC->LineTo(rectRow.right-1, m_rectReport.bottom); + } + else + { + pDC->MoveTo(rectRow.left, rectRow.top); + pDC->LineTo(rectRow.left, rectRow.bottom); + + pDC->MoveTo(rectRow.right-1, rectRow.top); + pDC->LineTo(rectRow.right-1, rectRow.bottom); + } + } + + if(m_dwStyle&RVS_SHOWHGRID && m_dwStyle&RVS_SHOWHGRIDEX && iRow>=iRows) + { + while(rectRow.bottomMoveTo(rectRow.left, rectRow.bottom-1); + pDC->LineTo(rectRow.right, rectRow.bottom-1); + + rectRow.bottom += m_iDefaultHeight; + } + } + + if(m_dwStyle&RVS_SHOWVGRID) + { + for(INT iColumn=0;iColumnMoveTo(rectRow.left-1, rectRow.top); + pDC->LineTo(rectRow.left-1, rectRow.bottom); + } + } + + pDC->SelectObject(pFont); + pDC->SelectObject(pPen); + + pen.DeleteObject(); +} + +void CReportCtrl::DrawRow(CDC* pDC, CRect rectRow, CRect rectClip, INT iRow, LPRVITEM lprvi, BOOL bAlternate) +{ + INT iColumns = m_wndHeader.GetItemCount(); + + // You have to insert at least 1 color to use color alternate style. + ASSERT(!(m_dwStyle&RVS_SHOWCOLORALTERNATE && !m_arrayColors.GetSize())); + + COLORREF crItem; + crItem = (m_dwStyle&RVS_SHOWCOLORALTERNATE && bAlternate) ? m_arrayColors[0]:m_crBackground; + crItem = lprvi->iBkColor>=0 ? m_arrayColors[lprvi->iBkColor]:crItem; + if(lprvi->nState&RVIS_SELECTED) + { + if(m_bFocus) + crItem = m_crBkSelected; + else + if(m_dwStyle&RVS_SHOWSELALWAYS) + crItem = m_crBkSelectedNoFocus; + } + + if(m_bitmap.m_hObject == NULL || crItem != m_crBackground || iRow == RVI_EDIT) + { + pDC->FillSolidRect(rectRow, crItem); + pDC->SetBkColor(crItem); + } + + if(lprvi->nState&RVIS_BOLD) + pDC->SelectObject(&m_fontBold); + + CRect rectItem(rectRow.left, rectRow.top, rectRow.left, rectRow.top+m_iDefaultHeight); + for(INT iColumn=0;iColumniSubItem = hdi.lParam; + rectItem.right = rectItem.left + hdi.cxy; + if(rectItem.right > rectClip.left) + { + lprvi->nMask = RVIM_TEXT; + VERIFY(GetItem(lprvi)); + + COLORREF crText = lprvi->nMask&RVIM_TEXTCOLOR ? m_arrayColors[lprvi->iTextColor]:m_crText; + if(lprvi->nState&RVIS_SELECTED) + { + if(m_bFocus) + crText = (m_dwStyle&RVS_SHOWCOLORALWAYS && lprvi->nMask&RVIM_TEXTCOLOR) ? crText:m_crTextSelected; + else + if(m_dwStyle&RVS_SHOWSELALWAYS) + crText = lprvi->nMask&RVIM_TEXTCOLOR && m_dwStyle&RVS_SHOWCOLORALWAYS ? crText:m_crTextSelectedNoFocus; + } + + if(m_iFocusRow == iRow && m_iFocusColumn == iColumn) + { + pDC->FillSolidRect(rectItem, m_crBackground); + crText = m_crText; + } + + pDC->SetTextColor(crText); + + rectItem.DeflateRect(m_iSpacing, 0); + DrawItem(pDC, rectItem, lprvi); + rectItem.InflateRect(m_iSpacing, 0); + + if(m_bFocus && m_hEditWnd == NULL && m_iFocusRow == iRow && m_iFocusColumn == iColumn) + { + if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID)) + rectItem.DeflateRect(1, 0, 1, 1); + + pDC->SetBkColor(m_crBackground); + pDC->SetTextColor(m_crText); + pDC->DrawFocusRect(rectItem); + + if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID)) + rectItem.InflateRect(1, 0, 1, 1); + } + } + rectItem.left = rectItem.right; + } + + if(lprvi->nState&RVIS_BOLD) + pDC->SelectObject(GetFont()); +} + +void CReportCtrl::DrawItem(CDC* pDC, CRect rect, LPRVITEM lprvi) +{ + INT iWidth = 0; + + rect.left += (iWidth = DrawImage(pDC, rect, lprvi)) ? iWidth+m_iSpacing : 0; + if(lprvi->nMask&RVIM_IMAGE && !iWidth) + return; + rect.left += (iWidth = DrawCheck(pDC, rect, lprvi)) ? iWidth+m_iSpacing : 0; + if(lprvi->nMask&RVIM_CHECK && !iWidth) + return; + DrawText(pDC, rect, lprvi); +} + +INT CReportCtrl::DrawImage(CDC* pDC, CRect rect, LPRVITEM lprvi) +{ + CImageList* pImageList = GetImageList(); + INT iWidth = 0; + + if(lprvi->nMask&RVIM_IMAGE) + { + ASSERT(pImageList); + ASSERT(lprvi->iImage>=0 && lprvi->iImageGetImageCount()); + + if(rect.Width()>0) + { + POINT point; + + point.y = rect.CenterPoint().y - (m_sizeImage.cy>>1); + point.x = rect.left; + + SIZE size; + size.cx = rect.Width()DrawIndirect(pDC, lprvi->iImage, point, size, CPoint(0, 0)); + + iWidth = m_sizeImage.cx; + } + } + else + iWidth = m_arraySubItems[lprvi->iSubItem].nFormat&RVCF_SUBITEM_IMAGE ? m_sizeImage.cx:0; + + return iWidth; +} + +INT CReportCtrl::DrawCheck(CDC* pDC, CRect rect, LPRVITEM lprvi) +{ + INT iWidth = 0; + + if(lprvi->nMask&RVIM_CHECK) + { + if(rect.Width()>m_sizeCheck.cx) + { + rect.top = rect.CenterPoint().y - (m_sizeCheck.cy>>1); + rect.left = rect.left; + rect.bottom = rect.top + m_sizeCheck.cx; + rect.right = rect.left + m_sizeCheck.cy; + + pDC->FillSolidRect(rect, m_crBackground); // Fixes visual problem with bigger fonts + pDC->DrawFrameControl( + rect, + DFC_BUTTON, + DFCS_BUTTONCHECK|DFCS_FLAT|(lprvi->iCheck?DFCS_CHECKED:0) + ); + + iWidth = m_sizeCheck.cx; + } + } + else + iWidth = m_arraySubItems[lprvi->iSubItem].nFormat&RVCF_SUBITEM_CHECK ? m_sizeCheck.cx:0; + + return iWidth; +} + +INT CReportCtrl::DrawText(CDC* pDC, CRect rect, LPRVITEM lprvi) +{ + CSize size; + + if(rect.Width()>0 && lprvi->nMask&RVIM_TEXT) + { + size = pDC->GetTextExtent(lprvi->lpszText); + + switch(m_arraySubItems[lprvi->iSubItem].nFormat&HDF_JUSTIFYMASK) + { + case HDF_LEFT: + case HDF_LEFT|HDF_RTLREADING: + pDC->DrawText(lprvi->lpszText, -1, rect, DT_LEFT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER); + break; + case HDF_CENTER: + case HDF_CENTER|HDF_RTLREADING: + pDC->DrawText(lprvi->lpszText, -1, rect, DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER); + break; + case HDF_RIGHT: + case HDF_RIGHT|HDF_RTLREADING: + pDC->DrawText(lprvi->lpszText, -1, rect, DT_RIGHT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER); + break; + } + } + + size.cx = rect.Width()>size.cx ? size.cx:rect.Width(); + return size.cx>0 ? size.cx:0; +} + +BOOL CReportCtrl::DrawBkgnd(CDC* pDC, CRect rect, COLORREF crBackground) +{ + if(m_bitmap.m_hObject != NULL) + { + CDC dc; + CRgn rgnBitmap; + CRect rectBitmap; + + dc.CreateCompatibleDC(pDC); + dc.SelectObject(&m_bitmap); + + rect.IntersectRect(rect, m_rectReport); + + INT iHPos = GetScrollPos32(SB_HORZ); + rectBitmap.top = rect.top - rect.top%m_sizeBitmap.cy; + rectBitmap.bottom = rect.top + m_sizeBitmap.cy; + rectBitmap.left = rect.left - (rect.left+iHPos)%m_sizeBitmap.cx; + rectBitmap.right = rect.left + m_sizeBitmap.cx; + + INT x, y; + for(x = rectBitmap.left; x < rect.right; x += m_sizeBitmap.cx) + for(y = rectBitmap.top; y < rect.bottom; y += m_sizeBitmap.cy) + pDC->BitBlt(x, y, m_sizeBitmap.cx, m_sizeBitmap.cy, &dc, 0, 0, SRCCOPY); + + return TRUE; + } + + pDC->FillSolidRect(rect, crBackground); + return FALSE; +} + +BOOL CReportCtrl::BeginEdit(INT iRow, INT iColumn, UINT nKey) +{ + if(iRow == RVI_INVALID || iColumn == -1) + return FALSE; + + TCHAR szText[REPORTCTRL_MAX_TEXT]; + + m_iEditItem = GetItemFromRow(iRow); + m_iEditSubItem = GetSubItemFromColumn(iColumn); + + // Make sure that the item to edit actually exists + ASSERT(m_iEditItem != RVI_INVALID && m_iEditSubItem != -1); + + RVITEM rvi; + rvi.iItem = m_iEditItem; + rvi.iSubItem = m_iEditSubItem; + rvi.nMask = RVIM_TEXT|RVIM_STATE|RVIM_LPARAM; + rvi.lpszText = szText; + rvi.iTextMax = REPORTCTRL_MAX_TEXT; + GetItem(&rvi); + + if(rvi.nState&RVIS_READONLY) + return FALSE; + + NMRVITEMEDIT nmrvie; + nmrvie.hdr.hwndFrom = GetSafeHwnd(); + nmrvie.hdr.idFrom = GetDlgCtrlID(); + nmrvie.hdr.code = RVN_BEGINITEMEDIT; + + nmrvie.iItem = m_iEditItem; + nmrvie.iSubItem = m_iEditSubItem; + + nmrvie.hWnd = NULL; + if(!GetItemRect(m_iEditItem, m_iEditSubItem, &nmrvie.rect)) + return FALSE; + + nmrvie.nKey = nKey; + if(rvi.nMask&RVIM_TEXT) + nmrvie.lpszText = szText; + + nmrvie.lParam = rvi.lParam; + + BOOL bResult = FALSE; + CWnd* pWnd = GetParent(); + if(pWnd != NULL) + bResult = pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie); + + if(!bResult) + { + if(!(rvi.nMask&RVIM_TEXT)) + return FALSE; + + if(!GetItemRect(m_iEditItem, m_iEditSubItem, &nmrvie.rect, RVIR_TEXT)) + return FALSE; + + CReportEditCtrl* pWnd= new CReportEditCtrl(m_iEditItem, m_iEditSubItem); + if(pWnd == NULL) + return FALSE; + + if(!pWnd->Create( + WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL, + nmrvie.rect, + this, + 0) + ) { + delete pWnd; + return FALSE; + } + + pWnd->SetFont( + rvi.nMask&RVIM_STATE && rvi.nState&RVIS_BOLD + ? + &m_fontBold:&m_font + ); + pWnd->SetWindowText(szText); + + switch (nKey){ + case VK_LBUTTON: + case VK_RETURN: + pWnd->SetSel((INT)_tcslen(szText), -1); + break; + case VK_BACK: + pWnd->SetSel((INT)_tcslen(szText), -1); + pWnd->SendMessage(WM_CHAR, nKey); + break; + case VK_TAB: + case VK_DOWN: + case VK_UP: + case VK_RIGHT: + case VK_LEFT: + case VK_NEXT: + case VK_PRIOR: + case VK_HOME: + case VK_SPACE: + case VK_END: + pWnd->SetSel(0,-1); + break; + default: + pWnd->SetSel(0,-1); + pWnd->SendMessage(WM_CHAR, nKey); + break; + } + + m_hEditWnd = pWnd->GetSafeHwnd(); + } + else + { + if(nmrvie.hWnd == NULL) + return FALSE; + + m_hEditWnd = nmrvie.hWnd; + } + + if(m_hEditWnd != NULL) + ::SetFocus(m_hEditWnd); + + return TRUE; +} + +void CReportCtrl::EndEdit(BOOL bUpdate, LPNMRVITEMEDIT lpnmrvie) +{ + if(!(m_dwStyle&RVS_OWNERDATA) && bUpdate) + { + if(lpnmrvie == NULL) + { + TCHAR szText[REPORTCTRL_MAX_TEXT]; + + INT i = ::GetWindowText(m_hEditWnd, szText, REPORTCTRL_MAX_TEXT-1); + szText[REPORTCTRL_MAX_TEXT-1] = 0; + + if(i || !::GetLastError()) + SetItemText(m_iEditItem, m_iEditSubItem, szText); + } + else + SetItemText(m_iEditItem, m_iEditSubItem, lpnmrvie->lpszText); + } + + if(IsWindow(m_hEditWnd)) + ::PostMessage(m_hEditWnd, WM_CLOSE, 0, 0); + m_hEditWnd = NULL; + + CWnd* pWnd = GetFocus(); + if(pWnd) + { + if(pWnd->GetSafeHwnd() != m_hWnd) + m_bFocus = FALSE; + } + + RedrawItems(m_iFocusRow, m_iFocusRow); +} + +///////////////////////////////////////////////////////////////////////////// +// CReportCtrl message handlers + +BOOL CReportCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + SetCursor(::LoadCursor(NULL, IDC_ARROW)); + return CWnd::OnSetCursor(pWnd, nHitTest, message); +} + +void CReportCtrl::OnSetFocus(CWnd* pOldWnd) +{ + CWnd::OnSetFocus(pOldWnd); + + m_bFocus = TRUE; + Invalidate(); +} + +void CReportCtrl::OnKillFocus(CWnd* pNewWnd) +{ + CWnd::OnKillFocus(pNewWnd); + + if(pNewWnd) + { + if(pNewWnd->m_hWnd != m_hEditWnd) + m_bFocus = FALSE; + } + else + m_bFocus = FALSE; + + Invalidate(); +} + +void CReportCtrl::OnSysColorChange() +{ + CWnd::OnSysColorChange(); + GetSysColors(); +} + +void CReportCtrl::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) +{ + CWnd::OnSettingChange(uFlags, lpszSection); + + m_nRowsPerWheelNotch = GetMouseScrollLines(); +} + +BOOL CReportCtrl::OnQueryNewPalette() +{ + Invalidate(); + return CWnd::OnQueryNewPalette(); +} + +void CReportCtrl::OnPaletteChanged(CWnd* pFocusWnd) +{ + CWnd::OnPaletteChanged(pFocusWnd); + + if(pFocusWnd->GetSafeHwnd() != GetSafeHwnd()) + Invalidate(); +} + +void CReportCtrl::OnSize(UINT nType, int cx, int cy) +{ + if(m_hEditWnd != NULL) + EndEdit(); + + CWnd::OnSize(nType, cx, cy); + + CRect rect; + GetClientRect(rect); + + Layout(rect.Width(), rect.Height()); +} + +LRESULT CReportCtrl::OnGetFont(WPARAM wParam, LPARAM lParam) +{ + return (LRESULT)m_font.m_hObject; +} + +LRESULT CReportCtrl::OnSetFont(WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult = Default(); + + CFont *pFont = CFont::FromHandle((HFONT)wParam); + if(pFont) + { + LOGFONT lf; + pFont->GetLogFont(&lf); + + m_font.DeleteObject(); + m_font.CreateFontIndirect(&lf); + + lf.lfWeight = FW_BOLD; + m_fontBold.DeleteObject(); + m_fontBold.CreateFontIndirect(&lf); + } + + CDC* pDC = GetDC(); + if (pDC) + { + CFont* pFont = pDC->SelectObject(&m_font); + TEXTMETRIC tm; + pDC->GetTextMetrics(&tm); + pDC->SelectObject(pFont); + ReleaseDC(pDC); + + m_iDefaultHeight = tm.tmHeight + tm.tmExternalLeading + 2; + m_iDefaultHeight += m_dwStyle&RVS_SHOWHGRID ? 1:0; + + m_sizeCheck.cx = m_iDefaultHeight-2; + m_sizeCheck.cy = m_iDefaultHeight-2; + } + + if(::IsWindow(GetSafeHwnd()) && lParam) + { + CRect rect; + GetClientRect(rect); + + Layout(rect.Width(), rect.Height()); + } + + return lResult; +} + + +BOOL CReportCtrl::OnEraseBkgnd(CDC* pDC) +{ + return TRUE; +} + +void CReportCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) +{ + LONG lStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); + + if(lStyle & WS_BORDER) + ::InflateRect(&lpncsp->rgrc[0], -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE)); + + Default(); +} + +void CReportCtrl::OnNcPaint() +{ + Default(); + + LONG lStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); + if(lStyle & WS_BORDER) + { + CWindowDC dc(this); + CRect rcBounds; + GetWindowRect(rcBounds); + ScreenToClient(rcBounds); + rcBounds.OffsetRect(-rcBounds.left, -rcBounds.top); + dc.DrawEdge(rcBounds, EDGE_SUNKEN, BF_RECT); + } +} + +void CReportCtrl::OnPaint() +{ + CPaintDC dc(this); + + CPalette* pPalette = NULL; + if(dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE) + { + pPalette = dc.SelectPalette(&m_palette, FALSE); + dc.RealizePalette(); + } + + dc.ExcludeClipRect(m_rectHeader); + + if(m_bDoubleBuffer) + { + CMemDC MemDC(&dc); + DrawCtrl(&MemDC); + + if(m_hEditWnd != NULL) + { + RECT rect; + ::GetWindowRect(m_hEditWnd, &rect); + + ScreenToClient(&rect); + dc.ExcludeClipRect(&rect); + } + } + else + DrawCtrl(&dc); + + if(pPalette && dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE) + dc.SelectPalette(pPalette, FALSE); +} + +void CReportCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + INT iScrollPos = GetScrollPos32(SB_HORZ); + INT iScroll; + + if(m_hEditWnd != NULL) + EndEdit(); + + switch (nSBCode) + { + case SB_LINERIGHT: + iScroll = min(m_iVirtualWidth-(m_rectReport.Width()+iScrollPos), m_rectReport.Width()>>3); + ScrollWindow(SB_HORZ, iScrollPos + iScroll); + break; + + case SB_LINELEFT: + iScroll = min(iScrollPos, m_rectReport.Width()>>3); + ScrollWindow(SB_HORZ, iScrollPos - iScroll); + break; + + case SB_PAGERIGHT: + iScrollPos = min(m_iVirtualWidth, iScrollPos + m_rectReport.Width()); + ScrollWindow(SB_HORZ, iScrollPos); + break; + + case SB_PAGELEFT: + iScrollPos = max(0, iScrollPos - m_rectReport.Width()); + ScrollWindow(SB_HORZ, iScrollPos); + break; + + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + iScrollPos = nPos; + ScrollWindow(SB_HORZ, iScrollPos); + break; + + case SB_RIGHT: + ScrollWindow(SB_HORZ, m_iVirtualWidth); + break; + + case SB_LEFT: + ScrollWindow(SB_HORZ, 0); + break; + + default: + break; + } +} + +void CReportCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + INT iFirst = GetScrollPos32(SB_VERT), iLast; + INT iItems = GetVisibleRows(TRUE, &iFirst, &iLast); + + if(m_hEditWnd != NULL) + EndEdit(); + + switch(nSBCode) + { + case SB_LINEUP: + if(iFirst>0) + iFirst--; + break; + + case SB_LINEDOWN: + if(iFirst+iItems < m_iVirtualHeight) + iFirst++; + break; + + case SB_PAGEUP: + GetVisibleRows(TRUE, &iLast, &iFirst, TRUE); + iFirst = iLast-1; + iFirst = iFirst<0 ? 0:iFirst; + break; + + case SB_PAGEDOWN: + iFirst += iItems; + GetVisibleRows(TRUE, &iFirst, &iLast); + GetVisibleRows(TRUE, &iFirst, &iLast, TRUE); + break; + + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + iFirst = nPos; + GetVisibleRows(TRUE, &iFirst, &iLast); + GetVisibleRows(TRUE, &iFirst, &iLast, TRUE); + break; + + case SB_TOP: + iFirst = 0; + break; + + case SB_BOTTOM: + iLast = m_iVirtualHeight-1; + GetVisibleRows(TRUE, &iFirst, &iLast, TRUE); + break; + + default: + return; + } + + ScrollWindow(SB_VERT, iFirst); +} + +void CReportCtrl::OnLButtonDown(UINT nFlags, CPoint point) +{ + SetFocus(); + + RVHITTESTINFO rvhti; + rvhti.point = point; + + HitTest(&rvhti); + + if(Notify(RVN_ITEMCLICK, nFlags, &rvhti)) + { + CWnd::OnLButtonDown(nFlags, point); + return; + } + + INT iFocusRow = m_iFocusRow, iFocusColumn = m_iFocusColumn; + m_iFocusColumn = m_dwStyle&RVS_FOCUSSUBITEMS? rvhti.iColumn:-1; + + if(rvhti.iItem >= -1) + { + INT iRow = GetRowFromItem(rvhti.iItem); + ASSERT(iRow >= -1); + + switch(nFlags&(MK_CONTROL|MK_SHIFT)) + { + case MK_CONTROL: + SelectRows(iRow, iRow, TRUE, TRUE, TRUE); + m_iSelectRow = iRow; + break; + + case MK_SHIFT: + SelectRows(m_iSelectRow, iRow, TRUE); + break; + + case MK_CONTROL|MK_SHIFT: + SelectRows(m_iSelectRow, iRow, TRUE, TRUE); + m_iSelectRow = iRow; + break; + + default: + SelectRows(iRow, iRow, TRUE); + m_iSelectRow = iRow; + + if(m_iFocusRow == iFocusRow && m_iFocusColumn == iFocusColumn) + BeginEdit(m_iFocusRow, m_iFocusColumn, VK_LBUTTON); + break; + } + } +} + +void CReportCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + RVHITTESTINFO rvhti; + rvhti.point = point; + + HitTest(&rvhti); + + if(Notify(RVN_ITEMDBCLICK, nFlags, &rvhti)) + { + CWnd::OnLButtonDblClk(nFlags, point); + return; + } +} + +UINT CReportCtrl::OnGetDlgCode() +{ + return DLGC_WANTARROWS; +} + +void CReportCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + INT iFirst = GetScrollPos32(SB_VERT), iLast; + GetVisibleRows(TRUE, &iFirst, &iLast); + + switch (nChar) + { + case VK_SPACE: + SelectRows(m_iFocusRow, m_iFocusRow, TRUE, TRUE, IsCtrlDown() ? TRUE:FALSE); + return; + + case VK_LEFT: + if(m_dwStyle&RVS_FOCUSSUBITEMS) + { + m_iFocusColumn -= m_iFocusColumn>0 ? 1:0; + + EnsureVisibleColumn(m_iFocusColumn); + + iFirst = GetRowFromItem(m_iFocusRow); + RedrawItems(iFirst, iFirst); + } + else + SendMessage(WM_HSCROLL, LOWORD(SB_LINELEFT), NULL); + return; + + case VK_RIGHT: + if(m_dwStyle&RVS_FOCUSSUBITEMS) + { + m_iFocusColumn += m_iFocusColumn RVI_EDIT) || + m_iFocusRow > RVI_FIRST + ) { + if(IsCtrlDown()) + { + SelectRows(m_iFocusRow-1, m_iFocusRow-1, FALSE); + m_iSelectRow = m_iFocusRow; + } + else if(!IsShiftDown()) + { + SelectRows(m_iFocusRow-1, m_iFocusRow-1, TRUE); + m_iSelectRow = m_iFocusRow; + } + else + SelectRows(m_iFocusRow-1, m_iSelectRow, TRUE); + + EnsureVisible(GetItemFromRow(m_iFocusRow)); + } + return; + + case VK_NEXT: + if(m_iFocusRow == iLast) + { + SendMessage(WM_VSCROLL, SB_PAGEDOWN, 0); + + iFirst = GetScrollPos32(SB_VERT); + GetVisibleRows(TRUE, &iFirst, &iLast); + } + + if(IsCtrlDown()) + { + SelectRows(iLast, iLast, FALSE); + m_iSelectRow = m_iFocusRow; + return; + } + else if(!IsShiftDown()) + { + iFirst = iLast; + m_iSelectRow = iLast; + } + else + iFirst = m_iSelectRow; + + SelectRows(iLast, iFirst, TRUE); + return; + + case VK_PRIOR: + if(m_iFocusRow == iFirst) + { + SendMessage(WM_VSCROLL, SB_PAGEUP, 0); + + iFirst = GetScrollPos32(SB_VERT); + } + + if(IsCtrlDown()) + { + SelectRows(iFirst, iFirst, FALSE); + m_iSelectRow = m_iFocusRow; + return; + } + else if(!IsShiftDown()) + { + iLast = iFirst; + m_iSelectRow = iFirst; + } + else + iLast = m_iSelectRow; + + SelectRows(iFirst, iLast, TRUE); + return; + + case VK_HOME: + if(m_iFocusRow>0) + { + SendMessage(WM_VSCROLL, SB_TOP, 0); + + if(!IsShiftDown()) + m_iSelectRow = 0; + + SelectRows(0, m_iSelectRow, IsCtrlDown()?FALSE:TRUE); + } + break; + + case VK_END: + if(m_iFocusRow 0) + for (i=0;iiPagesScrolled;i--) + PostMessage(WM_VSCROLL, SB_PAGEDOWN, 0); + } + else + { + int iRowsScrolled = (int)m_nRowsPerWheelNotch * zDelta / 120; + + if (iRowsScrolled>0) + for (i=0;iiRowsScrolled;i--) + PostMessage(WM_VSCROLL, SB_LINEDOWN, 0); + } + + return CWnd::OnMouseWheel(nFlags, zDelta, pt); +} + +void CReportCtrl::OnMouseMove(UINT nFlags, CPoint point) +{ + if(!nFlags && m_dwStyle&RVS_EXPANDSUBITEMS && m_hEditWnd == NULL) + { + RVHITTESTINFO rvhti; + rvhti.point = point; + + if(HitTest(&rvhti) != RVI_INVALID) + { + TCHAR szText[REPORTCTRL_MAX_TEXT]; + + RVITEM rvi; + rvi.iItem = rvhti.iItem; + rvi.iSubItem = rvhti.iSubItem; + rvi.lpszText = szText; + rvi.iTextMax = REPORTCTRL_MAX_TEXT; + rvi.nMask = RVIM_TEXT|RVIM_STATE; + GetItem(&rvi); + + if(rvi.nMask&RVIM_TEXT && _tcslen(rvi.lpszText)) + m_wndTip.Show( + rvhti.rect, + rvi.lpszText, + rvi.nState&RVIS_BOLD ? &m_fontBold:&m_font + ); + } + } + + CWnd::OnMouseMove(nFlags, point); +} + +void CReportCtrl::OnHdnItemChanged(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPHDITEM lphdi = (LPHDITEM)((LPNMHEADER)pNMHDR)->pitem; + + if(m_hEditWnd != NULL) + EndEdit(); + + HDITEM hdi; + hdi.mask = HDI_WIDTH|HDI_ORDER|HDI_LPARAM; + m_wndHeader.GetItem(((LPNMHEADER)pNMHDR)->iItem, &hdi); + + if(lphdi->mask&HDI_FORMAT) + m_arraySubItems[hdi.lParam].nFormat = lphdi->fmt&HDF_JUSTIFYMASK; + + if(lphdi->mask&HDI_WIDTH) + { + m_iVirtualWidth += lphdi->cxy - m_arraySubItems[hdi.lParam].iWidth; + ASSERT(m_iVirtualWidth >= 0); + + m_arraySubItems[hdi.lParam].iWidth = lphdi->cxy; + } + + ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ)); + Notify(RVN_LAYOUTCHANGED, -1, (INT)hdi.lParam); + + *pResult = FALSE; +} + +void CReportCtrl::OnHdnItemClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPHDITEM lphdi = (LPHDITEM)((LPNMHEADER)pNMHDR)->pitem; + + if(m_hEditWnd != NULL) + EndEdit(); + + HDITEM hdi; + hdi.mask = HDI_ORDER|HDI_LPARAM; + m_wndHeader.GetItem(((LPNMHEADER)pNMHDR)->iItem, &hdi); + + if(!Notify(RVN_COLUMNCLICK, -1, (INT)hdi.lParam)) + { + if(!(m_dwStyle&(RVS_NOSORT|RVS_OWNERDATA))) + { + BOOL bAscending; + if(((LPNMHEADER)pNMHDR)->iItem == m_wndHeader.GetSortColumn(&bAscending)) + bAscending = !bAscending; + else + bAscending = TRUE; + + VERIFY(SortItems((INT)hdi.lParam, bAscending)); + } + } + + pResult = FALSE; +} + +void CReportCtrl::OnHdnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMHEADER lpnmhdr = (LPNMHEADER)pNMHDR; + + if(m_hEditWnd != NULL) + EndEdit(); + + pResult = FALSE; +} + +void CReportCtrl::OnHdnEndDrag(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMHEADER lpnmhdr = (LPNMHEADER)pNMHDR; + + if(m_wndHeader.GetDropResult()) + { + if(m_dwStyle&RVS_ALLOWCOLUMNREMOVAL && m_arrayColumns.GetSize()>1) + DeactivateColumn(lpnmhdr->pitem->lParam); + + *pResult = TRUE; + } + else + { + m_bColumnsReordered = TRUE; + Invalidate(); + + *pResult = FALSE; + } +} + +void CReportCtrl::OnRvnEndItemEdit(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMRVITEMEDIT lpnmrvie = (LPNMRVITEMEDIT)pNMHDR; + + ASSERT(m_iEditItem == lpnmrvie->iItem); + ASSERT(m_iEditSubItem == lpnmrvie->iSubItem); + + NMRVITEMEDIT nmrvie; + nmrvie.hdr.hwndFrom = GetSafeHwnd(); + nmrvie.hdr.idFrom = GetDlgCtrlID(); + nmrvie.hdr.code = RVN_ENDITEMEDIT; + + nmrvie.iItem = m_iEditItem; + nmrvie.iSubItem = m_iEditSubItem; + + nmrvie.hWnd = lpnmrvie->hWnd; + + nmrvie.nKey = lpnmrvie->nKey; + nmrvie.lpszText = lpnmrvie->lpszText; + + BOOL bResult = FALSE; + CWnd* pWnd = GetParent(); + if(pWnd != NULL) + bResult = pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie); + + if(bResult) + EndEdit(FALSE); + else + EndEdit(nmrvie.nKey != VK_ESCAPE, &nmrvie); + + pResult = FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportColumnListCtrl + +CReportColumnListCtrl::CReportColumnListCtrl() +{ + m_pReportCtrl = NULL; + + m_iColumn = -1; + m_pDragWnd = NULL; +} + +CReportColumnListCtrl::~CReportColumnListCtrl() +{ +} + + +BEGIN_MESSAGE_MAP(CReportColumnListCtrl, CDragListBox) + //{{AFX_MSG_MAP(CReportColumnListCtrl) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CReportColumnListCtrl attributes + +BOOL CReportColumnListCtrl::SetReportCtrl(CReportCtrl* pReportCtrl) +{ + ASSERT_KINDOF(CReportCtrl, pReportCtrl); + + m_pReportCtrl = pReportCtrl; + ResetContent(); + + return TRUE; +} + +CReportCtrl* CReportColumnListCtrl::GetReportCtrl() +{ + return m_pReportCtrl; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportColumnListCtrl operations + +BOOL CReportColumnListCtrl::UpdateList() +{ + INT iColumn, iColumns = m_pReportCtrl->m_arraySubItems.GetSize(); + + ResetContent(); + + for(iColumn=0;iColumnIsActiveColumn(iColumn) && Include(iColumn)) + { + INT iItem = AddString(m_pReportCtrl->m_arraySubItems[iColumn].strText); + SetItemData(iItem, iColumn); + } + } + + return TRUE; +} + +BOOL CReportColumnListCtrl::Include(INT iColumn) +{ + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportColumnListCtrl message handlers + +void CReportColumnListCtrl::PreSubclassWindow() +{ + CDragListBox::PreSubclassWindow(); + + SetItemHeight(0, GetItemHeight(0)+2); +} + +void CReportColumnListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); + + CRect rcItem(lpDrawItemStruct->rcItem); + + if(GetCount() > 0) + { + pDC->DrawFrameControl(rcItem, DFC_BUTTON, DFCS_BUTTONPUSH); + + rcItem.DeflateRect(2, 2); + if(lpDrawItemStruct->itemState&ODS_SELECTED) + { + pDC->FillRect(rcItem, &CBrush(::GetSysColor(COLOR_3DSHADOW))); + pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT)); + } + else + pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT)); + + pDC->SetBkMode(TRANSPARENT); + + pDC->DrawText( + m_pReportCtrl->m_arraySubItems[lpDrawItemStruct->itemData].strText, + -1, + rcItem, + DT_SINGLELINE|DT_NOPREFIX|DT_NOCLIP|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT); + } + else + pDC->FillSolidRect(rcItem, ::GetSysColor(COLOR_WINDOW)); +} + +BOOL CReportColumnListCtrl::BeginDrag(CPoint pt) +{ + if(GetCount() <= 0) + return FALSE; + + BOOL bAutoScroll = FALSE; + INT iItem = ItemFromPt(pt); + if(iItem >= 0) + { + GetClientRect(m_rcDragWnd); + m_rcDragWnd.bottom = m_rcDragWnd.top + GetItemHeight(0); + + m_iColumn = GetItemData(iItem); + + _tcscpy(m_szColumnText, m_pReportCtrl->m_arraySubItems[m_iColumn].strText); + + m_hdiColumn.mask = HDI_WIDTH|HDI_TEXT|HDI_FORMAT; + m_hdiColumn.cxy = m_rcDragWnd.Width(); + m_hdiColumn.pszText = m_szColumnText; + m_hdiColumn.cchTextMax = sizeof(m_szColumnText); + m_hdiColumn.fmt = HDF_STRING|HDF_LEFT; + + m_pDragWnd = new CFHDragWnd; + if(m_pDragWnd) + m_pDragWnd->Create(m_rcDragWnd, &m_pReportCtrl->m_wndHeader, -2, &m_hdiColumn); + + GetWindowRect(m_rcDropTarget1); + m_pReportCtrl->m_wndHeader.GetWindowRect(m_rcDropTarget2); + } + + m_iDropIndex = -1; + + return TRUE; +} + +UINT CReportColumnListCtrl::Dragging(CPoint pt) +{ + CPoint point = pt; + point.Offset(-(m_rcDragWnd.Width()>>1), -(m_rcDragWnd.Height()>>1)); + + if(m_pDragWnd != NULL) + m_pDragWnd->SetWindowPos( + &wndTop, + point.x, point.y, + 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE + ); + + if(m_rcDropTarget1.PtInRect(pt)) + return DL_MOVECURSOR; + + m_iDropIndex = m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, TRUE, MAKELONG(pt.x, pt.y)); + + if(m_rcDropTarget2.PtInRect(pt)) + return DL_MOVECURSOR; + + return DL_STOPCURSOR; +} + +void CReportColumnListCtrl::CancelDrag(CPoint pt) +{ + m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, FALSE, -1); + + if(m_pDragWnd != NULL) + { + m_pDragWnd->DestroyWindow(); + m_pDragWnd = NULL; + } +} + +void CReportColumnListCtrl::Dropped(INT iSrcIndex, CPoint pt) +{ + m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, FALSE, -1); + + if(m_pDragWnd != NULL) + { + m_pDragWnd->DestroyWindow(); + m_pDragWnd = NULL; + } + + if(m_iDropIndex >= 0) + m_pReportCtrl->ActivateColumn(m_iColumn, m_iDropIndex); +} + +///////////////////////////////////////////////////////////////////////////// +// CReportEditCtrl + +CReportEditCtrl::CReportEditCtrl(INT iItem, INT iSubItem) +{ + m_bEndEdit = FALSE; + + m_iItem = iItem; + m_iSubItem = iSubItem; + + m_nLastKey = VK_RETURN; +} + +CReportEditCtrl::~CReportEditCtrl() +{ +} + +void CReportEditCtrl::PostNcDestroy() +{ + CEdit::PostNcDestroy(); + delete this; +} + +BEGIN_MESSAGE_MAP(CReportEditCtrl, CEdit) + //{{AFX_MSG_MAP(CReportEditCtrl) + ON_WM_KILLFOCUS() + ON_WM_GETDLGCODE() + ON_WM_CHAR() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CReportEditCtrl operations + +void CReportEditCtrl::EndEdit() +{ + CString str; + + if(m_bEndEdit) + return; + + m_bEndEdit = TRUE; + GetWindowText(str); + + NMRVITEMEDIT nmrvie; + + nmrvie.hdr.hwndFrom = GetSafeHwnd(); + nmrvie.hdr.idFrom = GetDlgCtrlID(); + nmrvie.hdr.code = RVN_ENDITEMEDIT; + + nmrvie.iItem = m_iItem; + nmrvie.iSubItem = m_iSubItem; + + nmrvie.hWnd = nmrvie.hdr.hwndFrom; + + nmrvie.nKey = m_nLastKey; + nmrvie.lpszText = (LPCTSTR)str; + + CWnd* pWnd = GetOwner(); + if(pWnd != NULL) + pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie); + + PostMessage(WM_CLOSE, 0, 0); + m_bEndEdit = FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportEditCtrl message handlers + +void CReportEditCtrl::OnKillFocus(CWnd* pNewWnd) +{ + CWnd::OnKillFocus(pNewWnd); + EndEdit(); +} + +UINT CReportEditCtrl::OnGetDlgCode() +{ + return DLGC_WANTALLKEYS; +} + +void CReportEditCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if(nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) + { + m_nLastKey = nChar; + + GetParent()->SetFocus(); + return; + } + + CEdit::OnChar(nChar, nRepCnt, nFlags); +} + +BOOL CReportEditCtrl::PreTranslateMessage(MSG* pMsg) +{ + if(pMsg->message == WM_SYSCHAR) + return TRUE; + + return CEdit::PreTranslateMessage(pMsg); +} + +///////////////////////////////////////////////////////////////////////////// +// CReportComboCtrl + +CReportComboCtrl::CReportComboCtrl(INT iItem, INT iSubItem) +{ + m_bEndEdit = FALSE; + + m_iItem = iItem; + m_iSubItem = iSubItem; + + m_nLastKey = VK_RETURN; +} + +CReportComboCtrl::~CReportComboCtrl() +{ +} + +void CReportComboCtrl::PostNcDestroy() +{ + CComboBox::PostNcDestroy(); + delete this; +} + +BEGIN_MESSAGE_MAP(CReportComboCtrl, CComboBox) + //{{AFX_MSG_MAP(CReportComboCtrl) + ON_WM_KILLFOCUS() + ON_WM_GETDLGCODE() + ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnKillfocus) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CReportComboCtrl operations + +void CReportComboCtrl::EndEdit() +{ + CString str; + + if(m_bEndEdit) + return; + + m_bEndEdit = TRUE; + GetWindowText(str); + + NMRVITEMEDIT nmrvie; + + nmrvie.hdr.hwndFrom = GetSafeHwnd(); + nmrvie.hdr.idFrom = GetDlgCtrlID(); + nmrvie.hdr.code = RVN_ENDITEMEDIT; + + nmrvie.iItem = m_iItem; + nmrvie.iSubItem = m_iSubItem; + + nmrvie.hWnd = nmrvie.hdr.hwndFrom; + + nmrvie.nKey = m_nLastKey; + nmrvie.lpszText = (LPCTSTR)str; + + CWnd* pWnd = GetOwner(); + if(pWnd != NULL) + pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie); + + PostMessage(WM_CLOSE, 0, 0); + m_bEndEdit = FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportComboCtrl message handlers + +void CReportComboCtrl::OnKillFocus(CWnd* pNewWnd) +{ + CWnd::OnKillFocus(pNewWnd); + + if(IsChild(pNewWnd)) + return; + + EndEdit(); +} + +UINT CReportComboCtrl::OnGetDlgCode() +{ + return DLGC_WANTALLKEYS; +} + +BOOL CReportComboCtrl::PreTranslateMessage(MSG* pMsg) +{ + if(pMsg->message == WM_CHAR && + (pMsg->wParam == VK_TAB || pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) + ) { + m_nLastKey = pMsg->wParam; + + GetParent()->SetFocus(); + return TRUE; + } + + if (pMsg->message == WM_SYSCHAR) + return TRUE; + + return CComboBox::PreTranslateMessage(pMsg); +} + +void CReportComboCtrl::OnKillfocus() +{ + EndEdit(); +} + +///////////////////////////////////////////////////////////////////////////// +// CReportTipCtrl + +CReportTipCtrl::CReportTipCtrl() +{ + WNDCLASS wndcls; + HINSTANCE hInst = AfxGetInstanceHandle(); + + if(!(::GetClassInfo(hInst, REPORTTIPCTRL_CLASSNAME, &wndcls))) + { + wndcls.style = CS_SAVEBITS ; + wndcls.lpfnWndProc = ::DefWindowProc; + wndcls.cbClsExtra = wndcls.cbWndExtra = 0; + wndcls.hInstance = hInst; + wndcls.hIcon = NULL; + wndcls.hCursor = LoadCursor(hInst, IDC_ARROW); + wndcls.hbrBackground = (HBRUSH)(COLOR_INFOBK+1); + wndcls.lpszMenuName = NULL; + wndcls.lpszClassName = REPORTTIPCTRL_CLASSNAME; + if(!AfxRegisterClass(&wndcls)) + AfxThrowResourceException(); + } + + m_dwLastLButtonDown = ULONG_MAX; + m_dwDblClickMsecs = GetDoubleClickTime(); +} + +CReportTipCtrl::~CReportTipCtrl() +{ +} + + +BEGIN_MESSAGE_MAP(CReportTipCtrl, CWnd) + //{{AFX_MSG_MAP(CReportTipCtrl) + ON_WM_MOUSEMOVE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CReportTipCtrl message handlers + +BOOL CReportTipCtrl::Create(CReportCtrl* pReportCtrl) +{ + ASSERT_VALID(pReportCtrl); + + DWORD dwStyle = WS_BORDER|WS_POPUP; + DWORD dwExStyle = WS_EX_TOOLWINDOW|WS_EX_TOPMOST; + m_pReportCtrl = pReportCtrl; + + return CreateEx(dwExStyle, REPORTTIPCTRL_CLASSNAME, NULL, dwStyle, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, NULL ); +} + +BOOL CReportTipCtrl::Show(CRect rectText, LPCTSTR lpszText, CFont* pFont) +{ + ASSERT(::IsWindow(GetSafeHwnd())); + + if(rectText.IsRectEmpty()) + return FALSE; + + if(IsWindowVisible()) + return FALSE; + + if(GetFocus() == NULL) + return FALSE; + + m_rectText.top = -1; + m_rectText.left = -1; + m_rectText.right = rectText.Width()+1; + m_rectText.bottom = rectText.Height(); + m_pReportCtrl->ClientToScreen(rectText); + + CClientDC dc(this); + pFont = pFont == NULL ? m_pReportCtrl->GetFont():pFont; + CFont *pFontDC = dc.SelectObject(pFont); + + CRect rectDisplay = rectText; + CSize size = dc.GetTextExtent(lpszText, _tcslen(lpszText)); + rectDisplay.right = rectDisplay.left + size.cx + 2*m_pReportCtrl->m_iSpacing; + + BOOL bResult = FALSE; + if(rectDisplay.right > rectText.right) + { + SetWindowPos( + &wndTop, + rectDisplay.left, rectDisplay.top, + rectDisplay.Width(), rectDisplay.Height(), + SWP_SHOWWINDOW|SWP_NOACTIVATE + ); + + dc.SetBkMode(TRANSPARENT); + dc.TextOut(m_pReportCtrl->m_iSpacing-1, 0, lpszText); + + SetCapture(); + + bResult = TRUE; + } + + dc.SelectObject(pFontDC); + return bResult; +} + +void CReportTipCtrl::Hide() +{ + if (!::IsWindow(GetSafeHwnd())) + return; + + if (GetCapture()->GetSafeHwnd() == GetSafeHwnd()) + ReleaseCapture(); + + ShowWindow(SW_HIDE); +} + +void CReportTipCtrl::OnMouseMove(UINT nFlags, CPoint point) +{ + if(!m_rectText.PtInRect(point)) + { + Hide(); + + ClientToScreen(&point); + CWnd *pWnd = WindowFromPoint(point); + if(pWnd == this) + pWnd = m_pReportCtrl; + + INT iHitTest = (INT)pWnd->SendMessage( + WM_NCHITTEST, + 0, + MAKELONG(point.x,point.y) + ); + + if(iHitTest == HTCLIENT) + { + pWnd->ScreenToClient(&point); + pWnd->PostMessage( + WM_MOUSEMOVE, + nFlags, + MAKELONG(point.x,point.y) + ); + } + else + { + pWnd->PostMessage( + WM_NCMOUSEMOVE, + iHitTest, + MAKELONG(point.x,point.y) + ); + } + } +} + +BOOL CReportTipCtrl::PreTranslateMessage(MSG* pMsg) +{ + DWORD dwTick = 0; + BOOL bDoubleClick = FALSE; + + CWnd *pWnd; + INT iHitTest; + + switch (pMsg->message) + { + case WM_LBUTTONDOWN: + + dwTick = GetTickCount(); + bDoubleClick = ((dwTick - m_dwLastLButtonDown) <= m_dwDblClickMsecs); + m_dwLastLButtonDown = dwTick; + + // Notice fall-through + + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + { + POINTS points = MAKEPOINTS(pMsg->lParam); + POINT point; + point.x = points.x; + point.y = points.y; + + ClientToScreen(&point); + pWnd = WindowFromPoint(point); + + if(pWnd == this) + pWnd = m_pReportCtrl; + + iHitTest = (INT)pWnd->SendMessage( + WM_NCHITTEST, + 0, + MAKELONG(point.x, point.y) + ); + + if(iHitTest == HTCLIENT) + { + pWnd->ScreenToClient(&point); + pMsg->lParam = MAKELONG(point.x,point.y); + } + else + { + switch (pMsg->message) + { + case WM_LBUTTONDOWN: pMsg->message = WM_NCLBUTTONDOWN; break; + case WM_RBUTTONDOWN: pMsg->message = WM_NCRBUTTONDOWN; break; + case WM_MBUTTONDOWN: pMsg->message = WM_NCMBUTTONDOWN; break; + } + + pMsg->wParam = iHitTest; + pMsg->lParam = MAKELONG(point.x,point.y); + } + + Hide(); + + pWnd->PostMessage( + bDoubleClick ? WM_LBUTTONDBLCLK : pMsg->message, + pMsg->wParam, + pMsg->lParam + ); + return TRUE; + } + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + + Hide(); + m_pReportCtrl->PostMessage( + pMsg->message, + pMsg->wParam, + pMsg->lParam + ); + return TRUE; + } + + if(GetFocus() == NULL) + { + Hide(); + return TRUE; + } + + return CWnd::PreTranslateMessage(pMsg); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.h new file mode 100644 index 0000000..4d0c4a9 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportCtrl.h @@ -0,0 +1,818 @@ +//////////////////////////////////////////////////////////////////////////// +// File: CReportCtrl.h +// Version: 1.1.0 +// +// Author: Maarten Hoeben +// E-mail: maarten.hoeben@nwn.com +// +// Implementation of the CReportCtrl and associated classes. +// +// This code may be used in compiled form in any way you desire. This +// file may be redistributed unmodified by any means PROVIDING it is +// not sold for profit without the authors written consent, and +// providing that this notice and the authors name and all copyright +// notices remains intact. +// +// An email letting me know how you are using it would be nice as well. +// +// This file is provided "as is" with no expressed or implied warranty. +// The author accepts no liability for any damage/loss of business that +// this product may cause. +// +//////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_REPORTCTRL_H__279B1CA0_D7F2_11D2_88D7_ABB23645F26D__INCLUDED_) +#define AFX_REPORTCTRL_H__279B1CA0_D7F2_11D2_88D7_ABB23645F26D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// ReportCtrl.h : header file +// + +#include "FlatHeaderCtrl.h" + +#define ID_HEADERCTRL 0 +#define ID_REPORTCTRL 0 + +// Use this as the classname when inserting this control as a custom control +// in the MSVC++ dialog editor +#define REPORTCTRL_CLASSNAME _T("MFCReportCtrl") +#define REPORTCTRL_MAX_TEXT 256 + +// Properties +#define RVP_SPACING 1 +#define RVP_CHECK 2 +#define RVP_NOITEMTEXT 3 +#define RVP_GRIDSTYLE 4 + +#define RVP_GRIDSTYLE_DOT 0 +#define RVP_GRIDSTYLE_DASH 1 +#define RVP_GRIDSTYLE_SOLID 2 + +// Styles +#define RVS_SINGLESELECT 0x0001 +#define RVS_SHOWSELALWAYS 0x0002 +#define RVS_SHOWCOLORALWAYS 0x0004 +#define RVS_SHOWCOLORALTERNATE 0x0008 +#define RVS_SHOWHGRID 0x0010 +#define RVS_SHOWVGRID 0x0020 +#define RVS_NOHEADER 0x0040 +#define RVS_NOSORT 0x0080 +#define RVS_ALLOWCOLUMNREMOVAL 0x0100 +#define RVS_SHOWEDITROW 0x0200 +#define RVS_SHOWHGRIDEX 0x0400 +#define RVS_OWNERDATA 0x0800 +#define RVS_FOCUSSUBITEMS 0x1000 +#define RVS_EXPANDSUBITEMS 0x2000 + +// Column Format +#define RVCF_LEFT HDF_LEFT +#define RVCF_RIGHT HDF_RIGHT +#define RVCF_CENTER HDF_CENTER +#define RVCF_TEXT HDF_STRING +#define RVCF_IMAGE HDF_IMAGE + +#define RVCF_JUSTIFYMASK HDF_JUSTIFYMASK +#define RVCF_MASK 0x0000ffff + +#define RVCF_EX_AUTOWIDTH (HDF_EX_AUTOWIDTH<<16) +#define RVCF_EX_INCLUDESORT (HDF_EX_INCLUDESORT<<16) +#define RVCF_EX_FIXEDWIDTH (HDF_EX_FIXEDWIDTH<<16) +#define RVCF_EX_TOOLTIP (HDF_EX_TOOLTIP<<16) +#define RVCF_EX_MASK 0x00ff0000 + +#define RVCF_SUBITEM_IMAGE 0x01000000 +#define RVCF_SUBITEM_CHECK 0x02000000 +#define RVCF_SUBITEM_MASK 0xff000000 + +typedef struct _RVCOLUMN +{ + UINT nFormat; + INT iWidth; + INT iMinWidth; + INT iMaxWidth; + INT iImage; + + LPTSTR lpszText; + + _RVCOLUMN() : nFormat(RVCF_LEFT|RVCF_TEXT), iWidth(-1), iMinWidth(0), iMaxWidth(-1), iImage(0), lpszText(NULL) {}; + +} RVCOLUMN, FAR* LPRVCOLUMN; + +// Item Masks +#define RVIM_TEXT 0x0001 +#define RVIM_TEXTCOLOR 0x0002 +#define RVIM_IMAGE 0x0004 +#define RVIM_CHECK 0x0008 +#define RVIM_BKCOLOR 0x0010 +#define RVIM_PREVIEW 0x0020 +#define RVIM_STATE 0x0040 +#define RVIM_LPARAM 0x0080 + +// Item Index +#define RVI_INVALID -2 +#define RVI_EDIT -1 +#define RVI_FIRST 0 +#define RVI_LAST 0x7fffffff + +// Item State +#define RVIS_FOCUSED 0x0001 +#define RVIS_SELECTED 0x0002 +#define RVIS_BOLD 0x0004 +#define RVIS_READONLY 0x0008 + +typedef struct _RVITEM +{ + UINT nMask; + INT iItem; + INT iSubItem; + + LPTSTR lpszText; + INT iTextMax; + INT iTextColor; + + INT iImage; + INT iCheck; + + INT iBkColor; + UINT nPreview; + UINT nState; + + LPARAM lParam; + + _RVITEM() : nMask(0), iItem(RVI_INVALID), iSubItem(-1), lpszText(NULL), iTextMax(0), iTextColor(-1), iImage(-1), iCheck(-1), iBkColor(-1), nPreview(0), nState(0), lParam(0) {}; + +} RVITEM, FAR* LPRVITEM; + +// Hit Test +#define RVHT_NOWHERE 0x0001 +#define RVHT_ONITEMIMAGE 0x0002 +#define RVHT_ONITEMCHECK 0x0004 +#define RVHT_ONITEMTEXT 0x0008 +#define RVHT_ONITEMPREVIEW 0x0010 +#define RVHT_ONITEM (RVHT_ONITEMIMAGE|RVHT_ONITEMCHECK|RVHT_ONITEMTEXT|RVHT_ONITEMPREVIEW) +#define RVHT_ONITEMEDIT 0x0020 + +#define RVHT_ABOVE 0x0100 +#define RVHT_BELOW 0x0200 +#define RVHT_TORIGHT 0x0400 +#define RVHT_TOLEFT 0x0800 + +typedef struct _RVHITTESTINFO +{ + POINT point; + UINT nFlags; + + INT iItem; + INT iSubItem; + + INT iRow; + INT iColumn; + + RECT rect; + +} RVHITTESTINFO, FAR* LPRVHITTESTINFO; + +// Notifications +#define RVN_ITEMDRAWPREVIEW (0U-2048U) +#define RVN_ITEMCLICK (0U-2049U) +#define RVN_ITEMDBCLICK (0U-2050U) +#define RVN_SELECTIONCHANGING (0U-2051U) +#define RVN_SELECTIONCHANGED (0U-2052U) +#define RVN_COLUMNCLICK (0U-2053U) +#define RVN_LAYOUTCHANGED (0U-2054U) +#define RVN_ITEMDELETED (0U-2055U) +#define RVN_ITEMCALLBACK (0U-2056U) +#define RVN_BEGINITEMEDIT (0U-2057U) +#define RVN_ENDITEMEDIT (0U-2058U) + +typedef struct _NMRVDRAWPREVIEW +{ + NMHDR hdr; + + INT iItem; + UINT nState; + + HDC hDC; + RECT rect; + + LPARAM lParam; + +} NMRVDRAWPREVIEW, FAR* LPNMRVDRAWPREVIEW; + +typedef struct _NMREPORTVIEW +{ + NMHDR hdr; + + UINT nKeys; + POINT point; + UINT nFlags; + + INT iItem; + INT iSubItem; + UINT nState; + + LPARAM lParam; + +} NMREPORTVIEW, FAR* LPNMREPORTVIEW; + +typedef struct _NMRVITEMCALLBACK +{ + NMHDR hdr; + RVITEM item; +} NMRVITEMCALLBACK, FAR* LPNMRVITEMCALLBACK; + +typedef INT (CALLBACK* LPFNRVCOMPARE)(INT iColumn, INT iItem1, INT iItem2); + +typedef struct _NMRVITEMEDIT +{ + NMHDR hdr; + + INT iItem; + INT iSubItem; + + HWND hWnd; + RECT rect; + + UINT nKey; + LPCTSTR lpszText; + + LPARAM lParam; + +} NMRVITEMEDIT, FAR* LPNMRVITEMEDIT; + +// Item Rect +#define RVIR_BOUNDS 0 +#define RVIR_IMAGE 1 +#define RVIR_CHECK 2 +#define RVIR_TEXT 3 + + +class CReportCtrl; +class CReportColumnListCtrl; + +///////////////////////////////////////////////////////////////////////////// +// CReportEditCtrl window + +class CReportEditCtrl: public CEdit +{ +public: + CReportEditCtrl(INT iItem, INT iSubItem); + +// Operations +public: + void EndEdit(); + +// Overrides +public: + virtual ~CReportEditCtrl(); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CReportEditCtrl) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementation +protected: + BOOL m_bEndEdit; + + INT m_iItem; + INT m_iSubItem; + + UINT m_nLastKey; + + //{{AFX_MSG(CReportEditCtrl) + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg UINT OnGetDlgCode(); + afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +// CReportComboCtrl window + +class CReportComboCtrl: public CComboBox +{ +public: + CReportComboCtrl(INT iItem, INT iSubItem); + +// Operations +public: + void EndEdit(); + +// Overrides +public: + virtual ~CReportComboCtrl(); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CReportComboCtrl) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementation +protected: + BOOL m_bEndEdit; + + INT m_iItem; + INT m_iSubItem; + + UINT m_nLastKey; + + //{{AFX_MSG(CReportComboCtrl) + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg UINT OnGetDlgCode(); + afx_msg void OnKillfocus(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +// CReportTipCtrl window + +#define REPORTTIPCTRL_CLASSNAME _T("MFCReportTipCtrl") + +class CReportTipCtrl : public CWnd +{ +// Construction +public: + CReportTipCtrl(); + + BOOL Create(CReportCtrl *pReportCtrl); + +// Attributes +public: + +// Operations +public: + BOOL Show(CRect rectTitle, LPCTSTR lpszText, CFont* pFont = NULL); + void Hide(); + +// Overrides +public: + virtual ~CReportTipCtrl(); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CReportTipCtrl) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +protected: + CReportCtrl *m_pReportCtrl; + CRect m_rectText; + DWORD m_dwLastLButtonDown; + DWORD m_dwDblClickMsecs; + + // Generated message map functions +protected: + //{{AFX_MSG(CReportTipCtrl) + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +// CReportData storage class + +class CReportData : public CString +{ +public: + CReportData(); + ~CReportData(); + + BOOL New(INT iSubItems); + + BOOL GetSubItem(INT iSubItem, LPINT lpiImage, LPINT lpiCheck, LPINT lpiColor, LPTSTR lpszText, LPINT lpiTextMax); + BOOL SetSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText); + + BOOL InsertSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText); + BOOL DeleteSubItem(INT iSubItem); +}; + +///////////////////////////////////////////////////////////////////////////// +// CReportCtrl window + +class CReportCtrl : public CWnd +{ + friend class CReportView; + friend class CReportTipCtrl; + friend class CReportColumnListCtrl; + +// Construction +public: + DECLARE_DYNCREATE(CReportCtrl) + CReportCtrl(); + +public: + BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); + INT PreviewHeight(CFont* pFont, UINT nLines); + INT PreviewHeight(CFont* pFont, LPCTSTR lpszText, LPRECT lpRect = NULL); + +// Attributes +public: + BOOL ModifyProperty(WPARAM wParam, LPARAM lParam); + + INT ActivateColumn(INT iColumn, INT iOrder = 0); + BOOL DeactivateColumn(INT iColumn); + BOOL IsActiveColumn(INT iColumn); + + BOOL GetItem(LPRVITEM lprvi); + BOOL SetItem(LPRVITEM lprvi); + + INT GetItemText(INT iItem, INT iSubItem, LPTSTR lpszText, INT iLen); + CString GetItemText(INT iItem, INT iSubItem); + BOOL SetItemText(INT iItem, INT iSubItem, LPCTSTR lpszText); + + INT GetItemImage(INT iItem, INT iSubItem); + BOOL SetItemImage(INT iItem, INT iSubItem, INT iImage); + + INT GetItemCheck(INT iItem, INT iSubItem); + BOOL SetItemCheck(INT iItem, INT iSubItem, INT iCheck = -1); + + DWORD GetItemData(INT iItem); + BOOL SetItemData(INT iItem, DWORD dwData); + + BOOL GetItemRect(INT iItem, INT iSubItem, LPRECT lpRect, UINT nCode = RVIR_BOUNDS); + void SetItemHeight(INT iHeight); + + INT GetVisibleCount(BOOL bUnobstructed = TRUE); + INT GetItemCount(); + void SetItemCount(INT iCount); + + INT GetFirstSelectedItem(); + INT GetNextSelectedItem(INT iItem); + + void ClearSelection(); + void SetSelection(INT iItem, BOOL bKeepSelection = FALSE); + void SetSelection(LPINT lpiItems, INT iCount, BOOL bKeepSelection = FALSE); + + BOOL SetImageList(CImageList* pImageList); + CImageList* GetImageList(); + + BOOL SetBkImage(UINT nIDResource); + BOOL SetBkImage(LPCTSTR lpszResourceName); + + BOOL HasFocus(); + CFlatHeaderCtrl* GetHeaderCtrl(); + + BOOL SetReportColumnListCtrl(CReportColumnListCtrl* lprclc); + CReportColumnListCtrl* GetReportColumnListCtrl(); + + BOOL SetSortCallback(LPFNRVCOMPARE lpfnrvc); + LPFNRVCOMPARE GetSortCallback(); + + BOOL WriteProfile(CString* strpProfile); + BOOL GetProfile(CString* strpProfile); + +// Operations +public: + BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0); + + INT DefineColumn(INT iColumn, LPRVCOLUMN lprvc, BOOL bUpdateList = FALSE); + BOOL UndefineColumn(INT iColumn); + + INT InsertItem(INT iItem, LPTSTR lpszText, INT iImage = -1, INT iCheck = -1, INT iTextColor = -1); + INT InsertItem(LPRVITEM lprvi); + BOOL DeleteItem(INT iItem); + BOOL DeleteAllItems(); + + void RedrawItems(INT iFirst, INT iLast = RVI_LAST); + BOOL EnsureVisible(INT iItem, BOOL bUnobstructed = TRUE); + + INT InsertColor(INT iIndex, COLORREF crColor); + BOOL DeleteColor(INT iIndex); + + INT HitTest(LPRVHITTESTINFO lprvhti); + + BOOL SortItems(INT iColumn, BOOL bAscending); + BOOL SortAllColumns(BOOL bAscending /*=TRUE*/); + +// Overrides +public: + virtual ~CReportCtrl(); +INT FindColumnInHeader(INT iColumn); + virtual void DrawItem(CDC* pDC, CRect rect, LPRVITEM lprvi); + virtual BOOL DrawBkgnd(CDC* pDC, CRect rect, COLORREF crBackground); + + virtual INT CompareItems(INT iColumn, INT iItem1, INT iItem2); + + virtual BOOL BeginEdit(INT iRow, INT iColumn, UINT nKey); + virtual void EndEdit(BOOL bUpdate = TRUE, LPNMRVITEMEDIT lpnmrvie = NULL); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CReportCtrl) + protected: + virtual void PreSubclassWindow(); + //}}AFX_VIRTUAL + +// Structures +protected: + + typedef struct structSUBITEM + { + UINT nFormat; + INT iWidth; + INT iMinWidth; + INT iMaxWidth; + INT iImage; + + CString strText; + + structSUBITEM() : nFormat(RVCF_LEFT), iWidth(-1), iMinWidth(0), iMaxWidth(-1), iImage(0) {}; + + } SUBITEM, FAR* LPSUBITEM; + + typedef struct structITEM + { + CReportData rdData; + INT iBkColor; + UINT nState; + UINT nPreview; + LPARAM lParam; + + structITEM() : + iBkColor(-1), + nPreview(0), + nState(0), + lParam(0) + {}; + + structITEM& operator = (structITEM& item) + { + rdData = item.rdData; + + iBkColor = item.iBkColor; + nPreview = item.nPreview; + nState = item.nState; + lParam = item.lParam; + + return *this; + } + + } ITEM, FAR* LPITEM; + +// Implementation +protected: + BOOL m_bSubclassFromCreate; + + BOOL m_bDoubleBuffer; + INT m_iSpacing; + UINT m_nRowsPerWheelNotch; + + DWORD m_dwStyle; + + CFont m_font; + CFont m_fontBold; + + CImageList* m_pImageList; + SIZE m_sizeImage; + SIZE m_sizeCheck; + + COLORREF m_crBackground; + COLORREF m_crBkSelected; + COLORREF m_crBkSelectedNoFocus; + COLORREF m_crText; + COLORREF m_crTextSelected; + COLORREF m_crTextSelectedNoFocus; + COLORREF m_crGrid; + COLORREF m_cr3DFace; + COLORREF m_cr3DHiLight; + COLORREF m_cr3DDkShadow; + + CArray m_arrayColors; + CPalette m_palette; + + INT m_iGridStyle; + + CString m_strNoItems; + + CRect m_rectTop; + CRect m_rectHeader; + CRect m_rectEdit; + CRect m_rectReport; + + INT m_iDefaultWidth, m_iDefaultHeight; + INT m_iVirtualWidth, m_iVirtualHeight; + + CArray m_arraySubItems; + CArray m_arrayItems; + ITEM m_itemEdit; + ITEM m_itemCache; + + BOOL m_bColumnsReordered; + CArray m_arrayColumns; + + BOOL m_bFocus; + INT m_iFocusRow; + INT m_iFocusColumn; + INT m_iSelectRow; + CArray m_arrayRows; + + INT m_iEditItem; + INT m_iEditSubItem; + HWND m_hEditWnd; + + LPFNRVCOMPARE m_lpfnrvc; + + CFlatHeaderCtrl m_wndHeader; + CReportTipCtrl m_wndTip; + CReportColumnListCtrl* m_lprclc; + + CBitmap m_bitmap; + SIZE m_sizeBitmap; + + BOOL Create(); + + void GetSysColors(); + UINT GetMouseScrollLines(); + BOOL CreatePalette(); + + BOOL Notify(UINT nCode, INT iItem = -1, INT iSubItem = -1, UINT nState = 0, LPARAM lParam = 0); + BOOL Notify(UINT nCode, UINT nKeys, LPRVHITTESTINFO lprvhti); + + void Layout(INT cx, INT cy); + + ITEM& GetItemStruct(INT iItem, INT iSubItem, UINT nMask = 0); + void SetItemStruct(INT iItem, ITEM& item); + + INT GetItemFromRow(INT iRow); + INT GetItemFromRow(INT iRow, ITEM& item); + INT GetRowFromItem(INT iItem); + INT GetSubItemFromColumn(INT iSubItem); + INT GetColumnFromSubItem(INT iColumn); + + void SetState(INT iRow, UINT nState, UINT nMask); + UINT GetState(INT iRow); + + + INT GetVisibleRows(BOOL bUnobstructed = TRUE, LPINT lpiFirst = NULL, LPINT lpiLast = NULL, BOOL bReverse = FALSE); + void SelectRows(INT iFirst, INT iLast, BOOL bSelect = TRUE, BOOL bKeepSelection = FALSE, BOOL bInvert = FALSE, BOOL bNotify = TRUE); + + INT GetScrollPos32(INT iBar, BOOL bGetTrackPos = FALSE); + BOOL SetScrollPos32(INT iBar, INT nPos, BOOL bRedraw = TRUE); + void ScrollWindow(INT iBar, INT iPos); + + void EnsureVisibleColumn(INT iColumn); + + void DrawCtrl(CDC* pDC); + void DrawRow(CDC* pDC, CRect rectRow, CRect rectClip, INT iRow, LPRVITEM lprvi, BOOL bAlternate); + INT DrawImage(CDC* pDC, CRect rect, LPRVITEM lprvi); + INT DrawCheck(CDC* pDC, CRect rect, LPRVITEM lprvi); + INT DrawText(CDC* pDC, CRect rect, LPRVITEM lprvi); + + // Generated message map functions +protected: + //{{AFX_MSG(CReportCtrl) + afx_msg void OnDestroy(); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnPaint(); + afx_msg void OnSysColorChange(); + afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection); + afx_msg void OnHdnItemChanged(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnHdnItemClick(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnHdnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnHdnEndDrag(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRvnEndItemEdit(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg UINT OnGetDlgCode(); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg BOOL OnQueryNewPalette(); + afx_msg void OnPaletteChanged(CWnd* pFocusWnd); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp); + afx_msg void OnNcPaint(); + afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + //}}AFX_MSG + afx_msg LRESULT OnSetFont(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnGetFont(WPARAM wParam, LPARAM lParam); + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +// CReportView + +class CReportView : public CView +{ +protected: + DECLARE_DYNCREATE(CReportView) + CReportView(); // protected constructor used by dynamic creation + +// Attributes +public: + CReportCtrl& GetReportCtrl(); + CReportCtrl* GetReportCtrlPtr(); + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CReportView) + public: + virtual void OnInitialUpdate(); + protected: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~CReportView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + BOOL m_bCreated; + CReportCtrl m_wndReportCtrl; + + // Generated message map functions +protected: + //{{AFX_MSG(CReportView) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +// CReportColumnList window + +class CReportColumnListCtrl : public CDragListBox +{ +// Construction +public: + CReportColumnListCtrl(); + ~CReportColumnListCtrl(); + +// Attributes +public: + BOOL SetReportCtrl(CReportCtrl* pReportCtrl); + CReportCtrl* GetReportCtrl(); + +// Operations +public: + BOOL UpdateList(); + +// Overrides + virtual BOOL Include(INT iColumn); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CReportColumnListCtrl) + public: + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + protected: + virtual void PreSubclassWindow(); + //}}AFX_VIRTUAL + +// Implementation +protected: + CReportCtrl* m_pReportCtrl; + + INT m_iColumn; + HDITEM m_hdiColumn; + TCHAR m_szColumnText[FLATHEADER_TEXT_MAX]; + + CFHDragWnd* m_pDragWnd; + CRect m_rcDragWnd; + CRect m_rcDropTarget1; + CRect m_rcDropTarget2; + + INT m_iDropIndex; + + BOOL BeginDrag(CPoint pt); + UINT Dragging(CPoint pt); + void CancelDrag(CPoint pt); + void Dropped(INT iSrcIndex, CPoint pt); + + // Generated message map functions +protected: + //{{AFX_MSG(CReportColumnListCtrl) + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_REPORTCTRL_H__279B1CA0_D7F2_11D2_88D7_ABB23645F26D__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.cpp new file mode 100644 index 0000000..d8a8b51 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.cpp @@ -0,0 +1,108 @@ +// ReportViewerDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ReportViewerDlg.h" + + +// CReportViewerDlg dialog + +IMPLEMENT_DYNAMIC(CReportViewerDlg, CDialog) +CReportViewerDlg::CReportViewerDlg(CWnd* pParent /*=NULL*/) + : CDialog(CReportViewerDlg::IDD, pParent) +{ + m_Report=NULL; + m_SubReport=NULL; +} + +CReportViewerDlg::~CReportViewerDlg() +{ +} + +void CReportViewerDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_CRVIEWER1, crv); +} + + +BEGIN_MESSAGE_MAP(CReportViewerDlg, CDialog) + ON_COMMAND(ID_PRINTSETUP, OnPrintsetup) + ON_COMMAND(ID_CLOSETHISSCREEN250, OnClosethisscreen250) +END_MESSAGE_MAP() + + +// CReportViewerDlg message handlers + +BOOL CReportViewerDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); +CWaitCursor cw; + crv.put_DisplayTabs(FALSE); + crv.put_EnableExportButton(TRUE); + crv.put_EnableRefreshButton(FALSE); + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + LayoutControls(); +ASSERT(m_Report!=NULL); +//m_Viewer.SetEnableToolbar(TRUE); +//m_Viewer.SetEnableAnimationCtrl(TRUE); +//m_Viewer.SetDisplayBorder(FALSE); +//AfxMessageBox("View"); + +crv.put_ReportSource(m_Report); + //m_Viewer.SetReportSource(m_Report); + + crv.ViewReport(); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CReportViewerDlg::LayoutControls(void) +{ + int nLeft,nTop,nWidth,nHeight; + CRect rectCtl1,rectCtl2,rectDlg; + GetClientRect(rectDlg);//client area needed for movewindow + //get client screen coordinates + nLeft=rectDlg.left; + nTop=rectDlg.top; + nWidth=rectDlg.Width(); + nHeight=rectDlg.Height(); + + //REPORT PREVIEW CONTROL + crv.GetWindowRect(rectCtl1);//windowrect is based on whole screen +// m_lblBrief.GetWindowRect(rectCtl2);//based on upper left corner of screen not client area +// ScreenToClient(rectCtl2);//convert whole screen co-ords to client area + nHeight=(rectDlg.bottom)-10;//calculate height + crv.MoveWindow(rectDlg.left,rectDlg.top+10,rectDlg.Width(),nHeight-10,TRUE); + + +} + +void CReportViewerDlg::OnPrintsetup() +{ + m_Report->PrinterSetup(0); + /*CString crPrinterName=(LPCTSTR) m_Report->GetPrinterName(); + CString crDriverName=(LPCTSTR) m_Report->GetDriverName(); + CString crPortName=(LPCTSTR) m_Report->GetPortName(); + CRPaperOrientation crPaperOrientation=m_Report->GetPaperOrientation(); + CRPaperSize crPaperSize=m_Report->GetPaperSize(); + CRPaperSource crPaperSource=m_Report->GetPaperSource(); + CRPrinterDuplexType crDuplexType=m_Report->GetPrinterDuplex(); + + long lPaperSize=(long)m_Report->GetPaperSize(); + m_Report->PaperSize=(CRPaperSize)lPaperSize; + */ + crv.ViewReport(); +} + +void CReportViewerDlg::OnClosethisscreen250() +{ + OnOK(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.h new file mode 100644 index 0000000..7b9d0f1 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ReportViewerDlg.h @@ -0,0 +1,30 @@ +#pragma once +#include "crviewer1.h" + + +// CReportViewerDlg dialog + +class CReportViewerDlg : public CDialog +{ + DECLARE_DYNAMIC(CReportViewerDlg) + +public: + CReportViewerDlg(CWnd* pParent = NULL); // standard constructor + virtual ~CReportViewerDlg(); + +// Dialog Data + enum { IDD = IDD_REPORT_DLG }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + CCrviewer1 crv; + IReportPtr m_Report; + IReportPtr m_SubReport; + virtual BOOL OnInitDialog(); + void LayoutControls(void); + afx_msg void OnPrintsetup(); + afx_msg void OnClosethisscreen250(); +}; diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.cpp new file mode 100644 index 0000000..d0c5935 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.cpp @@ -0,0 +1,696 @@ +// ResizeCtrl.cpp: implementation of the CResizeCtrl class. +// +// +// Written by Herbert Menke (h.menke@gmx.de) +// Copyright (c) 2000. +// +// This code may be used in compiled form in any way you desire. This +// file may be redistributed unmodified by any means PROVIDING it is +// not sold for profit without the authors written consent, and +// providing that this notice and the authors name is included. If +// the source code in this file is used in any commercial application +// then acknowledgement must be made to the author of this file +// (in whatever form you wish). +// +// This file is provided "as is" with no expressed or implied warranty. +// +// Expect bugs. +// +// Please use and enjoy. Please let me know of any bugs/mods/improvements +// that you have found/implemented and I will fix/incorporate them into this +// file. +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizeCtrl.h" +#ifndef __AFXTEMPL_H__ + #include +#endif + + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +// Specification struct +struct RSRect +{ + int left; // Specifies the percentage change in the position of the left edge + // of the object relative to the total change in the parent form’s width. + int top; // Specifies the percentage change in the position of the top + // of the object relative to the total change in the parent form’s height. + int width; // Specifies the percentage change in the width of the object + // relative to the total change in the parent form’s width. + int height; // Specifies the percentage change in the height of the object + // relative to the total change in the parent form’s height. +}; + + +struct CRPItemState +{ + HWND handle; // Handle of Control + RSRect pending; // pending Resize pixels + RSRect part; // resize specifications +}; + +class CResizeArray : public CArray { }; + +static const char m_szResizeProperty[] = "___CResizeCtrl___Class___"; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResizeCtrl::CResizeCtrl( ) +: m_array ( NULL ) +, m_hWndParent ( NULL ) +, m_maxPart ( 100 ) +, m_inResize ( FALSE ) +, m_prevWndProc ( NULL ) +, m_enabled ( FALSE ) +, m_minTracking ( CSize( -1, -1 ) ) +, m_maxTracking ( CSize( -1, -1 ) ) +, m_hitCode ( 0 ) +, m_inMouseMove ( FALSE ) +, m_delta ( CSize( 0, 0 ) ) +, m_windowRect ( CRect( 0, 0, 0, 0 ) ) +, m_gripEnabled ( FALSE ) +{ +} + +CResizeCtrl::CResizeCtrl( HWND hWndParent, BOOL enable, int maxPart ) +: m_array( NULL ) +, m_hWndParent ( NULL ) +, m_maxPart ( 100 ) +, m_inResize ( FALSE ) +, m_prevWndProc ( NULL ) +, m_enabled ( FALSE ) +, m_minTracking ( CSize( -1, -1 ) ) +, m_maxTracking ( CSize( -1, -1 ) ) +, m_hitCode ( 0 ) +, m_inMouseMove ( FALSE ) +, m_delta ( CSize( 0, 0 ) ) +, m_gripEnabled ( FALSE ) +{ + Create( hWndParent, enable, maxPart ); + +} + +CResizeCtrl::CResizeCtrl( CWnd * wndParent, BOOL enable, int maxPart ) +: m_array ( NULL ) +, m_hWndParent ( NULL ) +, m_maxPart ( 100 ) +, m_inResize ( FALSE ) +, m_prevWndProc ( NULL ) +, m_enabled ( FALSE ) +, m_minTracking ( CSize( -1, -1 ) ) +, m_maxTracking ( CSize( -1, -1 ) ) +, m_hitCode ( 0 ) +, m_inMouseMove ( FALSE ) +, m_delta ( CSize( 0, 0 ) ) +, m_gripEnabled ( FALSE ) +{ + Create( wndParent, enable, maxPart ); +} + +CResizeCtrl::~CResizeCtrl() +{ + SetEnabled( FALSE ); + m_array->RemoveAll(); + delete m_array; +} + +BOOL CResizeCtrl::Create( CWnd * wndParent, BOOL enable, int maxPart ) +{ + ASSERT( wndParent ); + if( wndParent ) + return Create( wndParent->GetSafeHwnd(), enable, maxPart ); + return FALSE; +} + +BOOL CResizeCtrl::Create( HWND hWndParent, BOOL enable, int maxPart ) +{ + ASSERT( !m_array ); + if( m_array ) + return FALSE; + + m_array = new CResizeArray; + ASSERT( m_array ); + ASSERT( hWndParent ); + ASSERT( maxPart > 0 ); + m_hWndParent = hWndParent; + m_maxPart = maxPart; + m_inResize = FALSE; + m_prevWndProc = NULL; + m_enabled = FALSE; + m_minTracking.cx = + m_minTracking.cy = + m_maxTracking.cx = + m_maxTracking.cy = -1; + m_hasResizingBorder = (::GetWindowLong( hWndParent, GWL_STYLE ) & WS_THICKFRAME ) == WS_THICKFRAME; + if( enable ) + SetEnabled( TRUE ); + else + ::GetWindowRect( hWndParent , &m_windowRect ); + return TRUE; +} + + + +// +// Enabled Property +// + +BOOL CResizeCtrl::SetEnabled( BOOL enable ) +{ + ASSERT ( m_array ); + + if( m_enabled != enable ) + { + ASSERT( m_hWndParent ); + ::GetWindowRect( m_hWndParent, &m_windowRect ); + // remove subclassing + if( FALSE == enable ) + { + ASSERT( m_prevWndProc ); + ::SetWindowLong( m_hWndParent, GWL_WNDPROC, reinterpret_cast( m_prevWndProc ) ); + m_prevWndProc = NULL; + ::RemoveProp( m_hWndParent, m_szResizeProperty ); + if( m_hasResizingBorder == FALSE ) + ChangeStyle( enable ); + } + else + { + m_hitCode = 0; + m_delta.cx = + m_delta.cy = 0; + m_inResize = + m_inMouseMove = FALSE; + //m_hWndFocus = NULL; + + WNDPROC wndProc = CResizeCtrl::WndProc; + if( m_hasResizingBorder == FALSE ) + { + ChangeStyle( enable ); + } + CRect rect; + ::GetClientRect( m_hWndParent, &rect ); + m_size.cx = rect.Width(); + m_size.cy = rect.Height(); + + ::SetProp( m_hWndParent, m_szResizeProperty, reinterpret_cast(this) ); + m_prevWndProc = reinterpret_cast( ::GetWindowLong( m_hWndParent, GWL_WNDPROC ) ); + ::SetWindowLong( m_hWndParent, GWL_WNDPROC, reinterpret_cast( wndProc ) ); + } + m_enabled = enable; + if( m_gripEnabled ) + { + GetGripRect( m_gripRect, TRUE ); + } + return TRUE; + } + return FALSE; +} +BOOL CResizeCtrl::GetEnabled() const +{ + return m_enabled; +} + +// +// GripEnabled Property +// + +BOOL CResizeCtrl::SetGripEnabled( BOOL showGrip ) +{ + if( m_gripEnabled != showGrip ) + { + m_gripEnabled = showGrip; + if( m_enabled ) + GetGripRect( m_gripRect, TRUE ); + } + return FALSE; +} +BOOL CResizeCtrl::GetGripEnabled() const +{ + return m_gripEnabled; +} + +// resizeInfo is a null terminated array of CResizeInfo + +BOOL CResizeCtrl::Add( const CResizeInfo * resizeInfo ) +{ + ASSERT ( m_array ); + + BOOL result = TRUE; + while( result == TRUE && resizeInfo->ctlID > 0 ) + { + result &= Add( resizeInfo->ctlID, + resizeInfo->left, + resizeInfo->top, + resizeInfo->width, + resizeInfo->height ); + resizeInfo++; + } + return result; +} + +BOOL CResizeCtrl::Add( int ctlID, int left, int top, int width, int height ) +{ + ASSERT ( m_array ); + + return Add( ::GetDlgItem( m_hWndParent, ctlID), left, top, width, height ); +} + +BOOL CResizeCtrl::Add( CWnd * wndCtl, int left, int top, int width, int height ) +{ + ASSERT ( m_array ); + + if( wndCtl ) + return Add( wndCtl->GetSafeHwnd(), left, top, width, height ); + return FALSE; + +} + +BOOL CResizeCtrl::Add(HWND hWndCtl, int left, int top, int width, int height) +{ + ASSERT ( m_array ); + + if( left < 0 || left > m_maxPart ) + { + return FALSE; + } + if( top < 0 || top > m_maxPart ) + { + return FALSE; + } + if( width < 0 || width > m_maxPart ) + { + return FALSE; + } + if( height < 0 || height > m_maxPart ) + { + return FALSE; + } + + if( ( left + width ) > m_maxPart ) + { + return FALSE; + } + if( ( top + height) > m_maxPart ) + { + return FALSE; + } + + if( !::IsWindow( hWndCtl)) + return FALSE; + + CRPItemState item; + + item.part.left = left; + item.part.top = top; + item.part.width = width; + item.part.height = height; + item.pending.left = + item.pending.top = + item.pending.width = + item.pending.height = 0; + item.handle = hWndCtl; + + return m_array->Add( item ) >= 0 ; +} + +BOOL CResizeCtrl::Remove( int ctlID ) +{ + ASSERT ( m_array ); + + return Remove( ::GetDlgItem( m_hWndParent, ctlID ) ); +} + +BOOL CResizeCtrl::Remove( CWnd * wndCtl ) +{ + ASSERT ( m_array ); + + if( wndCtl ) + return Remove( wndCtl->GetSafeHwnd () ); + return FALSE; +} + +BOOL CResizeCtrl::Remove(HWND hWndCtl) +{ + ASSERT ( m_array ); + + if( !::IsWindow( hWndCtl)) + return FALSE; + + int upperBound = m_array->GetUpperBound (); + for( int current = 0; current <= upperBound; current++ ) + { + if( m_array->GetAt( current ).handle == hWndCtl ) + { + m_array->RemoveAt( current ); + return TRUE; + } + } + return FALSE; +} + +BOOL CResizeCtrl::GetWindowRect( RECT * rect ) +{ + if( rect ) + { + *rect = m_windowRect; + return TRUE; + } + else + return FALSE; +} +BOOL CResizeCtrl::CalcValue(int delta, int part, int & pending, long &position, BOOL isSize) +{ + if( part > 0 ) + { + int toAdd = ( delta * part ) + pending; + if( toAdd != 0 ) + { + position += ( toAdd / m_maxPart ); + pending = toAdd % m_maxPart ; + // avoid negative width or height + if( TRUE == isSize && position < 0 ) + { + pending += ( position * m_maxPart ); + position = 0; + } + return TRUE; + } + } + return FALSE; +} + +void CResizeCtrl::Resize(int cx, int cy) +{ + ASSERT ( m_array ); + + if( FALSE == m_inResize ) + { + m_inResize = TRUE; + int upperBound = m_array->GetUpperBound(); + if( upperBound >= 0 ) + { + int deltaX = cx - m_size.cx; + int deltaY = cy - m_size.cy; + + if( deltaX != 0 || deltaY != 0 ) + { + CRPItemState * items = m_array->GetData(); + HDWP hdwp = ::BeginDeferWindowPos( 0 ); + for( int current = 0; current <= upperBound; current++, items++ ) + { + RECT rcItem; + + + ::GetWindowRect( items->handle, & rcItem ); + ::MapWindowPoints( HWND_DESKTOP, m_hWndParent, (LPPOINT)(RECT*)&rcItem, 2 ); + rcItem.right -= rcItem.left; + rcItem.bottom -= rcItem.top; + + BOOL changed = FALSE; + + changed |= CalcValue( deltaX, items->part.left, items->pending.left, rcItem.left, FALSE ); + changed |= CalcValue( deltaX, items->part.width, items->pending.width, rcItem.right, TRUE ); + changed |= CalcValue( deltaY, items->part.top, items->pending.top, rcItem.top, FALSE ); + changed |= CalcValue( deltaY, items->part.height, items->pending.height, rcItem.bottom, TRUE ); + + if( changed ) + { + hdwp = ::DeferWindowPos( hdwp, items->handle, NULL, + rcItem.left, rcItem.top, + rcItem.right, rcItem.bottom, SWP_NOZORDER ); + } + + } + ::EndDeferWindowPos( hdwp ); + m_size.cx = cx; + m_size.cy = cy; + } + } + m_inResize = FALSE; + } +} + + +LRESULT CALLBACK CResizeCtrl::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + CResizeCtrl * This = reinterpret_cast(::GetProp( hWnd, m_szResizeProperty )); + if( This ) + { + WNDPROC prevWndProc = This->m_prevWndProc; + if( FALSE == This->ProcessMessage( msg, wParam, lParam, result ) ) + result = ::CallWindowProc( prevWndProc, hWnd, msg, wParam, lParam ); + } + return result; +} + + + +void CResizeCtrl::ChangeStyle(BOOL enable) +{ + ASSERT( m_hWndParent ); + ASSERT( m_hasResizingBorder == FALSE ); + CRect rect; + + BOOL hasMenu = ::GetMenu( m_hWndParent ) != NULL; + long style = ::GetWindowLong( m_hWndParent, GWL_STYLE ); + ::GetWindowRect( m_hWndParent, &rect ); + + // retrieve client Rectangle + RECT oldClientRect; + ::GetClientRect( m_hWndParent, &oldClientRect ); + RECT newClientRect = oldClientRect; + + // adjust rect with current style + ::AdjustWindowRect( &oldClientRect, style, hasMenu ); + + if( enable ) + { + style |= WS_THICKFRAME; + } + else + { + style &= ~WS_THICKFRAME; + } + + // adjust rect with new style + ::AdjustWindowRect( &newClientRect, style, hasMenu ); + + // and adjust the windowrect, so that the clientrect remains equal + rect.left += ( newClientRect.left - oldClientRect.left ); + rect.right += ( newClientRect.right - oldClientRect.right ); + rect.top += ( newClientRect.top - oldClientRect.top ); + rect.bottom += ( newClientRect.bottom - oldClientRect.bottom ); + + ::SetWindowLong( m_hWndParent, GWL_STYLE, style ); + ::SetWindowPos ( m_hWndParent, HWND_DESKTOP, rect.left, rect.top, rect.Width(), rect.Height(), + SWP_NOZORDER | SWP_NOACTIVATE ); + +} + +BOOL CResizeCtrl::ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT & result) +{ + BOOL handled = FALSE; + if( m_gripEnabled && WM_NCHITTEST == message ) + { + POINT pt = { (int)LOWORD(lParam), (int)HIWORD(lParam) }; + ::ScreenToClient( m_hWndParent, &pt); + if( ::PtInRect ( m_gripRect, pt ) ) + { + result = HTBOTTOMRIGHT; + handled = TRUE; + } + } + else if( m_gripEnabled && WM_PAINT == message ) + { + // First let the previous windowproc handle the WM_SIZE message + result = ::CallWindowProc( m_prevWndProc, m_hWndParent, message, wParam, lParam ); + HDC hDC = ::GetDC( m_hWndParent ); + DrawFrameControl(hDC, &m_gripRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP); + ::ReleaseDC( m_hWndParent, hDC ); + // flag message handled + handled = TRUE; + } + else if( WM_DESTROY == message ) + { + // Remove subclassing + SetEnabled( FALSE ); + } + else if( WM_SIZE == message ) + { + // First let the previous windowproc handle the WM_SIZE message + result = ::CallWindowProc( m_prevWndProc, m_hWndParent, message, wParam, lParam ); + // resize all registered controls + Resize( (int)LOWORD(lParam) , (int)HIWORD(lParam) ); + if( m_gripEnabled ) + { + ::InvalidateRect( m_hWndParent, m_gripRect, TRUE ); + GetGripRect( m_gripRect, TRUE ); + } + // flag message handled + handled = TRUE; + } + else if( WM_GETMINMAXINFO == message ) + { + // First let the previous windowproc handle the WM_GETMINMAXINFO message + result = ::CallWindowProc( m_prevWndProc, m_hWndParent, message, wParam, lParam ); + MINMAXINFO * lpMMI = (MINMAXINFO * )lParam; + if( m_minTracking.cx == -1 ) + m_minTracking.cx = lpMMI->ptMinTrackSize.x; + + if( m_minTracking.cy == -1 ) + m_minTracking.cy = lpMMI->ptMinTrackSize.y; + + if( m_maxTracking.cx == -1 ) + m_maxTracking.cx = lpMMI->ptMaxTrackSize.x; + + if( m_maxTracking.cy == -1 ) + m_maxTracking.cy = lpMMI->ptMaxTrackSize.y; + + lpMMI->ptMinTrackSize.x = m_minTracking.cx; + lpMMI->ptMinTrackSize.y = m_minTracking.cy; + lpMMI->ptMaxTrackSize.x = m_maxTracking.cx; + lpMMI->ptMaxTrackSize.y = m_maxTracking.cy; + // flag message handled + handled = TRUE; + } + else + { + // if the original window had no resizing border + // we must serve WM_MOUSE, WM_NCLBUTTONDOWN and + // WM_LBUTTONUP to enable resizing + if( !m_hasResizingBorder ) + { + POINT mousePostion; + RECT currentRect; + + if( WM_MOUSEMOVE == message ) + { + if (m_hitCode && !m_inMouseMove ) + { + m_inMouseMove = TRUE; + + ::GetCursorPos( &mousePostion ); + mousePostion.x += m_delta.cx; + mousePostion.y += m_delta.cy; + + RECT m_previsionRect; + + ::GetWindowRect( m_hWndParent, ¤tRect ); + m_previsionRect = currentRect; + + switch( m_hitCode ) + { + case HTTOPLEFT : currentRect.left = mousePostion.x; // fall through + case HTTOP : currentRect.top = mousePostion.y; break; + + case HTBOTTOMRIGHT : currentRect.right = mousePostion.x; // fall through + case HTBOTTOM : currentRect.bottom = mousePostion.y; break; + + case HTBOTTOMLEFT : currentRect.bottom = mousePostion.y; // fall through + case HTLEFT : currentRect.left = mousePostion.x; break; + + case HTTOPRIGHT : currentRect.top = mousePostion.y; // fall through + case HTRIGHT : currentRect.right = mousePostion.x; break; + } + if (!::EqualRect( ¤tRect, &m_previsionRect )) + { + int width = currentRect.right - currentRect.left; + int height = currentRect.bottom - currentRect.top; + + ::SetWindowPos( m_hWndParent, HWND_DESKTOP, currentRect.left, currentRect.top, + width, height, SWP_NOZORDER | SWP_NOACTIVATE ); + } + m_inMouseMove = FALSE; + } + } + else if( WM_NCLBUTTONDOWN == message ) + { + ::GetCursorPos( &mousePostion ); + ::GetWindowRect( m_hWndParent, ¤tRect ); + + m_hitCode = wParam; + m_delta.cx = + m_delta.cy = 0; + + switch( m_hitCode ) + { + case HTTOPLEFT : m_delta.cx = currentRect.left - mousePostion.x; // fall through + case HTTOP : m_delta.cy = currentRect.top - mousePostion.y; break; + + case HTBOTTOMRIGHT : m_delta.cx = currentRect.right - mousePostion.x; // fall through + case HTBOTTOM : m_delta.cy = currentRect.bottom - mousePostion.y; break; + + case HTBOTTOMLEFT : m_delta.cy = currentRect.bottom - mousePostion.y; // fall through + case HTLEFT : m_delta.cx = currentRect.left - mousePostion.x; break; + + case HTTOPRIGHT : m_delta.cy = currentRect.top - mousePostion.y; // fall through + case HTRIGHT : m_delta.cx = currentRect.right - mousePostion.x; break; + + default : m_hitCode = 0; break; + } + + if (m_hitCode) + { + ::SetCapture( m_hWndParent ); + } + + } + else if( WM_LBUTTONUP == message ) + { + if (m_hitCode != 0) + { + ::ReleaseCapture(); + m_hitCode = 0; + } + } + } + } + return handled; +} +/////////////////////////////////////////////////////////////////////// +// MinMaxInfo Support + +BOOL CResizeCtrl::SetMinimumTrackingSize( const CSize & size ) +{ + m_minTracking = size; + return TRUE; +} +BOOL CResizeCtrl::SetMinimumTrackingSize() +{ + RECT rect; + ::GetWindowRect( m_hWndParent, &rect ); + return SetMinimumTrackingSize( CSize( rect.right - rect.left, rect.bottom - rect.top ) ); +} +CSize CResizeCtrl::GetMinimumTrackingSize( ) +{ + return m_minTracking; +} + +BOOL CResizeCtrl::SetMaximumTrackingSize( const CSize & size ) +{ + m_maxTracking = size; + return TRUE; +} +CSize CResizeCtrl::GetMaximumTrackingSize( ) +{ + return m_maxTracking; +} + + +void CResizeCtrl::GetGripRect(RECT & rect, BOOL redraw) +{ + GetClientRect( m_hWndParent, &rect ); + rect.left = rect.right - ::GetSystemMetrics(SM_CXVSCROLL) ; + rect.top = rect.bottom - ::GetSystemMetrics(SM_CYHSCROLL) ; + if( redraw ) + ::InvalidateRect( m_hWndParent, &rect, TRUE ); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.h new file mode 100644 index 0000000..92e855e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ResizeCtrl.h @@ -0,0 +1,187 @@ +// ResizeCtrl.h: interface for the CResizeCtrl class. +// +// +// Written by Herbert Menke (h.menke@gmx.de) +// Copyright (c) 2000. +// +// This code may be used in compiled form in any way you desire. This +// file may be redistributed unmodified by any means PROVIDING it is +// not sold for profit without the authors written consent, and +// providing that this notice and the authors name is included. If +// the source code in this file is used in any commercial application +// then acknowledgement must be made to the author of this file +// (in whatever form you wish). +// +// This file is provided "as is" with no expressed or implied warranty. +// +// Expect bugs. +// +// Please use and enjoy. Please let me know of any bugs/mods/improvements +// that you have found/implemented and I will fix/incorporate them into this +// file. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESIZECTRL_H__3CD44893_48A2_11D4_880C_00902755BD88__INCLUDED_) +#define AFX_RESIZECTRL_H__3CD44893_48A2_11D4_880C_00902755BD88__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CResizeArray; + +struct CResizeInfo +{ + int ctlID; // Specifies the identifier of the control + int left; // Specifies the change in the position of the left edge + // of the object relative to the total change in the parent window’s width. + int top; // Specifies the change in the position of the top + // of the object relative to the total change in the parent window’s height. + int width; // Specifies the change in the width of the object + // relative to the total change in the parent window’s width. + int height; // Specifies the change in the height of the object + // relative to the total change in the parent window’s height. +}; + +class CResizeCtrl +{ +public: + + // + // Add Method + // + + // Adds a control window to the list to be resized + + // left, top, width and height determines how the size and position of the control window + // will change when the size of the parent window changes. + + // In general, the formula is + // + // newValue = oldValue + (( deltaValueParent * partValue) / maxPart ); + // + // newValue - new left or top position or new width or height + // oldValue - old left or top position or old width or height + // deltaValueParent - changes in parent width or height + // partValue - left, top, width or height value specified in the Add Method + // maxPart - value specified by the maxPart parameter of the constructor + // or the Create method + + // + // left - Specifies the change in the position of the left edge + // of the object relative to the total change in the parent window’s width. + // For example: suppose that left is 50 and the width of the window increases by 200 pixels. + // Then the left edge of the object moves right by 100 pixels (50% of 200). + // top - Specifies the change in the top position + // of the object relative to the total change in the parent window’s height. + // width - Specifies the change in the width of the object + // relative to the total change in the parent window’s width. + // For example: suppose that width is zero. Then the width of the object does not change, + // regardless of how much the width of the parent window changes. + // suppose that width is 100 and the width of the window decreases by 50 pixels. + // Then the width of the object also decreases by 50 pixels (100% of 50). + // height - Specifies the change in the height of the object + // relative to the total change in the parent window’s height. + + BOOL Add( HWND hWndCtl, int left, int top, int width, int height ); + BOOL Add( int ctlID, int left, int top, int width, int height ); + BOOL Add( CWnd * wndCtl, int left, int top, int width, int height ); + + // resizeInfo is a null terminated array of CResizeInfo + + BOOL Add( const CResizeInfo * resizeInfo ); + + // + // Remove Method + // + + // Removes a control window from the list to be resized + + BOOL Remove( HWND hWndCtl ); + BOOL Remove( int ctlID ); + BOOL Remove( CWnd * wndCtl ); + + // enabled + // TRUE returns the position and size before resizing was enabled + // FALSE returns the last position and size before resizing was disabled + + BOOL GetWindowRect( RECT * rect ); + + // + // Construction + // + + BOOL Create( HWND hWndParent, BOOL enabled = TRUE, int maxPart = 100 ); + BOOL Create( CWnd * wndParent, BOOL enabled = TRUE, int maxPart = 100 ); + + CResizeCtrl(); + CResizeCtrl( HWND hWndParent, BOOL enabled = TRUE, int maxPart = 100 ); + CResizeCtrl( CWnd * wndParent, BOOL enabled = TRUE, int maxPart = 100 ); + virtual ~CResizeCtrl(); + + // + // Enabled Property + // + + // enable or disable resizing + + BOOL SetEnabled( BOOL enable ); + BOOL GetEnabled() const; + + // + // GripEnabled Property + // + + BOOL SetGripEnabled( BOOL showGrip ); + BOOL GetGripEnabled() const ; + + /////////////////////////////////////////////////////////////////////// + // + // MinMax Support + // + BOOL SetMinimumTrackingSize( const CSize & size ); + BOOL SetMinimumTrackingSize( ); + CSize GetMinimumTrackingSize( ); + + BOOL SetMaximumTrackingSize( const CSize & size ); + CSize GetMaximumTrackingSize( ); + +private: + void GetGripRect( RECT & rect, BOOL redraw ); + // Resize the controls + void Resize(int cx, int cy) ; + // processes the messages for resizing + BOOL ProcessMessage( UINT message, WPARAM wParam, LPARAM lParam, LRESULT & result ); + // adds or removes style WS_THICKFRAME of the aprent window + void ChangeStyle( BOOL enable ); + // initialise the control + // calculates the new left, top, width or height + BOOL CalcValue(int delta, int part, int & pending, long & position, BOOL isSize); + // subclass window proc + static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ); + + BOOL m_hasResizingBorder; // TRUE if the parent has a resizing border + WNDPROC m_prevWndProc; // previous Window Proc + BOOL m_enabled; // parent is subclassed + int m_maxPart; // max PartValue + HWND m_hWndParent; // handle of the paretn window + CSize m_size; // width and heigth of the parent window + CResizeArray * m_array; // parameters of registered controls + ///////////////////////////////////////////////// + CSize m_maxTracking; // parameters for max Tracking + CSize m_minTracking; // parameters for min Tracking + ///////////////////////////////////////////////// + BOOL m_inResize; // flag to prevent recursion in WM_SIZE + ///////////////////////////////////////////////// + int m_hitCode; // stored hitCode from WM_NCLBUTTONDOWN + CSize m_delta; // stored delta Size from WM_NCLBUTTONDOWN + BOOL m_inMouseMove; // flag to prevent recursion in WM_MOUSEMOVE + ///////////////////////////////////////////////// + CRect m_gripRect; // position and size of the grip rect + BOOL m_gripEnabled; // TRUE, if grip is enabled + ///////////////////////////////////////////////// + CRect m_windowRect; // last Window position and Size +}; + +#endif // !defined(AFX_RESIZECTRL_H__3CD44893_48A2_11D4_880C_00902755BD88__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.cpp new file mode 100644 index 0000000..16fb8bb --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.cpp @@ -0,0 +1,739 @@ +// RptSetDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "RptSetDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CRptSetDlg dialog + + +CRptSetDlg::CRptSetDlg(CWnd* pParent /*=NULL*/) +: CDialog(CRptSetDlg::IDD, pParent) +, m_strCurrentReportPath(_T("")) +{ + //{{AFX_DATA_INIT(CRptSetDlg) + //}}AFX_DATA_INIT + + m_pApp = (CSpApp*)AfxGetApp(); + + /* + rs=new GZRset("Error: Report settings screen "); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + + rs=m_pApp->rsPool->GetRS("CRptSetDlg"); + cryp=new GZK; + m_bNew=false; + m_bEditing=false; + //indicates run first + bFirstRun=true; +} + +CRptSetDlg::~CRptSetDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + delete cryp; +} + + +void CRptSetDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CRptSetDlg) + DDX_Control(pDX, IDC_BTNSELECTREPORT, m_btnSelectReport); + DDX_Control(pDX, IDC_BTNSELECTPRINTER, m_btnSelectPrinter); + DDX_Control(pDX, IDC_BTNRESET, m_btnReset); + DDX_Control(pDX, IDC_BTNDEFAULTREPORT, m_btnDefaultReport); + DDX_Control(pDX, IDC_BTNDEFAULTPRINTER, m_btnDefaultPrinter); + DDX_Control(pDX, IDC_CKPREVIEW, m_ckPreview); + DDX_Control(pDX, IDC_EDPRINTERSELECTED, m_edPrinterSelected); + DDX_Control(pDX, IDC_EDCUSTOMREPORTSELECTED, m_edCustomReport); + DDX_Control(pDX, IDC_EDCOPIES, m_edCopies); + DDX_Control(pDX, IDC_CBREPORTS, m_cbReports); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_LBL_DEFAULT_REPORT_FILE, m_lblDefaultReportFile); +} + + +BEGIN_MESSAGE_MAP(CRptSetDlg, CDialog) +//{{AFX_MSG_MAP(CRptSetDlg) +ON_BN_CLICKED(IDC_BTNDEFAULTPRINTER, OnBtndefaultprinter) +ON_BN_CLICKED(IDC_BTNSELECTPRINTER, OnBtnselectprinter) +ON_BN_CLICKED(IDC_BTNDEFAULTREPORT, OnBtndefaultreport) +ON_BN_CLICKED(IDC_BTNSELECTREPORT, OnBtnselectreport) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_BN_CLICKED(IDC_BTNRESET, OnBtnreset) +ON_CBN_CLOSEUP(IDC_CBREPORTS, OnCloseupCbreports) + //}}AFX_MSG_MAP + ON_BN_CLICKED(IDC_CKPREVIEW, OnBnClickedCkpreview) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CRptSetDlg message handlers + +void CRptSetDlg::OnOK() +{ + //enter key override hack + + +} + +void CRptSetDlg::OnBtndefaultprinter() +{ + m_edPrinterSelected.SetWindowText("< Windows default printer >"); + +} + +void CRptSetDlg::OnBtnselectprinter() +{ + CString msg; + CString strTemp; + CString strPage; + try { + + //m_strSampleReportPath=m_pApp->ReportDirectory() +"clientpb.rpt"; + + + m_Report=m_pApp->pApplication->OpenReport(_bstr_t(m_strCurrentReportPath)); + + //Set to previous defaults if any + m_edPrinterSelected.GetWindowText(strTemp); + if(strTemp!="< Windows default printer >") + { + m_Report->SelectPrinter(_bstr_t(m_strDRIVER),_bstr_t(m_strDEVICE),_bstr_t(m_strPORT)); + m_Report->PutPaperOrientation((CRPaperOrientation)m_lPaperOrientation); + m_Report->PutPaperSize((CRPaperSize)m_lPaperSize); + m_Report->PutPaperSource((CRPaperSource)m_lPaperSource); + m_Report->PutPrinterDuplex((CRPrinterDuplexType)m_lDuplexType); + } + + m_Report->PrinterSetup(0); + + + m_strDEVICE=(LPCTSTR) m_Report->GetPrinterName(); + m_strDRIVER=(LPCTSTR) m_Report->GetDriverName(); + m_strPORT=(LPCTSTR) m_Report->GetPortName(); + m_lPaperOrientation=m_Report->GetPaperOrientation(); + m_lPaperSize=m_Report->GetPaperSize(); + m_lPaperSource=m_Report->GetPaperSource(); + m_lDuplexType=m_Report->GetPrinterDuplex(); + + strPage=FormatPaperSettingsString(); + + + + if(m_strDEVICE.IsEmpty())//default printer? + strTemp="< Windows default printer >"; + else + strTemp.Format("%s on %s",m_strDEVICE,m_strPORT); + + msg.Format("%s\r\nPaper settings: %s",strTemp,strPage); + m_edPrinterSelected.SetWindowText(msg); + /*CRPaperOrientation crPaperOrientation=m_Report->GetPaperOrientation(); + CRPaperSize crPaperSize=m_Report->GetPaperSize(); + CRPaperSource crPaperSource=m_Report->GetPaperSource(); + CRPrinterDuplexType crDuplexType=m_Report->GetPrinterDuplex(); + + long lPaperSize=(long)m_Report->GetPaperSize(); + m_Report->PaperSize=(CRPaperSize)lPaperSize;*/ + + + } + catch(_com_error& e) + { + + CString strErr; + _bstr_t bstrSource(e.Source()); + _bstr_t bstrDescription(e.Description()); + TRACE("*************************************************\n"); + TRACE("Exception thrown for classes generated by #import\n"); + TRACE("\tCode = %081x\n", e.Error); + TRACE("\tCode Meaning = %s\n", e.ErrorMessage()); + TRACE("\tSource = %s\n", (LPCTSTR) bstrSource); + TRACE("Description = %s\n", (LPCTSTR) bstrDescription); + TRACE("*************************************************\n"); + strErr.Format( + + "Error: Crystal Reports RDC printing engine\r\n" + "Full error is:\r\n\r\n" + + "Code = %x\r\n" + "Code Meaning = %s\r\n" + "Source = %s\r\n" + "Description = %s\r\n\r\n" + ,e.Error,e.ErrorMessage(),(LPCTSTR) bstrSource,(LPCTSTR) bstrDescription); + m_pApp->ShowStuff(strErr); + //HandleComError(e,strLocalError); + } + return; +} + +void CRptSetDlg::OnBtndefaultreport() +{ + m_edCustomReport.SetWindowText("< Default >"); +} + +void CRptSetDlg::OnBtnselectreport() +{ + static char BASED_CODE szFilter[] = "Report files (*.rpt)|*.rpt||"; + CString ReportSelected; + CFileDialog f(true,"rpt",NULL,OFN_FILEMUSTEXIST|OFN_HIDEREADONLY,szFilter,NULL); + //f.m_ofn.lpstrInitialDir=m_pApp->m_WasRunFrom; + f.DoModal(); + ReportSelected=f.GetPathName(); + if(ReportSelected.GetLength()>0) + m_edCustomReport.SetWindowText(ReportSelected); + + +} + +void CRptSetDlg::OnBtndone() +{ + SaveRecord(); + CDialog::OnOK(); +} + + + + +void CRptSetDlg::OnCloseupCbreports() +{ + CString q,strTemp; + //Save the settings of the previously selected report + if(!bFirstRun) + SaveRecord(); + + //Now move on to the newly selected report + m_strCurrentReport=m_cbReports.GetCurrentRowID(); + + q.Format("SELECT rptsmaster.filename " + "FROM rptsmaster " + "WHERE (((rptsmaster.virtualname)=\"%s\"));",m_strCurrentReport); + if(rs->QueryReadOnly(q)) + { + rs->FetchField("filename",&strTemp); + m_strCurrentReportPath=m_pApp->ReportDirectory()+strTemp; + + } + + q.Format("SELECT rptsusers.* FROM rptsusers " + "WHERE (((rptsusers.virtualname)=\"%s\") AND ((rptsusers.user)=%u));",m_strCurrentReport,m_pApp->m_lusrID); + rs->Query(q); + if(rs->IsEmpty()) + {//making a new record + m_bNew=true; + m_bEditing=false; + ClearFields(); + } + else + {//editing an existing one + FillFields(); + m_bEditing=true; + m_bNew=false; + } + bFirstRun=false; + + strTemp.Format("Default file: %s",m_strCurrentReportPath); + m_lblDefaultReportFile.SetWindowText(strTemp); +} + + + +BOOL CRptSetDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + long lData; + Security(); + + CString strData,strRecordSet,strOriginal; + + strData.Format("%s - Custom report settings",m_pApp->m_strCurrentUserName); + SetWindowText(strData); + m_cbReports.Clear(); + rs->Query("SELECT rptsmaster.* FROM rptsmaster ORDER BY rptsmaster.virtualname;"); + + + ASSERT(!rs->IsEmpty()); + + do{ + + //added check for report id 3 as this points + //to a "work order list" report which doesn't really + //exist any more. + + //Note this is lazy, properly should have removed it + //from the db, but there was no other reason to update the + //db for this update and it's always problematic to do so + //un-necessarily. + rs->FetchField("id",&lData); + if(lData!=3) + { + rs->FetchField("virtualname",&strData); + strOriginal=strData; + strData.Remove('&'); + rs->FetchField("recordset",&strRecordSet); + if(strRecordSet=="woquick") strData="Quick WO - " + strData; + if(strRecordSet=="wostandard") strData="Standard WO - " + strData; + + m_cbReports.AddRow(strData,strOriginal); + } + + }while(rs->MoveForward()); + m_cbReports.Select(0);//should just go to first one + + OnCloseupCbreports(); + + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + +void CRptSetDlg::FillFields() +{ + CString str1,str2,msg,strPage,strTemp; + bool bData; + long lData; + + + //PRINTER SETTINGS + + rs->FetchField("port",&m_strPORT); + rs->FetchField("device",&m_strDEVICE); + rs->FetchField("driver",&m_strDRIVER); + + rs->FetchField("porient",&m_lPaperOrientation); + rs->FetchField("psize",&m_lPaperSize); + rs->FetchField("psource",&m_lPaperSource); + rs->FetchField("pduplex",&m_lDuplexType); + + rs->FetchField("defaultprtr",&bData); + if(bData) + m_edPrinterSelected.SetWindowText("< Windows default printer >"); + else + { + strPage=FormatPaperSettingsString(); + if(m_strDEVICE.IsEmpty()) + strTemp="< Windows default printer >"; + else + strTemp.Format("%s on %s",m_strDEVICE,m_strPORT); + + msg.Format("%s\r\nPaper settings: %s",strTemp,strPage); + m_edPrinterSelected.SetWindowText(msg); + } + + //CUSTOM REPORT + rs->FetchField("filename",&str1); + if(str1=="na") + m_edCustomReport.SetWindowText("< Default >"); + else + m_edCustomReport.SetWindowText(str1); + + //COPIES + rs->FetchField("copies",&lData); + str1.Format("%u",lData); + m_edCopies.SetWindowText(str1); + + //PREVIEW + rs->FetchField("preview",&bData); + m_ckPreview.SetCheck(bData ? TRUE:FALSE); + if(bData) + m_edCopies.EnableWindow(FALSE); + else + m_edCopies.EnableWindow(TRUE); + + + + + + +} + + + +void CRptSetDlg::ClearFields() +{ + m_edCustomReport.SetWindowText("< Default >"); + m_edPrinterSelected.SetWindowText("< Windows default printer >"); + m_ckPreview.SetCheck(TRUE); + m_edCopies.EnableWindow(FALSE); + m_edCopies.SetWindowText("1"); +} + + + + +void CRptSetDlg::OnBtnreset() +{ + ClearFields(); + +} + +void CRptSetDlg::SaveRecord() +{ + CString strData,report,printer,q; + bool bData,alldefaults,preview; + alldefaults=false; + long lData; + m_edCopies.GetWindowText(strData); + lData=atol(strData); + + preview=m_ckPreview.GetCheck() ? true:false; + + m_edCustomReport.GetWindowText(report); + m_edPrinterSelected.GetWindowText(printer); + + //see if user has selected all default settings + //in other words, these are the settings that would + //be in effect if a user record was not found, + //so to be efficient, we can delete if there is one + // or not save if there isn't + if(report=="< Default >" && printer=="< Windows default printer >" + && lData==1 && preview==true) + alldefaults=true; + + + if(alldefaults) + { + if(m_bEditing)//delete this record + { + q.Format("DELETE rptsusers.*, rptsusers.virtualname, rptsusers.user " + "FROM rptsusers WHERE (((rptsusers.virtualname)=\"%s\") " + "AND ((rptsusers.user)=%u));",m_strCurrentReport,m_pApp->m_lusrID); + rs->Ex(q); + + + } + + m_bNew=false; + m_bEditing=false; + return;//bail, our work here is done + + } + + //THINGS TO DO WHEN YOU DONT EXIST YET..... + if(m_bNew)//make new record + rs->AddNewRecord(); + + + //UPDATE each field + rs->UpdateField("virtualname",&m_strCurrentReport); + rs->UpdateField("user",&m_pApp->m_lusrID); + + m_edCustomReport.GetWindowText(strData); + if(strData=="< Default >") strData="na"; + rs->UpdateField("filename",&strData); + + + + m_edPrinterSelected.GetWindowText(strData); + if(strData=="< Windows default printer >") + { + m_strDEVICE.Empty(); + m_strDRIVER.Empty(); + m_strPORT.Empty(); + bData=true; + } + else + bData=false; + rs->UpdateField("defaultprtr",&bData); + + + m_edCopies.GetWindowText(strData); + if(strData.IsEmpty()) + strData="1"; + lData=atol(strData); + if(lData==0) lData=1; + rs->UpdateField("copies",&lData); + + bData=m_ckPreview.GetCheck() ? true:false; + rs->UpdateField("preview",&bData); + + rs->UpdateField("driver",&m_strDRIVER); + + rs->UpdateField("device",&m_strDEVICE); + rs->UpdateField("port",&m_strPORT); + + rs->UpdateField("porient",&m_lPaperOrientation); + rs->UpdateField("psize",&m_lPaperSize); + rs->UpdateField("psource",&m_lPaperSource); + rs->UpdateField("pduplex",&m_lDuplexType); + + + + //SAVE + rs->SaveRecord(); + m_bNew=false; + m_bEditing=false; +} + + + +void CRptSetDlg::Security() +{ +//m_bReadOnly=false; + int x=m_pApp->Allowed(RPRINTSETUP,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + //m_bReadOnly=true; + //m_ckCustomDefault.EnableWindow(FALSE); + m_ckPreview.EnableWindow(FALSE); + m_edCopies.SetReadOnly(TRUE); + m_edCustomReport.SetReadOnly(TRUE); + m_edPrinterSelected.SetReadOnly(TRUE); + m_btnDefaultPrinter.ShowWindow(FALSE); + m_btnDefaultReport.ShowWindow(FALSE); + m_btnReset.ShowWindow(FALSE); + m_btnSelectPrinter.ShowWindow(FALSE); + m_btnSelectReport.ShowWindow(FALSE); + + + + } +} + + +//Generate a string to represent all current paper +//settings +CString CRptSetDlg::FormatPaperSettingsString(void) +{ + CString strPage; + switch(m_lPaperOrientation) + { + case 0://default paper, say nothing + break; + case 1://portrait + strPage="Portrait, "; + break; + case 2://landscape + strPage="Landscape, "; + break; + + } + +switch(m_lPaperSize) + { + case 0://default paper size, say nothing + break; + case 16://10X14 + strPage+="10x14, "; + break; + case 17: + strPage+="11x17, "; + break; + case 8: + strPage+="A3, "; + break; + case 9: + strPage+="A4, "; + break; + case 10: + strPage+="A4 small, "; + break; + case 11: + strPage+="A5, "; + break; + case 12: + strPage+="B4, "; + break; + case 13: + strPage+="B5, "; + break; + case 24: + strPage+="C sheet, "; + break; + case 25: + strPage+="D sheet, "; + break; + case 20: + strPage+="#10 envelope, "; + break; + case 21: + strPage+="#11 envelope, "; + break; + case 22: + strPage+="#12 envelope, "; + break; + case 23: + strPage+="#14 envelope, "; + break; + case 19: + strPage+="#9 envelope, "; + break; + case 33: + strPage+="B4 envelope, "; + break; + case 34: + strPage+="B5 envelope, "; + break; + case 35: + strPage+="B6 envelope, "; + break; + case 29: + strPage+="C3 envelope, "; + break; + case 30: + strPage+="C4 envelope, "; + break; + case 28: + strPage+="C5 envelope, "; + break; + case 31: + strPage+="C6 envelope, "; + break; + case 32: + strPage+="C65 envelope, "; + break; + case 27: + strPage+="DL envelope, "; + break; + case 36: + strPage+="Italy envelope, "; + break; + case 37: + strPage+="Monarch envelope, "; + break; + case 38: + strPage+="Personal envelope, "; + break; + case 26: + strPage+="E sheet, "; + break; + case 7: + strPage+="Executive, "; + break; + case 41: + strPage+="German fanfold legal, "; + break; + case 40: + strPage+="German fanfold standard, "; + break; + case 39: + strPage+="US fanfold, "; + break; + case 14: + strPage+="Folio, "; + break; + case 4: + strPage+="Ledger, "; + break; + case 5: + strPage+="Legal, "; + break; + case 1: + strPage+="Letter, "; + break; + case 2: + strPage+="Letter small, "; + break; + case 18: + strPage+="Note, "; + break; + case 15: + strPage+="Quatro, "; + break; + case 3: + strPage+="Tabloid, "; + break; + case 6: + strPage+="Statement, "; + break; + case 256: + strPage+="Custom size, "; + break; + + + } + + switch(m_lPaperSource) + { + case 0: + break; + case 7://default paper source, say nothing + break; + case 14: + strPage+="Cassette tray, "; + break; + case 5: + strPage+="Envelope tray, "; + break; + case 6: + strPage+="Manual envelope tray, "; + break; + case 15: + strPage+="Form source tray, "; + break; + case 11: + strPage+="Large capacity tray, "; + break; + case 10: + strPage+="Large format tray, "; + break; + case 2: + strPage+="Lower tray, "; + break; + case 4: + strPage+="Manual tray, "; + break; + case 3: + strPage+="Middle tray, "; + break; + case 9: + strPage+="Small format tray, "; + break; + case 8: + strPage+="Tractor feed tray, "; + break; + case 1: + strPage+="Upper tray, "; + break; + + } +switch(m_lDuplexType) + { + case 0: + break; + case 1: + //strPage+="Simplex duplex "; + break; + case 2: + strPage+="Vertical duplex, "; + break; + case 3: + strPage+="Horizontal duplex, "; + break; + + } + +strPage.TrimRight(); +strPage.TrimRight(','); + + + + return strPage; +} + +void CRptSetDlg::OnBnClickedCkpreview() +{ + if(m_ckPreview.GetCheck()) + m_edCopies.EnableWindow(FALSE); + else + m_edCopies.EnableWindow(TRUE); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.h new file mode 100644 index 0000000..86a431e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/RptSetDlg.h @@ -0,0 +1,101 @@ +#if !defined(AFX_RPTSETDLG_H__E013A0C2_3DD8_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_RPTSETDLG_H__E013A0C2_3DD8_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// RptSetDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CRptSetDlg dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "gzk.h" +#include "afxwin.h" +#import "C:\Program Files\Crystal Decisions\Report Designer Component\craxdrt9.dll" no_namespace rename("FindText","crFindText") + +class CRptSetDlg : public CDialog +{ +// Construction +public: + void Security(); + //long m_lDevModeSize; + ~CRptSetDlg(); + bool bFirstRun; + void SaveRecord(); + //required variables for printing + //CString m_strDEVMODE; + CString m_strPORT; + CString m_strDEVICE; + CString m_strDRIVER; + long m_lPaperOrientation; + long m_lPaperSize; + long m_lPaperSource; + long m_lDuplexType; + + CString m_strCurrentReport; + + void ClearFields(); + void FillFields(); + bool m_bEditing; + bool m_bNew; + + CRptSetDlg(CWnd* pParent = NULL); // standard constructor + GZRset* rs; + GZK* cryp; + CSpApp* m_pApp; +// Dialog Data + //{{AFX_DATA(CRptSetDlg) + enum { IDD = IDD_REPORTSETUP }; + CButton m_btnSelectReport; + CButton m_btnSelectPrinter; + CButton m_btnReset; + CButton m_btnDefaultReport; + CButton m_btnDefaultPrinter; + CButton m_ckPreview; + CEdit m_edPrinterSelected; + CEdit m_edCustomReport; + CEdit m_edCopies; + //CButton m_ckCustomDefault; + CgzCombo m_cbReports; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CRptSetDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +private: + IReportPtr m_Report; +protected: + + // Generated message map functions + //{{AFX_MSG(CRptSetDlg) + virtual void OnOK(); + afx_msg void OnBtndefaultprinter(); + afx_msg void OnBtnselectprinter(); + afx_msg void OnBtndefaultreport(); + afx_msg void OnBtnselectreport(); + afx_msg void OnBtndone(); + afx_msg void OnBtnreset(); + afx_msg void OnCkcustdefault(); + afx_msg void OnCloseupCbreports(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + CString m_strCurrentReportPath; + CStatic m_lblDefaultReportFile; + CString FormatPaperSettingsString(void); + afx_msg void OnBnClickedCkpreview(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RPTSETDLG_H__E013A0C2_3DD8_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.cpp new file mode 100644 index 0000000..cd3b704 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.cpp @@ -0,0 +1,2644 @@ +// SRCH.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "SRCH.h" +#include "ted.h" +#include "SrchView.h" +#include "ClientsDlg.h" +#include "loanerseditdlg.h" +#include "ContactsViewDlg.h" +#include "unitsdlg.h" + +#include "SnREdit.h" + +#define WORDWINDOW 60 //# of characters on either side of keyword in window + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +//memory leak debugging help +#define _CRTDBG_MAP_ALLOC +#include +#include +///////////////////////////////////////////////////////////////////////////// +// SRCH + +IMPLEMENT_DYNCREATE(SRCH, CFormView) + +SRCH::SRCH() +: CFormView(SRCH::IDD) +, m_nCX(0) +{ + //{{AFX_DATA_INIT(SRCH) + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + + + +rs=m_pApp->rsPool->GetRS("SRCH (RS)"); +rs2=m_pApp->rsPool->GetRS("SRCH (RS2)"); + + m_strOrderBy="ORDER BY srch.rank DESC"; + +} + +SRCH::~SRCH() +{ + DeActivate(); +} + +void SRCH::DoDataExchange(CDataExchange* pDX) +{ + CFormView::DoDataExchange(pDX); + //{{AFX_DATA_MAP(SRCH) + DDX_Control(pDX, IDC_EDBAD, m_edBad); + DDX_Control(pDX, IDC_EDSEARCHTERMS, m_edSearchTerms); + DDX_Control(pDX, IDC_LBLBETWEEN, m_lblBetween); + DDX_Control(pDX, IDC_LBLAND, m_lblAnd); + DDX_Control(pDX, IDC_DTDATE2, m_dtDate2); + DDX_Control(pDX, IDC_LBLRESULTS, m_lblResults); + DDX_Control(pDX, IDC_LBLBAD, m_lblBad); + DDX_Control(pDX, IDC_BTNSEARCH, m_btnSearch); + DDX_Control(pDX, IDC_CBCLIENTS, m_cbClients); + DDX_Control(pDX, IDC_CKPREVIEW, m_ckPreview); + DDX_Control(pDX, IDC_CBDATE, m_cbDate); + DDX_Control(pDX, IDC_DTDATE, m_dtDate); + DDX_Control(pDX, IDC_REPORT, m_rc); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_LBL_DATE_RANGE, m_lblDateRange); + DDX_Control(pDX, IDC_LBL_CLIENTS, m_lblClients); + DDX_Control(pDX, IDC_LBL_KEYWORDS, m_lblKeyWords); +} + + +BEGIN_MESSAGE_MAP(SRCH, CFormView) +//{{AFX_MSG_MAP(SRCH) +ON_BN_CLICKED(IDC_BTNSEARCH, OnBtnsearch) +ON_CBN_CLOSEUP(IDC_CBDATE, OnCloseupCbdate) +ON_NOTIFY(RVN_ITEMDBCLICK, IDC_REPORT, OnRvnItemDbClick) +ON_NOTIFY(RVN_COLUMNCLICK, IDC_REPORT, OnColumnClick) +ON_NOTIFY(RVN_ITEMDRAWPREVIEW, IDC_REPORT, OnRvnItemDrawPreview) +//}}AFX_MSG_MAP +ON_WM_SIZE() +ON_WM_HELPINFO() +ON_CBN_SELCHANGE(IDC_CBCLIENTS, OnCbnSelchangeCbclients) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// SRCH diagnostics + +#ifdef _DEBUG +void SRCH::AssertValid() const +{ + CFormView::AssertValid(); +} + +void SRCH::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// SRCH message handlers + +void SRCH::Activate() +{ + + #ifdef _WTF_ + AfxMessageBox("SRCH activate"); + #endif + /* + if(rs==NULL) + { + rs = new GZRset("Error in rs.SRCH"); + rs->SetConnect(m_pApp->strConnectString); + } + */ + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("SRCH (RS)"); +rs2=m_pApp->rsPool->GetRS("SRCH (RS2)"); + + m_edSearchTerms.SetFocus(); + //m_edSearchTerms.SetWindowText("print* problem tray not paper"); +} + +void SRCH::DeActivate() +{ + + #ifdef _WTF_ + AfxMessageBox("SRCH De-activate"); + #endif + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs2->m_nID); + /* +if(rs!=NULL) + { + delete rs; + rs=NULL; + } + +if(rs2!=NULL) + { + delete rs2; + rs2=NULL; + } + */ +/* +CString profile; +m_rc.WriteProfile(&profile); +AfxMessageBox(profile); + */ +} + + + +void SRCH::OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + CString str,strID,q,strData,strWOID; + COleDateTime dtData; + int nTable; + long lID,lData; + bool bQuickWO=false; + CSrchView sv; + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + //FLAG THIS LIST ITEM AS CLICKED HERE + + + /*if(rs==NULL) + { + rs = new GZRset("Error in Search.rs.OnSrchView"); + rs->SetConnect(m_pApp->strConnectString); + }*/ + + + nTable=atoi(m_rc.GetItemText(lpnmrv->iItem,5)); + strID=m_rc.GetItemText(lpnmrv->iItem,4); + lID=atol(strID); + + + + //GET ORIGINAL TABLE DATA DEPENDING ON TYPE IF NECESSARY + //AND DISPLAY + switch(nTable) + { + case 0://problems + { + q.Format("SELECT [users].[last] & \", \" & [users].[first] AS techname, labor.details, probs.brief, probs.notes, IIf(IsNull([company]),[clients].[last] & \", \" & [clients].[first],[company]) AS clientname, wo.quick, wo.id AS woid " + "FROM (((labor RIGHT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN users ON labor.tech = users.id " + "WHERE (((probs.id)=%u));",lID); +#ifdef _DEBUG +//m_pApp->ShowStuff(q); +#endif + + rs->QueryReadOnly(q); + rs->FetchField("woid",&lData); + strWOID.Format("%u",lData); + rs->FetchField("quick",&bQuickWO); + str="CLIENT: "; + rs->FetchField("clientname",&strData); + str+= strData + "\r\n\r\nTECH: "; + rs->FetchField("techname",&strData); + str+=strData + "\r\n"; + if(!bQuickWO) + { + str+= "\r\nPROBLEM: "; + rs->FetchField("brief",&strData); + str+=strData + "\r\n"; + rs->FetchField("notes",&strData); + str+=strData + "\r\n"; + } + + rs->FetchField("details",&strData); + str+="\r\nSERVICE DETAILS:\r\n" + strData; + + str+="\r\n\r\n(note: click on EDIT button below to show entire workorder)"; + + //Display srchview for labour records + sv.m_pstrText=&str; + sv.m_pslHiWords=&strList; + if(m_bUseKeywords) + sv.m_nKeywords=m_nSWords; + else + sv.m_nKeywords=0; + + sv.m_bQuickWO=bQuickWO; + sv.m_strWOID=strWOID; + sv.DoModal(); + } + break; + + case 1://labour + { + q.Format("SELECT [users].[last] & \", \" & [users].[first] AS techname, labor.details, probs.brief, probs.notes, IIf(IsNull([company]),[clients].[last] & \", \" & [clients].[first],[company]) AS clientname, wo.quick, wo.id AS woid " + "FROM (((labor LEFT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN users ON labor.tech = users.id " + "WHERE (((labor.id)=%u));",lID); + + rs->QueryReadOnly(q); + rs->FetchField("woid",&lData); + strWOID.Format("%u",lData); + rs->FetchField("quick",&bQuickWO); + str="Workorder #: " + strWOID + "\r\n"; + str+="\r\nCLIENT: "; + rs->FetchField("clientname",&strData); + str+= strData + "\r\n\r\nTECH: "; + rs->FetchField("techname",&strData); + str+=strData + "\r\n"; + if(!bQuickWO) + { + str+= "\r\nPROBLEM: "; + rs->FetchField("brief",&strData); + str+=strData + "\r\n"; + rs->FetchField("notes",&strData); + str+=strData + "\r\n"; + } + + rs->FetchField("details",&strData); + str+="\r\nSERVICE DETAILS:\r\n" + strData; + + str+="\r\n\r\n(note: click on EDIT button below to show entire workorder)"; + //Display srchview for labour records + sv.m_pstrText=&str; + sv.m_pslHiWords=&strList; + if(m_bUseKeywords) + sv.m_nKeywords=m_nSWords; + else + sv.m_nKeywords=0; + sv.m_bQuickWO=bQuickWO; + sv.m_strWOID=strWOID; + sv.DoModal(); + } + break; + + case 2://subrepair + + { + CSnREdit srd; + srd.m_strSubRepairID=strID; + srd.DoModal(); + } + break; + + case 3://rentals + { + CLoanersEditDlg ld; + ld.SetRentalID(&strID); + ld.DoModal(); + } + + break; + + case 4://clients + { + CClientsDlg cd; + cd.m_strForceSelection.Format("%u",lID); + cd.DoModal(); + } + + break; + case 5://contacts + { + q.Format("SELECT contacts.id, contacts.clientlink " + "FROM contacts " + "WHERE (((contacts.id)=%u));",lID); + rs->QueryReadOnly(q); + rs->FetchField("clientlink",&lID); + strData.Format("%u",lID); + CContactsViewDlg cd; + cd.Setup(strData); + cd.DoModal(); + } + + break; + case 6://units + { + /* + q.Format("SELECT units.sn FROM units " + "WHERE (((units.id)=%u));",lID); + rs->Query(q); + rs->FetchField("sn",&strData); + */ + //strData.Format("%u",lID); + CString empty; + empty.Empty(); + CUnitsDlg cd; + cd.SetReturnStrings(&strID,&empty); + //cd.m_strSelectedUnit=strData; + cd.DoModal(); + } + + break; + + case 7://workorder header added May 10, 2001 + { + + + q.Format("SELECT [users].[last] & \", \" & [users].[first] AS techname, labor.details, probs.brief, probs.notes, IIf(IsNull([company]),[clients].[last] & \", \" & [clients].[first],[company]) AS clientname, wo.quick, wo.id AS woid, " + "wo.notes, wo.invoice, wo.clientrefnum, wo.clientcontact, wo.ourref " + "FROM (((labor RIGHT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN users ON labor.tech = users.id " + "WHERE (((wo.id)=%u));",lID); + + +#ifdef _DEBUG +//m_pApp->ShowStuff(q); +#endif + + rs->QueryReadOnly(q); + rs->FetchField("woid",&lData); + strWOID.Format("%u",lData); + rs->FetchField("quick",&bQuickWO); + + str.Format("WORKORDER: %s",strWOID); + + str+= "\r\nCLIENT REFERENCE#: "; + rs->FetchField("clientrefnum",&strData); + str+=strData; + + str+= "\r\nCLIENT CONTACT: "; + rs->FetchField("clientcontact",&strData); + str+=strData; + + str+= "\r\nOUR REFERENCE#: "; + rs->FetchField("ourref",&strData); + str+=strData; + + str+= "\r\n\r\nCLIENT: "; + rs->FetchField("clientname",&strData); + str+=strData + "\r\n"; + + str+= strData + "\r\n\r\nTECH: "; + rs->FetchField("techname",&strData); + str+=strData + "\r\n"; + + if(!bQuickWO) + { + str+= "\r\nINVOICE#: "; + rs->FetchField("invoice",&strData); + str+=strData + "\r\n"; + rs->FetchField("wo.notes",&strData); + str+=strData + "\r\n"; + } + + /*rs->FetchField("details",&strData); + str+="\r\nSERVICE DETAILS:\r\n" + strData; + */ + str+="\r\n\r\n(note: click on EDIT button below to show entire workorder)"; + //Display srchview for labour records + sv.m_pstrText=&str; + sv.m_pslHiWords=&strList; + if(m_bUseKeywords) + sv.m_nKeywords=m_nSWords; + else + sv.m_nKeywords=0; + + sv.m_bQuickWO=bQuickWO; + sv.m_strWOID=strWOID; + sv.DoModal(); + } + break; + + + + } + + + + + + + + + + + /* + if(rs!=NULL) + { + delete rs; + rs=NULL; + }*/ + rs->Close(); + + } + + *pResult = FALSE; +} + + + +//************************************************************* +void SRCH::OnBtnsearch() +{ + CString strTerms,str,strWild,q,dispwords; + long lMatches=0; + bool bAllGoodWords=false; + int loopwords,searchtime,pos; + bool bNegative=false; + COleDateTime dtStart,dtEnd; + COleDateTimeSpan dtsDuration; + + m_lResultCount=0; + m_lblResults.ShowWindow(FALSE); + m_lblBad.ShowWindow(FALSE); + m_edBad.ShowWindow(FALSE); + m_lblResults.SetFontBold(TRUE); + //m_lblResults.SetFontUnderline(TRUE); + m_edSearchTerms.GetWindowText(strTerms); + if(strTerms.IsEmpty()) + return; + + if(strTerms=="*" && m_cbClients.GetCurrentRowID()=="0") + { + AfxMessageBox("Select a client to use the * (all records) search\r\n"); + return; + } + strTerms.MakeLower(); + dtStart=COleDateTime::GetCurrentTime(); + + m_strCriteria.Empty(); + m_bPreview=false; + m_bUseKeywords=false; + if(strTerms!="*")//* means don't use keywords just return everything + { m_bPreview=m_ckPreview.GetCheck() ? true : false; + m_bUseKeywords=true; + if(strTerms.Left(4)=="not ") + { + AfxMessageBox("You can't use 'not' as the first word in a search term.\r\n" + "The first part of a search term needs to return matches"); + return; + } + + //CHECK FOR WILDCARDS NOT AT EDGE OF WORD... + pos=0; + pos=strTerms.Find("*",0); + while(pos!=-1) + { + if(pos!=0 && pos!=strTerms.GetLength()-1) + if(strTerms.Mid(pos-1,1)!=" " && strTerms.Mid(pos+1,1)!=" ") + { + AfxMessageBox("The wildcard (*) character can only be used at the start or end of a word"); + return; + } + pos=strTerms.Find("*",pos+1); + } + + /* + if(rs==NULL) + { + rs = new GZRset("Error in EXEC.Index.rs DBUTILS"); + rs->SetConnect(m_pApp->strConnectString); + } + */ + SuckWords(&strTerms); + + + + if(m_nSWords>0) + { + loopwords=m_nSWords; + bAllGoodWords=true; + strNotIn.Empty(); + strStopWords.Empty(); + for(int x=0;xQueryReadOnly(q); + if(!rs->IsEmpty())//it's a stop word + { + strStopWords+=str+" "; + //mark the word as blank if it's invalid + strList.SetAt(strList.FindIndex(x),""); + //Mark(str,true); + bAllGoodWords=false; + + } + else//see if it's in the dictionary + { + //optimize query for performance, if don't need a wildcard search + //dont do it as adds about 10 times to length of time to search + strWild="="; + if(str.Find("%")!=-1) + strWild="Like"; + + q.Format("SELECT Count(srchdict.ID) AS wordcount " + "FROM srchdict " + "WHERE (((srchdict.word) %s '%s'));",strWild,str); + rs->QueryReadOnly(q); + rs->FetchField("wordcount",&lMatches); + if(lMatches==0) + { + //mark search terms word as invalid + strNotIn+=str +" "; + //set the word as blank if it's invalid + strList.SetAt(strList.FindIndex(x),""); + //Mark(str,false); + bAllGoodWords=false; + } + else + { + str.Replace("%","*"); + if(bNegative) + str="not "+ str; + + dispwords+=str + " "; + bNegative=false; + + } + } + + + } + m_edSearchTerms.SetWindowText(dispwords); + if(!bAllGoodWords) + { + CString badwords; + badwords=strStopWords + " " + strNotIn; + badwords.TrimLeft(" "); + badwords.TrimRight(" "); + m_edBad.SetWindowText(badwords); +m_lblBad.ShowWindow(TRUE); + m_edBad.ShowWindow(TRUE); + + /* + if(!strNotIn.IsEmpty()) + Mark(strNotIn,false); + + if(!strStopWords.IsEmpty()) + Mark(strStopWords,true); + */ + + } + } + + + /* + if(rs!=NULL) + { + delete rs; + rs=NULL; + }*/ + rs->Close(); + + + if(DoSearch()) + { + // + FillView(); + } + else + m_rc.DeleteAllItems(); + +}//if sterms="*" +else +{ + bAllGoodWords=true;//There aren't any, so they must be all good! + if(DoNoKeywordSearch()) + FillView(); + else + m_rc.DeleteAllItems(); + +} + +dtEnd=COleDateTime::GetCurrentTime(); +dtsDuration=dtEnd-dtStart; +searchtime=(int)dtsDuration.GetTotalSeconds(); +if(m_lResultCount>0) +{ + m_lblResults.SetTextColor(RGB(0,0,255)); + str.Format("%u matches found in %i seconds",m_lResultCount,searchtime); + m_lblResults.SetWindowText(str); + +} +else +{ + m_lblResults.SetTextColor(RGB(255,0,0)); + if(!bAllGoodWords) + m_lblResults.SetWindowText("No matches - hit enter to search with revised search words"); + else + m_lblResults.SetWindowText("No matches found"); +} +m_lblResults.ShowWindow(TRUE); + +} + +//suck the words out of the search terms +//using same algorithm as was used to make the +//dictionary, ensuring matches to badly formed terms +//with punctuation marks etc. +bool SRCH::SuckWords(CString* pTerms) +{ + CString str,strText,strWord,lchar,q; + long lPos; + m_nSWords=0; + int nLength; + + bool firstword=true; + bool bNot=false;//indicates it's a "not" exclusive word + CStringList sl; + strList.RemoveAll(); + //make sure there is something to parse + nLength=pTerms->GetLength(); + if (nLength > 1) + { + strText.MakeLower(); //make all lower case + strWord.Empty(); + + //loop through all characters in strText + for(lPos=0;lPos < nLength+1;lPos++) + { + lchar=pTerms->Mid(lPos,1); + //is a regular character + if ( (lchar >= "a" && lchar <= "z") || (lchar >="0" && lchar <= "9") || (lchar=="*") || (lchar=="?")) + strWord=strWord+lchar; + else//is a non-regular text character + { + + + if(strWord.GetLength() > 0 ) + { + //is it an exclusion word? + if(strWord=="not") + bNot=true; + else + { + //ANSI SQL conformity + strWord.Replace("*","%"); + //UPDATED:not supported - strWord.Replace("?","_"); + if(bNot) + strWord="-"+strWord; + + if(firstword) + strList.AddHead(strWord); + else + strList.AddTail(strWord); + m_nSWords++; + firstword=false; + bNot=false; + } + } + strWord.Empty(); + }//end of else for a non regular character + }//lPos loop + + + //have to add the very last strWord in manually, this may not really be necessary + //but does not hurt as all duplicates are purged anyway later on in the process + if(strWord.GetLength() > 0) + { + //ANSI SQL conformity + strWord.Replace("*","%"); + //NOT SUPPORTED:strWord.Replace("?","_"); + strList.AddTail(strWord); + m_nSWords++; + } + }//nLength if to make sure is longer than null + + return true; + +} + + +//***************************///////////************* +void SRCH::OnInitialUpdate() +{ + #ifdef _WTF_ + AfxMessageBox("top of: SRCH::OnInitialUpdate()"); + #endif + + + CFormView::OnInitialUpdate(); + CString strIndex,strData; + long lData; + m_ckPreview.SetCheck(TRUE); + /* + if(rs==NULL) + { + rs = new GZRset("Error in rs.SRCH"); + rs->SetConnect(m_pApp->strConnectString); + } + */ + #ifdef _WTF_ + AfxMessageBox("Fill client list: SRCH::OnInitialUpdate()"); + #endif + + m_cbClients.Clear(); + + m_cbClients.AddRow(" < Any Client > ","0"); + + rs->QueryReadOnly("SELECT clients.id, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS name " + "FROM clients ORDER BY IIf(IsNull([company]),[last] & \", \" & [first],[company]);"); + + + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbClients.AddRow(strData,strIndex); + }while(rs->MoveForward()); + } + + #ifdef _WTF_ + AfxMessageBox("Done filling client list: SRCH::OnInitialUpdate()"); + #endif + + m_cbClients.Select(0); + //============================================ + + + m_cbDate.SetCurSel(0); + + + + + + + #ifdef _WTF_ + AfxMessageBox("Create report control: SRCH::OnInitialUpdate()"); + #endif + + //REPORT CONTROL + m_ilReport.Create(IDB_BM2, 16, 1, RGB(255,0,255)); + m_rc.SetImageList(&m_ilReport); + + //ShowWindow(SW_MAXIMIZE); + + m_rc.InsertColor(0, 0x00C0D8C0); + m_rc.InsertColor(1, ::GetSysColor(COLOR_GRAYTEXT)); + m_rc.InsertColor(2, 0x00D0C0C0); + m_rc.InsertColor(3, 0x00804000); + + + RVCOLUMN rvc; + + rvc.nFormat = RVCF_TEXT;// | RVCF_EX_FIXEDWIDTH; + + rvc.lpszText = "Relevance:"; + rvc.iWidth = 75; + m_rc.DefineColumn(0, &rvc); + + rvc.lpszText = _T("Source"); + rvc.iWidth = 131; + m_rc.DefineColumn(1, &rvc); + + rvc.lpszText = "Date"; + rvc.iWidth = 105; + m_rc.DefineColumn(2, &rvc); + + rvc.lpszText = "Client"; + rvc.iWidth = 450; + m_rc.DefineColumn(3, &rvc); + + rvc.lpszText = "id"; + rvc.iWidth = 0; + m_rc.DefineColumn(4, &rvc); + + rvc.lpszText = "table"; + m_rc.DefineColumn(5, &rvc); + + + #ifdef _WTF_ + AfxMessageBox("About to activate columns: SRCH::OnInitialUpdate()"); + #endif + m_rc.ActivateColumn(0, 0); + m_rc.ActivateColumn(1, 1); + m_rc.ActivateColumn(2, 2); + m_rc.ActivateColumn(3, 3); + m_rc.ActivateColumn(4, 4); + m_rc.ActivateColumn(5, 5); + + + + #ifdef _WTF_ + AfxMessageBox("About to modify style: SRCH::OnInitialUpdate()"); + #endif + m_rc.ModifyStyle(0, RVS_SINGLESELECT); + //m_rc.ModifyStyle(0, RVS_SHOWCOLORALTERNATE); + + + //turn off the grids + m_rc.ModifyStyle(RVS_SHOWVGRID, 0); + m_rc.ModifyStyle(RVS_SHOWHGRID, 0); + + m_edSearchTerms.SetFocus(); + + #ifdef _WTF_ + AfxMessageBox("Setting column sorts: SRCH::OnInitialUpdate()"); + #endif + + for(int xx=0;xxSetConnect(m_pApp->strConnectString); + } + */ + rs->Query("SELECT * FROM defaults;"); + q.Format("SELECT srch.* FROM srch WHERE (((srch.userid)=%u)) %s;",m_pApp->m_lusrID,m_strOrderBy); + rs->Query(q); + m_rc.DeleteAllItems(); + slExcerpts.RemoveAll(); + + if(rs->IsEmpty()) + { + /* + if(rs!=NULL) + { + delete rs; + rs=NULL; + }*/ + rs->Close(); + return; + } + // rs->MoveFirst(); + do + { + rs->FetchField("excerpt",&strData); + if(bFirst) + { + slExcerpts.AddHead(strData); + bFirst=false; + } + else + slExcerpts.AddTail(strData); + + rs->FetchField("rank",&lData); + strData.Format("%u",lData); + //RANK + RVITEM rvi; + rvi.iItem = x; + rvi.iSubItem = 0; + rvi.nMask = RVIM_TEXT|RVIM_PREVIEW|RVIM_STATE|RVIM_LPARAM;; + if(m_bPreview) + rvi.nPreview = 17; + else + rvi.nPreview = 0; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.InsertItem(&rvi); + + + //SOURCE + rs->FetchField("tabletype",&ucData); + switch (ucData) + { + case 0: + strData="Problems"; + break; + case 1: + strData="Labour"; + break; + case 2: + strData="Subrepairs"; + break; + case 3: + strData="Rentals / Loaners"; + break; + case 4: + strData="Clients"; + break; + case 5: + strData="Client notebook"; + break; + case 6: + strData="Units"; + break; + case 7://added may 10th, 2001 + strData="Workorder header"; + break; + + } + + rvi.iSubItem = 1; + rvi.nMask = RVIM_TEXT; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //Date + rs->FetchField("date",&dtData); + strData=dtData.Format(VAR_DATEVALUEONLY); + rvi.iSubItem = 2; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //CLIENT + rs->FetchField("client",&strData); + strData.Replace("&","&&"); + rvi.iSubItem = 3; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //TABLEID + rs->FetchField("tableid",&lData); + strData.Format("%u",lData); + rvi.iSubItem = 4; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + //TABLETYPE + rs->FetchField("tabletype",&ucData); + strData.Format("%i",(int)ucData); + rvi.iSubItem = 5; + rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + + + + x++; + + }while(rs->MoveForward()); + /* + if(rs!=NULL) + { + delete rs; + rs=NULL; + }*/ + rs->Close(); + m_lResultCount=x; +} + + +/* + +//mark a word as invalid in the richedit +//control. bStopWord means cross it out +//as it's a stop word, otherwise just underline it +//as not in dictionary. +void SRCH::Mark(CString strText,bool bStopWord) +{ + FINDTEXTEX ft; + CHARFORMAT cf; + + strText.TrimLeft(" "); + strText.TrimRight(" "); + m_lblBad.ShowWindow(TRUE); + m_redBadWords.ShowWindow(TRUE); + + ft.chrg.cpMin = 0; + ft.chrg.cpMax = -1; + ft.lpstrText = (LPSTR) strText.GetBuffer(0); + long n = m_redBadWords.FindText(FR_MATCHCASE|FR_WHOLEWORD, &ft); + if (n != -1) + m_redBadWords.SetSel(ft.chrgText); + else + return; + //red stopword, blue not in dictionary word + //had to set bold, will not change + //color if some effect is not also applied + cf.dwMask = CFM_COLOR | CFM_BOLD; + if(bStopWord) + { + cf.crTextColor=RGB(255,0,0); + cf.dwEffects = CFE_BOLD; + } + else + { + cf.crTextColor=RGB(0,0,255); + cf.dwEffects = CFE_BOLD; + } + m_redBadWords.SetSelectionCharFormat(cf); + + m_redBadWords.SetSel(0,0); + +} +*/ +void SRCH::OnCloseupCbdate() +{ + int x=0; + x=m_cbDate.GetCurSel(); + m_dtDate.ShowWindow(FALSE); + m_dtDate2.ShowWindow(FALSE); + m_lblBetween.ShowWindow(FALSE); + m_lblAnd.ShowWindow(FALSE); + + if(x==2 || x==3) + m_dtDate.ShowWindow(TRUE); + + if(x==1) + { + m_dtDate.ShowWindow(TRUE); + m_dtDate2.ShowWindow(TRUE); + m_lblBetween.ShowWindow(TRUE); + m_lblAnd.ShowWindow(TRUE); + } + + + +} + +void SRCH::OnRvnItemDrawPreview(NMHDR* pNMHDR, LRESULT* pResult) +{ + + CString strText; + LPNMRVDRAWPREVIEW lpnmrvdp = (LPNMRVDRAWPREVIEW)pNMHDR; + + strText=slExcerpts.GetAt(slExcerpts.FindIndex(lpnmrvdp->iItem)); + + CReportCtrl& rc = m_rc; + + CDC dc; + dc.Attach(lpnmrvdp->hDC); + if(lpnmrvdp->nState&RVIS_SELECTED) + dc.SetTextColor(::GetFocus()==rc.m_hWnd ? GetSysColor(COLOR_HIGHLIGHTTEXT):GetSysColor(COLOR_HIGHLIGHT)); + else + dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHT)); + + lpnmrvdp->rect.left += 40; + lpnmrvdp->rect.top += 2; + lpnmrvdp->rect.bottom -= 2; + dc.DrawText(strText, &lpnmrvdp->rect, DT_LEFT|DT_END_ELLIPSIS|DT_WORDBREAK|DT_NOPREFIX|DT_EXPANDTABS); + + dc.Detach(); + + + *pResult = FALSE; + + +} + + + + + +//>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<< +//***************************************************** +//Do the actual search +//using rs connection 09/10/2001 +bool SRCH::DoSearch() +{ + CString q,str,strWild; + + + long lRank,lTableID; + + long debugcounter=0; + CString strKeep; + COleDateTime dtData; + CString strClient; + bool bNoMatch=false; + bool bFirst=true; + CWaitCursor wait; + BuildCriteria(); + /* + if(rs==NULL) + { + rs = new GZRset("Error in Search.rs.DoSearch"); + rs->SetConnect(m_pApp->strConnectString); + } + if(rs2==NULL) + { + rs2 = new GZRset("Error in Search.rs2.DoSearch"); + rs2->SetConnect(m_pApp->strConnectString); + } + */ + + + + //Empty previous srch results + q.Format("DELETE srch.*, srch.userid FROM srch " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + + rs2->Ex(q); + + + //each word has already been cleared + //cycle through each word, add to table srch + //add items and remove from table srch remove items + //until list is exhausted or srch is empty + + //BUILD SRCH LIST FROM KEYWORDS + for(int x=0;x1) + { + if(bFirst==true) + { //MAKE THE TABLE FROM THE FIRST WORD + + //optimize query for performance, if don't need a wildcard search + //dont do it as adds about 10 times to length of time to search + strWild="="; + if(str.Find("%")!=-1) + strWild="Like"; + + + + //First word used to build initial list + q.Format("INSERT INTO srch ( tabletype, [tableid], keep, userid ) " + "SELECT DISTINCT [srchkey].[tabletype], [srchkey].[tableid], False AS keeper, %u AS [user] " + "FROM srchdict RIGHT JOIN srchkey ON [srchdict].[ID]=[srchkey].[wordid] " + "WHERE ((([srchdict].[word]) %s \"%s\") %s );",m_pApp->m_lusrID,strWild,strList.GetAt(strList.FindIndex(0)),m_strCriteria); + + //m_pApp->ShowStuff(q); + /* + INSERT INTO srch ( tabletype, [tableid], keep, userid ) + SELECT DISTINCT srchkey.tabletype, srchkey.tableid, False AS keeper, 1 AS [user] + FROM srchdict RIGHT JOIN srchkey ON srchdict.ID = srchkey.wordid + WHERE (((srchdict.word) Like "print*") AND ((srchkey.client)=268) AND ((DatePart("m",[srchkey].[date]))>=DatePart("m",Date())-5) AND ((DatePart("yyyy",[srchkey].[date]))=DatePart("yyyy",Date()))); + */ + rs2->Ex(q); + bFirst=false; + } + else + { + if(str.Left(1)=="-") + { + strKeep="False"; + //if processing a discard, flag all as true + q.Format("UPDATE srch SET srch.keep = True " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + rs2->Ex(q); + } + else + { + strKeep="True"; + //if processing a keeper, flag all as false + q.Format("UPDATE srch SET srch.keep = False " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + rs2->Ex(q); + + } + str.Remove('-'); + + //optimize query for performance, if don't need a wildcard search + //dont do it as adds about 10 times to length of time to search + strWild="="; + if(str.Find("%")!=-1) + strWild="Like"; + //flag keepers + q.Format("UPDATE srch INNER JOIN (srchdict RIGHT JOIN " + "srchkey ON srchdict.ID = srchkey.wordid) ON " + "(srch.tableid = srchkey.tableid) AND " + "(srch.tabletype = srchkey.tabletype) " + "SET srch.keep = %s " + "WHERE (((srchdict.word) %s \"%s\") " + "AND ((srch.userid)=%u));",strKeep,strWild,str,m_pApp->m_lusrID); + rs2->Ex(q); + //Remove culls + q.Format("DELETE srch.*, srch.keep, srch.userid " + "FROM srch " + "WHERE (((srch.keep)=False) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + rs2->Ex(q); + + + //BUGBUG: POSSIBLE PROBLEM AREA REQUIRING FLUSHING + + + + }//bFirst IF statement + //check to see if were still in business + q.Format("SELECT srch.userid FROM srch " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + { + bNoMatch=true; + break; + } + + + + }//if it's a deleted word + }//loop through all the words + + + + + + + //------------------------------------------- + if(!bNoMatch) + { + //Suck out excerpts and rank each item: + //PROBS + q.Format("SELECT srch.tableid,[probs].[brief], [probs].[notes], probs.created AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " + "FROM srch LEFT JOIN ((probs LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id) ON srch.tableid = probs.id " + "WHERE (((srch.tabletype)=0) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + //m_pApp->ShowStuff(q); + rs->QueryReadOnly(q); + + if(!rs->IsEmpty()) + { + do{ + rs->FetchAllTextFieldsAsOneString(&str); + + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=0) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + + + }while(rs->MoveForward()); + + + + } + + //AfxMessageBox("probs completed"); + //LABOUR + q.Format("SELECT srch.tableid,labor.details, labor.stop AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " + "FROM (((srch LEFT JOIN labor ON srch.tableid = labor.id) LEFT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id " + "WHERE (((srch.tabletype)=1) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + //Show(q); + rs->QueryReadOnly(q); + //AfxMessageBox("lab A"); + //rs->MoveFirst(); + /* + int xtest=0; + CString xstr; + */ + if(!rs->IsEmpty()) + { + do{ + + rs->FetchAllTextFieldsAsOneString(&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + strClient.Replace("&"," and "); + + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=1) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + }while(rs->MoveForward()); + + + } + + //AfxMessageBox("subrepaircompleted"); + //SUBREPAIR + q.Format("SELECT srch.tableid,subrepair.notes , subrepair.created AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " + "FROM (srch LEFT JOIN subrepair ON srch.tableid = subrepair.id) LEFT JOIN ((probs LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id) ON subrepair.link = probs.id " + "WHERE (((srch.tabletype)=2) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchAllTextFieldsAsOneString(&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=2) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + + + }while(rs->MoveForward()); + + + + } + //AfxMessageBox("rentalscompleted"); + //RENTALS + q.Format("SELECT srch.tableid,[rentals].[notes], [rentals].[loanedto], [rentals].[description], rentals.dateout AS ddate, [loanedto] & \" \" & IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient, clients.id AS dclientid " + "FROM (srch INNER JOIN rentals ON srch.tableid = rentals.id) LEFT JOIN clients ON rentals.clientlink = clients.id " + "WHERE (((srch.tabletype)=3) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchAllTextFieldsAsOneString(&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\",srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=3) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + + + }while(rs->MoveForward()); + + + + } + + //AfxMessageBox("clients completed"); + //CLIENTS + q.Format( + "SELECT srch.tableid, clients.id AS dclientid,[generalnotes] , " + "[technotes] , [alert] , " + "[first] , [last] , [company] " + " , [mailaddress] , " + "[streetaddress] , [city] , " + "[stateprov] , [postal] , " + "[country] , [bizphone] , " + "[fax] , [email] , [acctnumber] , [phone2] , [phone3], " + "clients.created AS ddate, IIf(IsNull([clients]![company])," + "[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient " + "FROM srch LEFT JOIN clients ON srch.tableid = clients.id " + "WHERE (((srch.tabletype)=4) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + + + // m_pApp->ShowStuff(q); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchAllTextFieldsAsOneString(&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=4) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + + + }while(rs->MoveForward()); + + + + } + + + //CONTACTS + q.Format("SELECT srch.tableid, contacts.clientlink AS dclientid, contacts.notes , contacts.date AS ddate, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient " + "FROM (srch LEFT JOIN contacts ON srch.tableid = contacts.id) LEFT JOIN clients ON contacts.clientlink = clients.id " + "WHERE (((srch.tabletype)=5) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchAllTextFieldsAsOneString(&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=5) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + + + }while(rs->MoveForward()); + + + + } + + } + + + + //UNITS + q.Format("SELECT srch.tableid, units.client AS dclientid, " + "[units].[sn], [units].[id1]," + "[units].[id2],[units].[id3], " + "[units].[receipt], " + "[units].[notes], " + "[units].[description], IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient, IIf(IsNull([units].[purchasedate]),IIf(IsNull([units].[created]),IIf(IsNull([units].[modified]),#1/1/2000#,[units].[modified]),[units].[created]),[units].[purchasedate]) AS ddate " + "FROM (srch LEFT JOIN units ON srch.tableid = units.id) LEFT JOIN clients ON units.client = clients.id " + "WHERE (((srch.tabletype)=6) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchAllTextFieldsAsOneString(&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=6) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + + + }while(rs->MoveForward()); + + + + } + + + + //WORKORDER HEADER TABLE 7 added May 9th, 2001 + q.Format("SELECT srch.tableid, [wo].[notes] , [wo].[invoice] , [wo].[clientrefnum] , " + "[wo].[clientcontact], [wo].[ourref] , wo.created AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " +"FROM srch LEFT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON srch.tableid = wo.id " +"WHERE (((srch.tabletype)=7) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + +/* q.Format("SELECT srch.tableid, units.client AS dclientid, \"SN:\" & [units].[sn] & \" \" & \"ID1:\" & [units].[id1] & \" ID2:\" & [units].[id2] & \" ID3:\" & [units].[id3] & \" Receipt#:\" & [units].[receipt] & \" NOTES:\" & [units].[notes] & \" DESCRIPTION:\" & [units].[description] AS [text], IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient, IIf(IsNull([units].[purchasedate]),IIf(IsNull([units].[created]),IIf(IsNull([units].[modified]),#1/1/2000#,[units].[modified]),[units].[created]),[units].[purchasedate]) AS ddate " + "FROM (srch LEFT JOIN units ON srch.tableid = units.id) LEFT JOIN clients ON units.client = clients.id " + "WHERE (((srch.tabletype)=6) AND ((srch.userid)=%u));",m_pApp->m_lusrID); +*/ + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchAllTextFieldsAsOneString(&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=7) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + rs2->Ex(q); + + + + }while(rs->MoveForward()); + + + + } + + + + //AfxMessageBox("part2completed"); + //--------------------------------------------------------------------- + /* + if(rs!=NULL) + { + delete rs; + rs=NULL; + } + if(rs2!=NULL) + { + delete rs2; + rs2=NULL; + } + */ + rs->Close(); + rs2->Close(); + + //pConnection->Close(); + + //StopWatch("DoSearch part II",false); + if(bNoMatch) + return false; + return true; +} + + + + + + + +/* + +//>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<< +//***************************************************** +//Do the actual search +bool SRCH::DoSearch() +{ + CString q,str,strWild; + + + long lRank,lTableID; + + long debugcounter=0; + CString strKeep; + COleDateTime dtData; + CString strClient; + bool bNoMatch=false; + bool bFirst=true; + CWaitCursor wait; + BuildCriteria(); + + + //connection stuff here to avoid overhead + //of using one in gzrset + //create a pointer to a connection + _bstr_t strSQL; + _ConnectionPtr pConnection = NULL; + + //instantiate it: + pConnection.CreateInstance(__uuidof(Connection)); + + //get connect string + _bstr_t strCnn(m_pApp->strConnectString); + + //open the connection + pConnection->Open (strCnn, "", "", adConnectUnspecified); + + + //Empty previous srch results + q.Format("DELETE srch.*, srch.userid FROM srch " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->BeginTrans(); + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + pConnection->CommitTrans(); + + + //START OF SLOW LOOP + //StopWatch("",true); + + + + + + //each word has already been cleared + //cycle through each word, add to table srch + //add items and remove from table srch remove items + //until list is exhausted or srch is empty + + //BUILD SRCH LIST FROM KEYWORDS + for(int x=0;x1) + { + if(bFirst==true) + { //MAKE THE TABLE FROM THE FIRST WORD + + //optimize query for performance, if don't need a wildcard search + //dont do it as adds about 10 times to length of time to search + strWild="="; + if(str.Find("%")!=-1) + strWild="Like"; + + + + //First word used to build initial list + q.Format("INSERT INTO srch ( tabletype, [tableid], keep, userid ) " + "SELECT DISTINCT [srchkey].[tabletype], [srchkey].[tableid], False AS keeper, %u AS [user] " + "FROM srchdict RIGHT JOIN srchkey ON [srchdict].[ID]=[srchkey].[wordid] " + "WHERE ((([srchdict].[word]) %s \"%s\") %s );",m_pApp->m_lusrID,strWild,strList.GetAt(strList.FindIndex(0)),m_strCriteria); + + //m_pApp->ShowStuff(q); + + //convert the string to a bstr + strSQL=q; + //m_edSearchTerms.SetWindowText(q); + //execute the query + pConnection->BeginTrans(); + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + pConnection->CommitTrans(); + bFirst=false; + } + else + { + if(str.Left(1)=="-") + { + strKeep="False"; + //if processing a discard, flag all as true + q.Format("UPDATE srch SET srch.keep = True " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->BeginTrans(); + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + pConnection->CommitTrans(); + } + else + { + strKeep="True"; + //if processing a keeper, flag all as false + q.Format("UPDATE srch SET srch.keep = False " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->BeginTrans(); + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + pConnection->CommitTrans(); + + } + str.Remove('-'); + + //optimize query for performance, if don't need a wildcard search + //dont do it as adds about 10 times to length of time to search + strWild="="; + if(str.Find("%")!=-1) + strWild="Like"; + //flag keepers + q.Format("UPDATE srch INNER JOIN (srchdict RIGHT JOIN " + "srchkey ON srchdict.ID = srchkey.wordid) ON " + "(srch.tableid = srchkey.tableid) AND " + "(srch.tabletype = srchkey.tabletype) " + "SET srch.keep = %s " + "WHERE (((srchdict.word) %s \"%s\") " + "AND ((srch.userid)=%u));",strKeep,strWild,str,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->BeginTrans(); + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + pConnection->CommitTrans(); + + //Remove culls + q.Format("DELETE srch.*, srch.keep, srch.userid " + "FROM srch " + "WHERE (((srch.keep)=False) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->BeginTrans(); + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + pConnection->CommitTrans(); + //removed dec 9th obsolete call? + //rs->Flush(pConnection); + + + + + }//bFirst IF statement + //check to see if were still in business + q.Format("SELECT srch.userid FROM srch " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + { + bNoMatch=true; + break; + } + + + + }//if it's a deleted word + }//loop through all the words + + //StopWatch("DoSearch Part I",false); + //**************** END OF SLOW LOOP ************ + + //AfxMessageBox("part1completed"); + + //Delay(5); + + + + + + //------------------------------------------- + if(!bNoMatch) + { + //Suck out excerpts and rank each item: + //PROBS + q.Format("SELECT srch.tableid,[probs].[brief] & \" \" & [probs].[notes] AS [text], probs.created AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " + "FROM srch LEFT JOIN ((probs LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id) ON srch.tableid = probs.id " + "WHERE (((srch.tabletype)=0) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + //m_pApp->ShowStuff(q); + rs->QueryReadOnly(q); + + if(!rs->IsEmpty()) + { + do{ + rs->FetchField("text",&str); + + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=0) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs->MoveForward()); + + + + } + + //AfxMessageBox("probs completed"); + //LABOUR + q.Format("SELECT srch.tableid,labor.details AS [text], labor.stop AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " + "FROM (((srch LEFT JOIN labor ON srch.tableid = labor.id) LEFT JOIN probs ON labor.link = probs.id) LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id " + "WHERE (((srch.tabletype)=1) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + //Show(q); + rs->QueryReadOnly(q); + //AfxMessageBox("lab A"); + //rs->MoveFirst(); + + if(!rs->IsEmpty()) + { + do{ + + rs->FetchField("text",&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + strClient.Replace("&"," and "); + + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=1) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + }while(rs->MoveForward()); + + + } + + //AfxMessageBox("subrepaircompleted"); + //SUBREPAIR + q.Format("SELECT srch.tableid,subrepair.notes AS [text], subrepair.created AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " + "FROM (srch LEFT JOIN subrepair ON srch.tableid = subrepair.id) LEFT JOIN ((probs LEFT JOIN wo ON probs.wolink = wo.id) LEFT JOIN clients ON wo.client = clients.id) ON subrepair.link = probs.id " + "WHERE (((srch.tabletype)=2) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchField("text",&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=2) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs->MoveForward()); + + + + } + //AfxMessageBox("rentalscompleted"); + //RENTALS + q.Format("SELECT srch.tableid,[rentals].[notes] & \" \" & [rentals].[loanedto] & \" \" & [rentals].[description] AS [text], rentals.dateout AS ddate, [loanedto] & \" \" & IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient, clients.id AS dclientid " + "FROM (srch INNER JOIN rentals ON srch.tableid = rentals.id) LEFT JOIN clients ON rentals.clientlink = clients.id " + "WHERE (((srch.tabletype)=3) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchField("text",&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\",srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=3) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs->MoveForward()); + + + + } + + //AfxMessageBox("clients completed"); + //CLIENTS + q.Format("SELECT srch.tableid, clients.id AS dclientid,[generalnotes] & \" \" & [technotes] & \" \" & [alert] & \" \" & [first] & \" \" & [last] & \" \" & [company] & \" \" & [mailaddress] & \" \" & [streetaddress] & \" \" & [city] & \" \" & [stateprov] & \" \" & [postal] & \" \" & [country] & \" \" & [bizphone] & \" \" & [fax] & \" \" & [email] & \" \" & [acctnumber] AS [text], clients.created AS ddate, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient " + "FROM srch LEFT JOIN clients ON srch.tableid = clients.id " + "WHERE (((srch.tabletype)=4) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + // m_pApp->ShowStuff(q); + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchField("text",&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=4) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs->MoveForward()); + + + + } + + + //CONTACTS + q.Format("SELECT srch.tableid, contacts.clientlink AS dclientid, contacts.notes AS [text], contacts.date AS ddate, IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient " + "FROM (srch LEFT JOIN contacts ON srch.tableid = contacts.id) LEFT JOIN clients ON contacts.clientlink = clients.id " + "WHERE (((srch.tabletype)=5) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchField("text",&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=5) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs->MoveForward()); + + + + } + + } + + + + //UNITS + q.Format("SELECT srch.tableid, units.client AS dclientid, \"SN:\" & [units].[sn] & \" \" & \"ID1:\" & [units].[id1] & \" ID2:\" & [units].[id2] & \" ID3:\" & [units].[id3] & \" Receipt#:\" & [units].[receipt] & \" NOTES:\" & [units].[notes] & \" DESCRIPTION:\" & [units].[description] AS [text], IIf(IsNull([clients]![company]),[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS dclient, IIf(IsNull([units].[purchasedate]),IIf(IsNull([units].[created]),IIf(IsNull([units].[modified]),#1/1/2000#,[units].[modified]),[units].[created]),[units].[purchasedate]) AS ddate " + "FROM (srch LEFT JOIN units ON srch.tableid = units.id) LEFT JOIN clients ON units.client = clients.id " + "WHERE (((srch.tabletype)=6) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchField("text",&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=6) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs->MoveForward()); + + + + } + + + + //WORKORDER HEADER TABLE 7 added May 9th, 2001 + q.Format("SELECT srch.tableid, [wo].[notes] & \" \" & [wo].[invoice] & \" \" & [wo].[clientrefnum] & \" \" & " + "[wo].[clientcontact] & \" \" & [wo].[ourref] AS [text], wo.created AS ddate, clients.id AS dclientid, IIf(IsNull([company]),[last] & \", \" & [first],[company]) AS dclient " +"FROM srch LEFT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON srch.tableid = wo.id " +"WHERE (((srch.tabletype)=7) AND ((srch.userid)=%u));",m_pApp->m_lusrID); + + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do{ + rs->FetchField("text",&str); + rs->FetchField("tableid",&lTableID); + rs->FetchField("dclient",&strClient); + rs->FetchField("ddate",&dtData); + + ExtractAndRank(&str,&lRank); + + q.Format("UPDATE srch SET srch.date = #%s#, srch.client= \"%s\", srch.excerpt = \"%s\", srch.rank = %u " + "WHERE (((srch.tabletype)=7) AND ((srch.tableid)=%u) AND ((srch.userid)=%u));" + ,dtData.Format(_T("%m/%d/%Y")),strClient,str,lRank,lTableID,m_pApp->m_lusrID); + //convert the string to a bstr + strSQL=q; + //execute the query + pConnection->Execute(strSQL, NULL, adExecuteNoRecords); + + + + + }while(rs->MoveForward()); + + + + } + + + + //AfxMessageBox("part2completed"); + //--------------------------------------------------------------------- + + rs->Close(); + rs2->Close(); + + pConnection->Close(); + + //StopWatch("DoSearch part II",false); + if(bNoMatch) + return false; + return true; +} +*/ + + + + + + + + + + + + +//**************************************************** +//take the passed in raw text, return an excerpt of +//25 words or less through the same string +//and return a ranking from 1 to 100 for accuracy +//currently only wildcard accepted is *(%) which +//for this function is simply stripped out since it can +//is irrelevant for matching left or right side strings +//NOTE:Wildcard * not at either end is invalid and not +//supported here, will mis-match +bool SRCH::ExtractAndRank(CString *excerpt, long *rank) +{ + CString str,strwindow,str2,leftpad,rightpad,tempexcerpt; + int x,curpos,counter,lowcount,lowword,leftwindow,rightwindow; + int rawlength,wordlength; + int prox,bestprox,bestleftwindow,bestrightwindow;//number of other words within proximity window + int curpos2; + bool anymatches=false; + + //v 1.9.4.6 added 09-may-2005 + //because being used before initialized + bestrightwindow=0; + bestleftwindow=0; + + lowcount=9999;//seed with a high number + lowword=0; + bestprox=0; + rawlength=excerpt->GetLength(); + tempexcerpt=*excerpt; + tempexcerpt.MakeLower(); + + //loop through all the search words + //finding the word with the least occurences + for(x=0;x 1 && str.Left(1)!="-") + { + counter=0; + curpos=tempexcerpt.Find(str,0); + while (curpos!=-1) + { anymatches=true; + counter++; + curpos=tempexcerpt.Find(str,curpos+1); + } + + } + if(counter< lowcount && counter > 0) + { + lowcount=counter; + lowword=x; + } + if(counter==1) + break; + + } + + + + + //scan text looking for window with most keywords in it. + + str=strList.GetAt(strList.FindIndex(lowword)); + + //STrip wildcards + str.Remove('%'); + str.Remove('_'); + wordlength=str.GetLength(); + curpos=tempexcerpt.Find(str,0); + //counter=0; + while (curpos!=-1) + { + //counter++; + + //LEFTWINDOW + if(curpos (curpos+wordlength+WORDWINDOW)) + rightwindow=(curpos+wordlength+WORDWINDOW); + else + rightwindow=rawlength; + //fill strwindow with all the text within + //the window, hopefully centered on the keyword + strwindow=tempexcerpt.Mid(leftwindow,(rightwindow-leftwindow)); + + //how many of the other keywords appear within that window + //Loop through all the keywords, if they appear in the window + //then add one to the count, eventually will result in a % + prox=0; + for(x=0;x 1 && str.Left(1)!="-") + { + curpos2=tempexcerpt.Find(str2,leftwindow); + while(curpos2!=-1 && curpos2< rightwindow) + { + prox++;//count of how many of each of the keywords appear in window + curpos2=tempexcerpt.Find(str2,curpos2+1); + } + } + } + + + if(prox > bestprox) + { + bestprox=prox; + bestleftwindow=leftwindow; + bestrightwindow=rightwindow; + } + + + curpos=tempexcerpt.Find(str,curpos+1); + + } + + *rank=bestprox;//number of keywords within window + + *excerpt=excerpt->Mid(bestleftwindow,(bestrightwindow-bestleftwindow)); + + if(bestleftwindow==0) + leftpad.Empty(); + else + leftpad="..."; + + if(bestrightwindow==rawlength) + rightpad.Empty(); + else + rightpad="..."; + *excerpt=leftpad+*excerpt+rightpad; + + + + + excerpt->Replace("'",""); + excerpt->Replace("\"",""); + excerpt->Replace("&"," AND "); + excerpt->Replace("\r"," "); + excerpt->Replace("\n",""); + + + + if(anymatches==false)//problem + { + //AfxMessageBox("There is a problem with the search index tables. Do a full re-index before attempting to search again."); + excerpt->Format("< Search item no longer in this record - you should reindex soon >"); + return false; + } + return true; +} + + + + +void SRCH::StopWatch(CString msg, bool bStart) +{ + CString str; + int searchtime; + if(bStart) + swStart=COleDateTime::GetCurrentTime(); + else + { + swEnd=COleDateTime::GetCurrentTime(); + swSpan=swEnd-swStart; + searchtime=(int)swSpan.GetTotalSeconds(); + str.Format("%s - %i seconds",msg,searchtime); + AfxMessageBox(str); + + } +} + +void SRCH::Delay(int nSeconds) +{ + COleDateTime dtStart,dtEnd; + COleDateTimeSpan dtSpan; + dtStart=COleDateTime::GetCurrentTime(); + do { + + dtEnd=COleDateTime::GetCurrentTime(); + dtSpan=dtEnd-dtStart; + }while(nSeconds > (int)dtSpan.GetTotalSeconds()); + +} + + + +//BUILD CRITERIA FROM CLIENT AND DATE SELECTIONS +void SRCH::BuildCriteria() +{ + + int nDateCrit; + CString strClientCrit,strDateCrit,strStartDate,strEndDate,client; + COleDateTime dtStart,dtEnd; + + m_dtDate.GetTime(dtStart); + m_dtDate2.GetTime(dtEnd); + strStartDate=dtStart.Format(_T("%m/%d/%Y")); + strEndDate=dtEnd.Format(_T("%m/%d/%Y")); + + nDateCrit=m_cbDate.GetCurSel(); + + m_strCriteria.Empty(); + + client=m_cbClients.GetCurrentRowID(); + if(client!="0")//theres a client + { + //process client criteria to criteria string + strClientCrit.Format(" AND ((srchkey.client)=%s) ",client); + } + + + + + + if(nDateCrit >0) //0=Anytime + { + switch(nDateCrit) + { + case 1://between... + strDateCrit.Format(" AND ((srchkey.date) Between #%s# And #%s#) ",strStartDate,strEndDate); + break; + case 2: //after... + strDateCrit.Format(" AND ((srchkey.date) > #%s#) ",strStartDate); + break; + case 3: //before... + strDateCrit.Format(" AND ((srchkey.date) < #%s#) ",strStartDate); + break; + case 4:///in the last week + strDateCrit=" AND ((DatePart(\"ww\",[srchkey].[date]))=DatePart(\"ww\",Date())) AND ((DatePart(\"yyyy\",[srchkey].[date]))=DatePart(\"yyyy\",Date())) "; + break; + case 5: //in the last 2 weeks + strDateCrit=" AND ((DatePart(\"ww\",[srchkey].[date]))>=DatePart(\"ww\",Date())-1) AND ((DatePart(\"yyyy\",[srchkey].[date]))=DatePart(\"yyyy\",Date())) "; + break; + case 6://within the last 45 days + strDateCrit=" AND (([srchkey].[date])>= (DateAdd(\"d\",-45, Date()))) "; + break; + case 7://in the last month + strDateCrit=" AND ((DatePart(\"m\",[srchkey].[date]))=DatePart(\"m\",Date())) AND ((DatePart(\"yyyy\",[srchkey].[date]))=DatePart(\"yyyy\",Date())) "; + break; + case 8://in the last 3 months + strDateCrit=" AND ((DatePart(\"m\",[srchkey].[date]))>=DatePart(\"m\",Date())-2) AND ((DatePart(\"yyyy\",[srchkey].[date]))=DatePart(\"yyyy\",Date())) "; + break; + case 9: //in the last 6 months + strDateCrit=" AND ((DatePart(\"m\",[srchkey].[date]))>=DatePart(\"m\",Date())-5) AND ((DatePart(\"yyyy\",[srchkey].[date]))=DatePart(\"yyyy\",Date())) "; + + break; + case 10: //in the last year + strDateCrit=" AND (( DatePart(\"yyyy\",[srchkey].[date]))=DatePart(\"yyyy\",Date() ))"; + break; + case 11://in the last 2 years + strDateCrit=" AND (( DatePart(\"yyyy\",[srchkey].[date]))>=DatePart(\"yyyy\",Date() )-1)"; + break; + } + + + + //pdv->sqlcriteria+=str1; + + } + + m_strCriteria=strClientCrit + strDateCrit; + + +} + + + + +//SEARCH FOR NON_KEYWORD items +bool SRCH::DoNoKeywordSearch() +{ + CString q,strCrit; + BuildCriteria(); + m_strCriteria=m_strCriteria.Right(m_strCriteria.GetLength()-4);//strip off the AND + CWaitCursor wait; + + //hack for no criteria and no keywords + if(!m_strCriteria.IsEmpty()) + strCrit.Format("WHERE ( %s )",m_strCriteria); + else + strCrit.Empty(); + /* + if(rs==NULL) + { + rs = new GZRset("Error in Search.rs.DoNoKeywordSearch"); + rs->SetConnect(m_pApp->strConnectString); + } + */ + //Empty previous srch results + q.Format("DELETE srch.*, srch.userid FROM srch " + "WHERE (((srch.userid)=%u));",m_pApp->m_lusrID); + rs->Ex(q); + + q.Format("INSERT INTO srch ( tabletype, [tableid], userid, [date], client, rank ) " + "SELECT DISTINCT srchkey.tabletype, srchkey.tableid, %u AS [user], srchkey.date, IIf(IsNull([company]),[last] & \", \" & [first],[company]), 100 " + "FROM (srchdict RIGHT JOIN srchkey ON srchdict.ID = srchkey.wordid) INNER JOIN clients ON srchkey.client = clients.id " + "%s;",m_pApp->m_lusrID,strCrit); + + + rs->Ex(q); + rs->Close(); + return true; +} + + + +//Display a text string +void SRCH::Show(CString strTxt) +{ + CTED d; + d.m_strText=strTxt; + d.DoModal(); + +} + + + +//SET ORDER BY CLAUSE DEPENDING ON CLICK HERE +void SRCH::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + int x; + CString str; + CFlatHeaderCtrl* header; + header=m_rc.GetHeaderCtrl(); + + //FIND CLICKED COLUMN + x=COLUMNCOUNT-header->GetHotIndex(); + x--;//because zero based + + bColumnSortAsc[x]=!bColumnSortAsc[x]; + switch(x) + {//DESC + case 0://relevance + m_strOrderBy="ORDER BY srch.rank"; + break; + case 1://source + m_strOrderBy="ORDER BY srch.tabletype"; + break; + + case 2://DATE + m_strOrderBy="ORDER BY srch.date"; + break; + + case 3://client + m_strOrderBy="ORDER BY srch.client"; + break; + } + + if(!bColumnSortAsc[x]) + m_strOrderBy+=" DESC"; + + + header->SetSortColumn(header->GetHotIndex(),bColumnSortAsc[x]); + + *pResult = TRUE;//TRUE means we handled it here thanks anyway + FillView(); +} + +void SRCH::LayoutControls(void) +{ + CRect rectCtl,rectStat; + GetWindowRect(rectStat); + + + int nOffset=rectStat.top; + int nFullRight=rectStat.right; + int nLastBottom,nRight; + int nHeight,nWidth; + float fData; + + + m_rc.GetWindowRect(rectCtl); + + rectCtl.right=rectStat.right-13; + rectCtl.top-=nOffset; + rectCtl.left=13; + rectCtl.bottom=rectStat.bottom-168-nOffset; + m_rc.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + nRight=rectCtl.right; + + + m_lblResults.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom+25; + rectCtl.top=rectCtl.bottom-nHeight; + m_lblResults.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + + + /* +nRight=rectCtl.right; + + + m_btnEditWO.GetWindowRect(rectCtl); + nWidth=rectCtl.Width(); + rectCtl.right=nRight; + rectCtl.left=nRight-nWidth; + rectCtl.top-=nOffset; + rectCtl.bottom-=nOffset; + m_btnEditWO.MoveWindow(rectCtl,TRUE); + */ + m_ckPreview.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + + nWidth=rectCtl.Width(); + rectCtl.right=nRight; + rectCtl.left=nRight-nWidth; + + m_ckPreview.MoveWindow(rectCtl,TRUE); + + + + m_lblKeyWords.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom+17; + rectCtl.top=rectCtl.bottom-nHeight; + m_lblKeyWords.MoveWindow(rectCtl,TRUE); + + nLastBottom=rectCtl.bottom;//because it just changed and the others below need it + + m_lblDateRange.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_lblDateRange.MoveWindow(rectCtl,TRUE); + + + //"BETWEEN" + m_lblBetween.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + nWidth=rectCtl.Width(); + + rectCtl.right=nFullRight*0.74; + rectCtl.left=(nFullRight*0.74)-nWidth; + + m_lblBetween.MoveWindow(rectCtl,TRUE); + + nLastBottom+=24; + m_edSearchTerms.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_edSearchTerms.MoveWindow(rectCtl,TRUE); + + m_cbDate.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_cbDate.MoveWindow(rectCtl,TRUE); + + + //START DATE + m_dtDate.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + nWidth=rectCtl.Width(); + rectCtl.right=nFullRight*0.81; + rectCtl.left=(nFullRight*0.81)-nWidth; + m_dtDate.MoveWindow(rectCtl,TRUE); + + + nLastBottom+=18; + m_lblBad.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_lblBad.MoveWindow(rectCtl,TRUE); + + m_lblClients.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_lblClients.MoveWindow(rectCtl,TRUE); + + + //"AND" + m_lblAnd.GetWindowRect(rectCtl); + +nWidth=rectCtl.Width(); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + rectCtl.right=nFullRight*0.725; + rectCtl.left=(nFullRight*0.725)-nWidth; + m_lblAnd.MoveWindow(rectCtl,TRUE); + + nLastBottom+=24; + + m_edBad.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_edBad.MoveWindow(rectCtl,TRUE); + + m_cbClients.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + fData=(float)rectCtl.right/(float)nFullRight; + nHeight=rectCtl.Height(); + nWidth=rectCtl.Width(); + + rectCtl.right=nFullRight*0.63875; + + + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_cbClients.MoveWindow(rectCtl,TRUE); + + + //END DATE + m_dtDate2.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + nWidth=rectCtl.Width(); +rectCtl.right=nFullRight*0.8075; + rectCtl.left=(nFullRight*0.8075)-nWidth; + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_dtDate2.MoveWindow(rectCtl,TRUE); + + m_btnSearch.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + //fData=(float)rectCtl.right/(float)nFullRight; + nHeight=rectCtl.Height(); + nWidth=rectCtl.Width(); +rectCtl.right=nFullRight*0.90875; + rectCtl.left=(nFullRight*0.90875)-nWidth; + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnSearch.MoveWindow(rectCtl,TRUE); + + + + /* + m_btnRefresh.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnRefresh.MoveWindow(rectCtl,TRUE); + + m_btnClientNotes.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnClientNotes.MoveWindow(rectCtl,TRUE); + + m_btnPrint.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnPrint.MoveWindow(rectCtl,TRUE);*/ +} + + + +void SRCH::OnSize(UINT nType, int cx, int cy) +{ + CFormView::OnSize(nType, cx, cy); + +if(cx>m_nCX)//to cut down on number of times called + { + m_nCX=cx; + if(m_rc.m_hWnd) + { + LayoutControls(); + } + } + +} + +BOOL SRCH::OnHelpInfo(HELPINFO* pHelpInfo) +{ +WinHelp (0x00020000 + IDD_SRCH_FORM,HELP_CONTEXT); + return TRUE; +} + +void SRCH::OnCbnSelchangeCbclients() +{ + // TODO: Add your control notification handler code here +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.h new file mode 100644 index 0000000..f6e908b --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SRCH.h @@ -0,0 +1,130 @@ +#if !defined(AFX_SRCH_H__B3971467_FC37_11D3_964F_00C0F02C4B69__INCLUDED_) +#define AFX_SRCH_H__B3971467_FC37_11D3_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SRCH.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// SRCH form view + +#ifndef __AFXEXT_H__ +#include +#endif +#include "gzrset.h" +#include "gzcombo.h" +#include "ReportCtrl.h" +#include "label.h" +#include "afxwin.h" + + + +class SRCH : public CFormView +{ +public: + void DeActivate(); + void Activate(); + + virtual ~SRCH(); + SRCH(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(SRCH) + CSpApp* m_pApp; + GZRset* rs; + GZRset* rs2; + #define COLUMNCOUNT 6 +// Form Data +public: + //{{AFX_DATA(SRCH) + enum { IDD = IDD_SRCH_FORM }; + CEdit m_edBad; + CEdit m_edSearchTerms; + CStatic m_lblBetween; + CStatic m_lblAnd; + CDateTimeCtrl m_dtDate2; + CLabel m_lblResults; + CStatic m_lblBad; + CButton m_btnSearch; + CgzCombo m_cbClients; + CButton m_ckPreview; + CComboBox m_cbDate; + CDateTimeCtrl m_dtDate; + CReportCtrl m_rc; + //}}AFX_DATA + +// Attributes +public: +CImageList m_ilReport; +CStringList m_lsPreview; +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(SRCH) + public: + virtual void OnInitialUpdate(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +public: + bool SuckWords(CString* pTerms); + CStringList strList; + CStringList slExcerpts; + CString strNotIn; + CString strStopWords; + void Show(CString strTxt); + CString m_strCriteria; + bool DoNoKeywordSearch(); + void BuildCriteria(); + bool m_bUseKeywords; + bool m_bPreview; + void Delay(int nSeconds); + //============================== + void StopWatch(CString msg,bool bStart); + COleDateTime swStart,swEnd; + COleDateTimeSpan swSpan; + //=================== + BOOL bColumnSortAsc[COLUMNCOUNT]; + + long m_lResultCount; + CString m_strOrderBy; + bool ExtractAndRank(CString* excerpt, long * rank); + bool DoSearch(); + void FillView(); + void Mark(CString strText,bool bStopWord); + int m_nSWords; + + void OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnRvnItemDrawPreview(NMHDR* pNMHDR, LRESULT* pResult); + void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(SRCH) + afx_msg void OnBtnsearch(); + afx_msg void OnCloseupCbdate(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + void LayoutControls(void); + int m_nCX; + afx_msg void OnSize(UINT nType, int cx, int cy); + CStatic m_lblDateRange; + CStatic m_lblClients; + CStatic m_lblKeyWords; + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + afx_msg void OnCbnSelchangeCbclients(); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SRCH_H__B3971467_FC37_11D3_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.cpp new file mode 100644 index 0000000..81c180c --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.cpp @@ -0,0 +1,2216 @@ +// STAT.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "STAT.h" + +#include "ContactsViewDlg.h" +#include "PerfTimer.h" +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +//memory leak debugging help +#define _CRTDBG_MAP_ALLOC +#include +#include +///////////////////////////////////////////////////////////////////////////// +// STAT + +IMPLEMENT_DYNCREATE(STAT, CFormView) + +STAT::STAT() +: CFormView(STAT::IDD) +, m_bFreshStatsAwait(false) +, m_strStats(_T("")) +{ + //{{AFX_DATA_INIT(STAT) + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + + + //Initialize recordset pointer + + rs=m_pApp->rsPool->GetRS("STAT RS"); + cbrs=m_pApp->rsPool->GetRS("STAT CBRS"); + brs=m_pApp->rsPool->GetRS("STAT brs"); + rsPrint=m_pApp->rsPool->GetRSPrint("STAT RSPRINT"); + + + m_bShowDescription=true; + + + + m_nFldCount=0; + m_strSelectedView="0"; + dv.sqlcriteria="WHERE (((wo.closed)>Date()-45));"; + FirstRun=true;//indicates first time filling the view + m_pApp->m_bRefreshStatScreen=true;//refresh stat screen on activate + m_nCX=0; +} + +STAT::~STAT() +{ + + DeActivate(); + //AfxMessageBox("STAT::~STAT()"); +} + +void STAT::DoDataExchange(CDataExchange* pDX) +{ + CFormView::DoDataExchange(pDX); + //{{AFX_DATA_MAP(STAT) + DDX_Control(pDX, IDC_BTNCLIENTNOTES, m_btnClientNotes); + DDX_Control(pDX, IDC_BTNREFRESH, m_btnRefresh); + DDX_Control(pDX, IDC_BTNNEWWO, m_btnNewSTWO); + DDX_Control(pDX, IDC_BTNNEWQWO, m_btnNewQWO); + DDX_Control(pDX, IDC_BTNEDITWONUM, m_btnEditWO); + DDX_Control(pDX, IDC_BTNPRINT, m_btnPrint); + DDX_Control(pDX, IDC_lblContactInfo, m_lblContactInfo); + DDX_Control(pDX, IDC_EDWONUM, m_edWONumber); + DDX_Control(pDX, IDC_CBVIEWS, m_cbViews); + DDX_Control(pDX, IDC_LBLCHOOSEFIELDS, m_lblChooseDisplayFields); + DDX_Control(pDX, IDC_LBLSAVEVIEW, m_lblSaveView); + DDX_Control(pDX, IDC_LBLDELETEVIEW, m_lblDeleteView); + DDX_Control(pDX, IDC_RPTDISPATCH, m_rc); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(STAT, CFormView) +//{{AFX_MSG_MAP(STAT) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_BN_CLICKED(IDC_LBLSAVEVIEW, OnLblsaveview) +ON_BN_CLICKED(IDC_LBLDELETEVIEW, OnLbldeleteview) +ON_BN_CLICKED(IDC_LBLCHOOSEFIELDS, OnLblchoosefields) +ON_CBN_CLOSEUP(IDC_CBVIEWS, OnCloseupCbviews) +ON_BN_CLICKED(IDC_BTNNEWWO, OnBtnnewwo) +ON_BN_CLICKED(IDC_BTNNEWQWO, OnBtnnewqwo) +ON_BN_CLICKED(IDC_BTNPRINT, OnBtnprint) +ON_BN_CLICKED(IDC_BTNEDITWONUM, OnBtneditwonum) +ON_BN_CLICKED(IDC_BTNREFRESH, OnBtnrefresh) +ON_BN_CLICKED(IDC_BTNCLIENTNOTES, OnBtnclientnotes) +ON_WM_SIZE() +ON_NOTIFY(RVN_ITEMDRAWPREVIEW, IDC_RPTDISPATCH, OnRvnItemDrawPreview) +ON_NOTIFY(RVN_ITEMDBCLICK, IDC_RPTDISPATCH, OnRvnItemDbClick) +ON_NOTIFY(RVN_ITEMCLICK, IDC_RPTDISPATCH, OnRvnItemClick) +ON_NOTIFY(RVN_COLUMNCLICK, IDC_RPTDISPATCH, OnColumnClick) +//}}AFX_MSG_MAP +ON_WM_MOUSEMOVE() +ON_WM_HELPINFO() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// STAT diagnostics + +#ifdef _DEBUG +void STAT::AssertValid() const +{ + CFormView::AssertValid(); +} + +void STAT::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// STAT message handlers + +void STAT::OnInitialUpdate() +{ + + CString q; + CFormView::OnInitialUpdate(); + + //ShowWindow(FALSE); +#ifdef _WTF_ + AfxMessageBox("STAT::OnInitialUpdate\r\nTOP. CALLING ALLOWED"); +#endif + //no sense doing this if it's not going to be + //accessed + if(m_pApp->Allowed(RSTAT,false)==0) return; + //TEST DEC 5th changed to not refresh above + +#ifdef _WTF_ + AfxMessageBox("STAT::OnInitialUpdate\r\n1"); +#endif + + CWaitCursor wait; + + + + //Set the initial sort order for the columns + for(int xx=0;xxm_lusrID); + rs->QueryReadOnly(q); + rs->FetchField("statview",&m_strSelectedView); + if(m_strSelectedView.IsEmpty()) + { + //some users have deleted the default view + //so make sure it can't be deleted + m_strSelectedView="1"; + } + + FillViewList(); + //"Hyperlink-o-size" labels + m_lblDeleteView.SetTextColor(RGB(0,0,255)); + m_lblDeleteView.SetFontUnderline(TRUE); + m_lblDeleteView.SetLink(TRUE); + m_lblDeleteView.SetLinkCursor(m_pApp->hcHand); + m_lblDeleteView.SetLinkURL(""); + + m_lblSaveView.SetTextColor(RGB(0,0,255)); + m_lblSaveView.SetFontUnderline(TRUE); + m_lblSaveView.SetLink(TRUE); + m_lblSaveView.SetLinkCursor(m_pApp->hcHand); + m_lblSaveView.SetLinkURL(""); + + m_lblChooseDisplayFields.SetTextColor(RGB(0,0,255)); + m_lblChooseDisplayFields.SetFontUnderline(TRUE); + m_lblChooseDisplayFields.SetLink(TRUE); + m_lblChooseDisplayFields.SetLinkCursor(m_pApp->hcHand); + m_lblChooseDisplayFields.SetLinkURL(""); + + //m_lblContactInfo.SetFontSize(6); + // m_lblContactInfo.SetBkColor(RGB(255,255,255)); + //m_lblContactInfo.SetFontBold(TRUE); + + m_ilReport.Create(IDB_REPORT, 16, 1, RGB(255,0,255)); + m_rc.SetImageList(&m_ilReport); + + int y=0; + RVCOLUMN rvc; + rvc.iWidth = 120; + rvc.nFormat = RVCF_TEXT|RVCF_LEFT; + + rvc.lpszText = "Client"; + m_rc.DefineColumn(y, &rvc); + + + rvc.nFormat = RVCF_TEXT|RVCF_CENTER;//center the dates + rvc.lpszText = "SchedDate"; + m_rc.DefineColumn(++y, &rvc); + rvc.lpszText = "SchedEndDate"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "SchedTech"; + m_rc.DefineColumn(++y, &rvc); + + rvc.nFormat = RVCF_TEXT|RVCF_LEFT; + rvc.lpszText = "EntryDate"; + m_rc.DefineColumn(++y, &rvc); + rvc.lpszText = "LastActivity"; + m_rc.DefineColumn(++y, &rvc); + + //Checkmark + rvc.nFormat = RVCF_TEXT|RVCF_SUBITEM_IMAGE|RVCF_CENTER; + //rvc.iImage = 2; + rvc.lpszText = "Onsite"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "Closed"; + m_rc.DefineColumn(++y, &rvc); + + + rvc.nFormat = RVCF_TEXT|RVCF_LEFT; + rvc.lpszText = "ClosedDate"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "Postal"; + m_rc.DefineColumn(++y, &rvc); + rvc.lpszText = "City"; + m_rc.DefineColumn(++y, &rvc); + rvc.lpszText = "WO#"; + m_rc.DefineColumn(++y, &rvc); + rvc.lpszText = "Zone"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "Invoice"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "Date"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "Status"; + m_rc.DefineColumn(++y, &rvc); + + + rvc.lpszText = "OurRef#"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "ClientRef#"; + m_rc.DefineColumn(++y, &rvc); + + //Last modified 07/30/2001 - added category/type column + //COLUMNMOD + rvc.lpszText = "Category"; + m_rc.DefineColumn(++y, &rvc); + + rvc.lpszText = "Project"; + m_rc.DefineColumn(++y, &rvc); + + //ADD NEW COLUMNS JUST BEFORE HERE IN FUTURE + ++y; + m_nFldCount=y; + //did we forget to increment the column count + //defined in the header? + ASSERT(!(m_nFldCount>STATCOLUMNCOUNT)); + //DisplayColumns(); + //FillView(); + /*//removed this code as causing an error when default + //view was deleted + cbrs->Query("SELECT statusviews.id FROM statusviews WHERE (((statusviews.default)=True));"); + long lData; + cbrs->FetchField("id",&lData); + m_strSelectedView.Format("%u",lData); + */ + OnCloseupCbviews(); + + //ShowWindow(TRUE); + //ShowWindow(SW_MAXIMIZE); + + FirstRun=false; + //unlock the recordsets + DeActivate(); +} + + +void STAT::OnBtndone() +{ + //CDialog::OnOK(); +} + + + + + +//********************************************* +void STAT::FillView() +{ +#ifdef _DEBUG +// CPerfTimer pTimer; +// pTimer.Start(TRUE); +#endif + //Added Oct 4th 2002 + if(m_pApp->m_bDefShowHGridOnMainScreen) + m_rc.ModifyStyle(0,RVS_SHOWHGRID); + else + m_rc.ModifyStyle(RVS_SHOWHGRID,0); + + + if(!m_pApp->m_bRefreshStatScreen) + return; + m_pApp->m_bRefreshStatScreen=false; + + //Added Oct 5th 2002. + //gets stats if enabled so they can be displayed at top when + //a wo is not selected in the list + GetStats(); + + //Show stats now so that display is never empty at the top + //safe to do so because the list is just about to be + //refreshed anyway so there is no way a user will have + //a selection from the workorder list at this point (or at least in a few + //milliseconds anyway) + m_bFreshStatsAwait=false; + m_lblContactInfo.SetWindowText(m_strStats); + + + CString q,qbrs,strData,str,parameters,strBriefs,strWONotes; + long lData,lWOID,T1,T2,T3,T4;/* Added t1 to t4 Oct 10 2002 to more properly format schedtech display*/ + COleDateTime dtData,dtClosed,dtScheduled,dtEntry; + bool bData,bHasText,bQuick,bIsScheduled; + bool bAbort=false,bPrompt=true;//abort fetch, prompt if > 250 records + int nContinuePromptChoice; + int x=0; + int y=0; + int probnum,lines; + int x2=0; + + CWaitCursor cWait; + + //"PARAMETERS" -way to complex to pass parameters, so + //putting them in the datastream instead. + if(dv.preview) + parameters="True AS zShowNotes, "; + else + parameters="False AS zShowNotes, "; + + str.Format("\"%s\" AS zCurrentUser, ",m_pApp->m_strCurrentUserName); + parameters = parameters + str; + + + //TODO: only shows main tech, should it be modified to show all techs? + + //Last modified 07/30/2001 - added category/type column + //COLUMNMOD + /* + q.Format("SELECT %s IIf([wo].[anytime]=True,[wo].[created],[wo].[starttime]) AS cdate, wo.notes AS wonotes, wo.invoice, " + "IIf(IsNull([company]),[clients]![last] & \", \" & [clients]![first],[company]) AS clientcompany, " + "wo.anytime, wo.starttime, wo.stoptime, users.initials, wo.created, wo.modified, " + "wo.onsite, wo.closed, wo.prob_found, wo.prob_reported, wo.action_taken, clients.postal, " + "clients.city, zones.name AS zonename, wo.quick, wo.id, wo.ourref, wo.clientrefnum, probstat.notes AS wostatus, wotypes.category, projects.name AS projname " + "FROM (((((wo LEFT JOIN users ON wo.assigntech = users.id) LEFT JOIN clients ON " + "wo.client = clients.id) LEFT JOIN zones ON clients.czone = zones.id) LEFT JOIN " + "projects ON wo.project = projects.id)LEFT JOIN probstat ON wo.status = probstat.id) LEFT JOIN wotypes ON wo.type = wotypes.id %s %s;",parameters, dv.sqlcriteria, dv.sqlorderby); + +*/ + + q.Format("SELECT %s " + "IIf([wo].[anytime]=True,[wo].[created],[wo].[starttime]) AS cdate, wo.notes AS wonotes, " + "wo.invoice, clients.company AS clientcompany, wo.anytime, wo.starttime, wo.stoptime, users.initials, " + "users_1.initials AS INIT2, users_2.initials AS INIT3, users_3.initials AS INIT4, wo.created, wo.modified, wo.onsite, " + "wo.assigntech AS T1, wo.assigntech2 AS T2, wo.assigntech3 AS T3, wo.assigntech4 AS T4, " + "wo.closed, wo.prob_found, wo.prob_reported, wo.action_taken, clients.postal, clients.city, " + "zones.name AS zonename, wo.quick, wo.id, wo.ourref, wo.clientrefnum, probstat.notes AS wostatus, " + "wotypes.category, projects.name AS projname " +"FROM ((((((((wo LEFT JOIN users ON wo.assigntech = users.id) LEFT JOIN clients ON wo.client = " +"clients.id) LEFT JOIN zones ON clients.czone = zones.id) LEFT JOIN projects ON wo.project = projects.id) " +"LEFT JOIN probstat ON wo.status = probstat.id) LEFT JOIN wotypes ON wo.type = wotypes.id) " +"LEFT JOIN users AS users_1 ON wo.assigntech2 = users_1.id) LEFT JOIN users AS users_2 ON wo.assigntech3 = users_2.id) " +"LEFT JOIN users AS users_3 ON wo.assigntech4 = users_3.id " +"%s %s;",parameters, dv.sqlcriteria, dv.sqlorderby); + + + +#ifdef _DEBUG + //m_pApp->ShowStuff(q); +#endif + ASSERT(rs!=NULL); + + rs->QueryReadOnly(q); + + lsNotes.RemoveAll(); + m_rc.DeleteAllItems(); + if(rs->IsEmpty()) + { + DeActivate(); + return; + + } + + + + do{ + + bHasText=false; + y=0; + RVITEM rvi; + + + + + + + //WORKORDER BRIEF DESCRIPTIONS LOOP HERE + //If not quick workorder: Loop through all prob records for current workorder + //gather up all briefs and insert into strData for processing as normal + rs->FetchField("quick",&bQuick); + rs->FetchField("id",&lData); + strData.Format("%u",lData); + strBriefs.Empty(); + if(!bQuick)//not quick wo + { + if(!m_pApp->m_bShowProblemActionFields) + { + probnum=0; + rs->FetchField("wonotes",&strWONotes); + if(!strWONotes.IsEmpty()) + { + //probnum=1; + //strWONotes.Replace("&","&&"); + strBriefs=strWONotes+"\r\n"; + //covered in case no problems + bHasText=true; + lines=17; + } + /* + qbrs.Format("SELECT probs.brief FROM probs WHERE " + "(((probs.wolink)=%s) AND ((probs.brief)<>\"\")) ORDER BY probs.id;",strData); + */ + qbrs.Format("SELECT probs.brief, probstat.notes AS STATUS " + "FROM probs LEFT JOIN probstat ON probs.status = probstat.id " + "WHERE (((probs.brief)<>\"\") AND ((probs.wolink)=%s)) " + "ORDER BY probs.id;",strData); + +#ifdef _DEBUG + + //m_pApp->ShowStuff(qbrs); +#endif + + brs->QueryReadOnly(qbrs); + if(!brs->IsEmpty()) + { + strData.Empty(); + + do + { + probnum++; + strData.Format(" %i)",probnum); + if(probnum>1) + strBriefs+="\r\n"; + strBriefs+=strData; + brs->FetchField("STATUS",&strData); + if(!strData.IsEmpty()) + { + strData=" <" + strData + "> "; + } + strBriefs=strBriefs+strData;//+ "\r\n"; + brs->FetchField("brief",&strData); + //strData.Replace("&","&&"); + strBriefs=strBriefs+strData;//+ "\r\n"; + }while(brs->MoveForward()); + + if(!strBriefs.IsEmpty()) + { + bHasText=true; + if(!strWONotes.IsEmpty()) probnum++; + lines=probnum*17; + //lines=(strBriefs.GetLength()/64)*20; + //if(lines<17) lines=17; + } + } + }//alternate view + else//it's a securenet view + { + bHasText=true; + //problem reported + rs->FetchField("prob_reported",&strData); + strData.Replace("&","&&"); + strBriefs="Problem reported: " + strData +"\r\n"; + + //problem found + rs->FetchField("prob_found",&strData); + strData.Replace("&","&&"); + strBriefs+="\r\nProblem found: " + strData +"\r\n"; + + //Action Taken + rs->FetchField("action_taken",&strData); + strData.Replace("&","&&"); + strBriefs+="\r\nAction taken: " + strData; + + strBriefs.TrimRight('\r'); + strBriefs.TrimRight('\n'); + + x2=0; + lines=0; + while (x2!=-1) + { + x2=strBriefs.Find('\r',x2); + if(x2!=-1) + x2++; + lines+=15; + } + + lines = m_rc.PreviewHeight(m_rc.GetFont(), strBriefs); + lines = lines<0 ? 56:lines; + + lines+=10; + + }//securenet view + } + if(x==0) + lsNotes.AddHead(strBriefs); + else + lsNotes.AddTail(strBriefs); + + + + + + + + + //CLIENT + if(!rs->FetchField("clientcompany",&strData)) + { + DeActivate(); + return; + + } + strData.Replace("&","&&"); + rvi.iItem = x; + rvi.iSubItem = y; + rvi.nMask = RVIM_PREVIEW|RVIM_TEXT|RVIM_LPARAM; + if(dv.preview && bHasText) + rvi.nPreview = lines;//show first line only + else + rvi.nPreview = 0; + + //Original with incorrect use of GetBuffer (and missing releasebuffer) + //rvi.lpszText = strData.GetBuffer(strData.GetLength()); + //m_rc.InsertItem(&rvi); + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.InsertItem(&rvi); + strData.ReleaseBuffer(); + + + + //SCHEDULE DATE AND TIME + rs->FetchField("anytime",&bData);//see if it's scheduled + bIsScheduled=!bData;//added 10/10/2002 for use by sched tech below + if(!bData || bQuick) + { + //start date + if(bQuick)//added 11/03/00 + strData=""; + else + { + rs->FetchField("starttime",&dtData); + strData=dtData.Format(); + } + rvi.iSubItem = ++y; + rvi.lParam = x; + + //Original with incorrect use of GetBuffer (and missing releasebuffer) + //rvi.lpszText = strData.GetBuffer(strData.GetLength()); + //m_rc.SetItem(&rvi); + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //end date + if(bQuick) + strData=""; + else + { + rs->FetchField("stoptime",&dtData); + strData=dtData.Format(); + } + rvi.iSubItem = ++y; + rvi.lParam = x; + + //Original with incorrect use of GetBuffer (and missing releasebuffer) + //rvi.lpszText = strData.GetBuffer(strData.GetLength()); + //m_rc.SetItem(&rvi); + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + } + else + {//anytime, so indicate with a --- + strData=" --- "; + rvi.iSubItem = ++y; + m_rc.SetItem(&rvi); + rvi.iSubItem = ++y; + m_rc.SetItem(&rvi); + + + } + + //SCHED TECH + //modified 8/23/2001 to support multi techs + strData.Empty(); + if(bIsScheduled ||bQuick) + { + rs->FetchField("T1",&T1); + rs->FetchField("T2",&T2); + rs->FetchField("T3",&T3); + rs->FetchField("T4",&T4); + + + if(0==T1) + str="?"; + else + { + rs->FetchField("initials",&str); + } + + if(!str.IsEmpty()) + strData=str; + + + if(0==T2) + str="?"; + else + { + rs->FetchField("INIT2",&str); + } + if(!str.IsEmpty()) + strData+=", " + str; + + if(0==T3) + str="?"; + else + { + rs->FetchField("INIT3",&str); + } + + if(!str.IsEmpty()) + strData+=", " + str; + + + if(0==T4) + str="?"; + else + { + rs->FetchField("INIT4",&str); + } + + if(!str.IsEmpty()) + strData+=", " + str; + + + if(strData.IsEmpty()) + strData="---"; + + if(bQuick) + strData="*"+strData;//indicating it's a quick workorder + + strData.TrimLeft(','); + }//if scheduled + else + strData="---"; + + + //rvi.iTextColor + + //Original with incorrect use of GetBuffer (and missing releasebuffer) + //rvi.lpszText = strData.GetBuffer(strData.GetLength()); + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + rvi.iSubItem = ++y; + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //ENTRY DATE + rs->FetchField("created",&dtData); + strData=dtData.Format();//VAR_DATEVALUEONLY); + rvi.iSubItem = ++y; + rvi.lParam = x; + //Original with incorrect use of GetBuffer (and missing releasebuffer) + //rvi.lpszText = strData.GetBuffer(strData.GetLength()); + //m_rc.SetItem(&rvi); + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + + //Last activity DATE + rs->FetchField("modified",&dtData); + strData=dtData.Format(VAR_DATEVALUEONLY); + rvi.iSubItem = ++y; + rvi.lParam = x; + //Original with incorrect use of GetBuffer (and missing releasebuffer) + //rvi.lpszText = strData.GetBuffer(strData.GetLength()); + //m_rc.SetItem(&rvi); + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + + //ONSITE + rs->FetchField("onsite",&bData); + rvi.nMask = RVIM_IMAGE |RVIM_CHECK; + rvi.nState = 0;//RVIS_BOLD; + rvi.iSubItem = ++y; + rvi.lParam = x; + //rvi.iImage = 2; + rvi.iCheck = bData ? TRUE : FALSE; + rvi.lpszText = "Check"; + m_rc.SetItem(&rvi); + + + //CLOSED CHECK / CLOSED DATE + rs->FetchField("closed",&dtClosed); + if(dtClosed.GetYear()==1968)//still open + { //isn't closed + rvi.nMask = RVIM_IMAGE |RVIM_CHECK; + rvi.nState = 0;//RVIS_BOLD; + rvi.iSubItem = ++y; + rvi.lParam = x; + //rvi.iImage = 2; + rvi.iCheck = FALSE; + rvi.lpszText = "Check"; + m_rc.SetItem(&rvi); + strData="open"; + + } + else + { //is closed + rvi.nMask = RVIM_IMAGE |RVIM_CHECK; + rvi.nState = 0;//RVIS_BOLD; + rvi.iSubItem = ++y; + rvi.lParam = x; + //rvi.iImage = 2; + rvi.iCheck = TRUE; + rvi.lpszText = "Check"; + m_rc.SetItem(&rvi); + //v1.9.4.4 - apparently an overwhelming majority of people + //want to see the time as well as the date for closed so... +// strData=dtClosed.Format(VAR_DATEVALUEONLY); + strData=dtClosed.Format(); + + } + //date + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //POSTAL CODE + rs->FetchField("postal",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //CITY + rs->FetchField("city",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + + //WORKORDER ID + rs->FetchField("quick",&bData); + rs->FetchField("id",&lData); + lWOID=lData;//added 11/20/2002 used by DATE column quick work order query below + strData.Format("%u",lData); + + if(bData) + strData=strData+"*";//language neutral depiction of quick workorder + + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + + //CZONE + rs->FetchField("zonename",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + + //INVOICE + rs->FetchField("invoice",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //DATE- combined entry date for quick or non booked standard + // sched date for open standard + if(!bQuick) + rs->FetchField("cdate",&dtData); + else//added 11/03/00//changed 11/20/2002 (is supposed to be quick work order start date not closed date) + { + //strData=dtClosed.Format(VAR_DATEVALUEONLY); + qbrs.Format("SELECT labor.start FROM labor RIGHT JOIN (probs RIGHT " + "JOIN wo ON probs.wolink = wo.id) ON labor.link " + "= probs.id WHERE (((wo.id)=%u));",lWOID); + brs->QueryReadOnly(qbrs); + if(!brs->IsEmpty()) + { + brs->FetchField("start",&dtData); + + } + + + } + + strData=dtData.Format(VAR_DATEVALUEONLY); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //STATUS + rs->FetchField("wostatus",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + //rvi.iTextColor + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi); + */ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //OURREF + rs->FetchField("ourref",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //clientREF + rs->FetchField("clientrefnum",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //Last modified 07/30/2001 - added category/type and project column + //COLUMNMOD + rs->FetchField("category",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + //project name + rs->FetchField("projname",&strData); + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = ++y; + rvi.lParam = x; + /*rvi.lpszText = strData.GetBuffer(strData.GetLength()); + m_rc.SetItem(&rvi);*/ + //02/19/2003 - GetBuffer / ReleaseBuffer change + rvi.lpszText = strData.GetBuffer(0); + m_rc.SetItem(&rvi); + strData.ReleaseBuffer(); + + + + + + + //NEW COLUMNS BEFORE HERE + x++; + + //overflow handler here + if((x % 250)==0 && bPrompt==true) + { + nContinuePromptChoice=AfxMessageBox( + "There's a lot of data here!\r\n" + "You can configure your view to display less records\r\n\r\n" + "Do you want to be prompted again after another 250 records [Yes/No] ...\r\n" + "or cancel retrieving data now? [Cancel]",MB_YESNOCANCEL); + + if(nContinuePromptChoice==IDCANCEL) bAbort=true; + if(nContinuePromptChoice==IDNO) bPrompt=false; + + + cWait.Restore();//go back to a wait cursor + + + } + }while(rs->MoveForward() && !bAbort); + +#ifdef _DEBUG +/* + CString strPerf; +pTimer.Stop(); +strPerf.Format("Time: %.3f",pTimer.Elapsed()); +AfxMessageBox(strPerf); +*/ +#endif + + //clear the recordsets + DeActivate(); +} + + + + + + //************************************************ + void STAT::OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult) + { + + CString str; + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + + str=m_rc.GetItemText(lpnmrv->iItem,11); + + if(str.Right(1)=='*')//quick workorder + { + str.Remove('*'); + CSimpleWODlg qwo; + qwo.SetWorkorderID(&str); + qwo.DoModal(); + + } + else + { + CWOHeaderDlg wo; + wo.SetWorkorderID(str); + wo.DoModal(); + + } + + + + + + + + + } + + + + *pResult = FALSE; + FillView(); + } + + //************************************************ + // USED TO RETRIEVE ADDRESS AND CONTACT INFO + //************************************************ + void STAT::OnRvnItemClick(NMHDR* pNMHDR, LRESULT* pResult) + { + + CString strWOID,q, strData, strDisplay; + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + + strWOID=m_rc.GetItemText(lpnmrv->iItem,11); + //remove asterisk which is appended to quick workorder + //numbers + strWOID.Remove('*'); + + //retrieve contact info based on workorder + + q.Format( + "SELECT clients.first, clients.last, clients.company, " + "clients.mailaddress, clients.streetaddress, clients.city, " + "clients.stateprov, clients.postal, clients.country, clients.bizphone, " + "clients.extension, clients.fax, clients.email " + "FROM wo LEFT JOIN clients ON wo.client = clients.id " + "WHERE (((wo.id)=%s));",strWOID); + + cbrs->QueryReadOnly(q); + + + + strDisplay="[Contact: "; + cbrs->FetchField("first",&strData); + if(!strData.IsEmpty()) + strDisplay+=strData + " "; + + cbrs->FetchField("last",&strData); + strDisplay+=strData+"]"; + + cbrs->FetchField("bizphone",&strData); + if(!strData.IsEmpty()) + strDisplay+= "[Phone: " + strData; + + cbrs->FetchField("extension",&strData); + if(!strData.IsEmpty()) + strDisplay+=" ext:" + strData; + + strDisplay+="]"; + + + + cbrs->FetchField("fax",&strData); + if(!strData.IsEmpty()) + strDisplay+="[Fax: " + strData + "]"; + + cbrs->FetchField("email",&strData); + if(!strData.IsEmpty()) + strDisplay+="[Email: " + strData + "]"; + + //Physical address for Lenny and the lock people + strDisplay+="[Addr: "; + cbrs->FetchField("streetaddress",&strData); + if(!strData.IsEmpty()) + strDisplay+= strData + ", "; + cbrs->FetchField("city",&strData); + if(!strData.IsEmpty()) + strDisplay+= strData; + strDisplay+="]"; + + m_lblContactInfo.SetWindowText(strDisplay); + + } + + //Indicate that stats are available to be displayed + //since this function just overwrote the stats display + m_bFreshStatsAwait=true; + + *pResult = FALSE; + + } + //******************************************** + void STAT::OnRvnItemDrawPreview(NMHDR* pNMHDR, LRESULT* pResult) + { + + CString strText; + LPNMRVDRAWPREVIEW lpnmrvdp = (LPNMRVDRAWPREVIEW)pNMHDR; + + strText=lsNotes.GetAt(lsNotes.FindIndex(lpnmrvdp->iItem)); + CReportCtrl& rc = m_rc; + + CDC dc; + dc.Attach(lpnmrvdp->hDC); + if(lpnmrvdp->nState&RVIS_SELECTED) + dc.SetTextColor(::GetFocus()==rc.m_hWnd ? GetSysColor(COLOR_HIGHLIGHTTEXT):GetSysColor(COLOR_HIGHLIGHT)); + else + dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHT)); + + lpnmrvdp->rect.left += 40; + lpnmrvdp->rect.top += 2; + lpnmrvdp->rect.bottom -= 2; + dc.DrawText(strText, &lpnmrvdp->rect, DT_LEFT|DT_END_ELLIPSIS|DT_WORDBREAK|DT_NOPREFIX|DT_EXPANDTABS); + + dc.Detach(); + *pResult = FALSE; + + + } + + + + + //************************************** + //void STAT::OnOK() + //{} + + //SET ORDER BY CLAUSE DEPENDING ON CLICK HERE + void STAT::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) + { + CWaitCursor Wait; + int x; + CString str; + CFlatHeaderCtrl* header; + header=m_rc.GetHeaderCtrl(); + dv.sqlorderby.Empty(); + //FIND CLICKED COLUMN + + str=header->m_szHotItemText; + + if(str=="Client") + { + x=0; + goto OUTTAHERE; + } + if(str=="SchedDate") + { + x=1; + goto OUTTAHERE; + } + if(str=="SchedEndDate") + { + x=2; + goto OUTTAHERE; + } + if(str=="Date") //here because it's more common + { + x=14; + goto OUTTAHERE; + } + if(str=="SchedTech") + { + x=3; + goto OUTTAHERE; + } + if(str=="EntryDate") + { + x=4; + goto OUTTAHERE; + } + + if(str=="LastActivity") + { + x=5; + goto OUTTAHERE; + } + if(str=="Onsite") + { + x=6; + goto OUTTAHERE; + } + + if(str=="Closed") + { + x=7; + goto OUTTAHERE; + } + + if(str=="ClosedDate") + { + x=8; + goto OUTTAHERE; + } + + if(str=="Postal") + { + x=9; + goto OUTTAHERE; + } + + if(str=="City") + { + x=10; + goto OUTTAHERE; + } + if(str=="WO#") + { + x=11; + goto OUTTAHERE; + } + if(str=="Zone") + { + x=12; + goto OUTTAHERE; + } + if(str=="Invoice") + { + x=13; + goto OUTTAHERE; + } + if(str=="Status") + { + x=15; + goto OUTTAHERE; + } + if(str=="OurRef#") + { + x=16; + goto OUTTAHERE; + } + if(str=="OurRef#") + { + x=16; + goto OUTTAHERE; + } + if(str=="ClientRef#") + { + x=17; + goto OUTTAHERE; + } + + //Last modified 07/30/2001 - added category/type column + //COLUMNMOD + if(str=="Category") + { + x=18; + goto OUTTAHERE; + } + + if(str=="Project") + { + x=19; + goto OUTTAHERE; + } + +OUTTAHERE:; + bColumnSortAsc[x]=!bColumnSortAsc[x]; + + switch(x) + {//DESC + case 0://client + dv.sqlorderby="ORDER BY IIf(IsNull([company]),[clients]![last] & \", \" & [clients]![first],[company])"; + break; + case 1://scheddate + dv.sqlorderby="ORDER BY starttime"; + break; + + case 2://schedenddate + dv.sqlorderby="ORDER BY stoptime"; + break; + + case 3://schedtech + dv.sqlorderby="ORDER BY users.initials"; + break; + + case 4://entrydate + dv.sqlorderby="ORDER BY wo.created"; + break; + + + case 5://lastactivity + dv.sqlorderby="ORDER BY wo.modified"; + break; + + + case 6://onsite + dv.sqlorderby="ORDER BY onsite"; + break; + + + case 7://closed + dv.sqlorderby="ORDER BY closed"; + break; + + + case 8://closeddate + dv.sqlorderby="ORDER BY closed"; + break; + + + case 9://postal + dv.sqlorderby="ORDER BY postal"; + break; + + + case 10://city + dv.sqlorderby="ORDER BY city"; + break; + + + case 11://wo# + dv.sqlorderby="ORDER BY wo.id"; + break; + + + case 12://ZONE <-one of the underlying + //tenets of this universe is that the word + //ZONE must be capitalized at all times :) + dv.sqlorderby="ORDER BY zones.name"; + break; + + + case 13://invoice + dv.sqlorderby="ORDER BY invoice"; + break; + + + case 14://DATE Combined date + dv.sqlorderby="ORDER BY IIf([wo].[anytime]=True,[wo].[created],[wo].[starttime])"; + break; + + case 15://STATUS + dv.sqlorderby="ORDER BY probstat.notes"; + break; + + + case 16://OURREF + dv.sqlorderby="ORDER BY wo.ourref"; + break; + //wo.ourref, probstat.notes AS wostatus + + case 17://customer REF + dv.sqlorderby="ORDER BY wo.clientrefnum"; + break; + + //Last modified 07/30/2001 - added category/type and project column + //COLUMNMOD + case 18://CATEGORY + dv.sqlorderby="ORDER BY wotypes.category"; + break; + + case 19://PROJECT + dv.sqlorderby="ORDER BY projects.name"; + break; + + + + } + + if(!bColumnSortAsc[x]) + dv.sqlorderby+=" DESC"; + + + header->SetSortColumn(header->GetHotIndex(),bColumnSortAsc[x]); + + *pResult = TRUE;//TRUE means we handled it here thanks anyway + OnBtnrefresh(); +} + +//*************************************** +void STAT::DisplayColumns() +{ + + if(dv.client!=0) + m_rc.ActivateColumn(0, 0); + else + m_rc.DeactivateColumn(0); + + if(dv.schedstart!=0) + m_rc.ActivateColumn(1, 1); + else + m_rc.DeactivateColumn(1); + + if(dv.schedenddate!=0) + m_rc.ActivateColumn(2, 2); + else + m_rc.DeactivateColumn(2); + + if(dv.schedtech!=-2) + m_rc.ActivateColumn(3, 3); + else + m_rc.DeactivateColumn(3); + + if(dv.wocreateddate!=0) + m_rc.ActivateColumn(4, 4); + else + m_rc.DeactivateColumn(4); + + if(dv.lastactivity!=0) + m_rc.ActivateColumn(5, 5); + else + m_rc.DeactivateColumn(5); + + if(dv.onsite!=0) + m_rc.ActivateColumn(6, 6); + else + m_rc.DeactivateColumn(6); + + if(dv.closed!=0) + m_rc.ActivateColumn(7, 7); + else + m_rc.DeactivateColumn(7); + + if(dv.closeddate!=0) + m_rc.ActivateColumn(8, 8); + else + m_rc.DeactivateColumn(8); + + if(dv.postal!=0) + m_rc.ActivateColumn(9, 9); + else + m_rc.DeactivateColumn(9); + + if(dv.city!=0) + m_rc.ActivateColumn(10, 10); + else + m_rc.DeactivateColumn(10); + + if(dv.workorder!=0) + m_rc.ActivateColumn(11, 11); + else + m_rc.DeactivateColumn(11); + + if(dv.zone!=0) + m_rc.ActivateColumn(12, 12); + else + m_rc.DeactivateColumn(12); + + if(dv.invoice!=0) + m_rc.ActivateColumn(13, 13); + else + m_rc.DeactivateColumn(13); + + if(dv.date!=0) + m_rc.ActivateColumn(14, 14); + else + m_rc.DeactivateColumn(14); + + if(dv.status!=0) + m_rc.ActivateColumn(15, 15); + else + m_rc.DeactivateColumn(15); + + if(dv.ourrefnumber!=0) + m_rc.ActivateColumn(16, 16); + else + m_rc.DeactivateColumn(16); + + if(dv.custrefnumber!=0) + m_rc.ActivateColumn(17, 17); + else + m_rc.DeactivateColumn(17); + + //Last modified 07/30/2001 - added category/type and project column + //COLUMNMOD + if(dv.category!=0) + m_rc.ActivateColumn(18, 18); + else + m_rc.DeactivateColumn(18); + + //project + if(dv.project!=0) + m_rc.ActivateColumn(19, 19); + else + m_rc.DeactivateColumn(19); + + + +} + + +//************************************ +void STAT::OnLblsaveview() +{ + CString str,newviewname,q; + CGetStringDlg d; + bool overwrite=false;//indicates if overwriting an existing view or it/s a new view + + newviewname=m_cbViews.GetCurrentRowText(); + + d.Setup("Enter a view name:",&newviewname); + if(d.DoModal()==IDCANCEL) + return; + if(newviewname=="< default >") + { + AfxMessageBox("You can not overwrite the default view"); + return; + + } + q.Format("SELECT statusviews.viewname FROM statusviews " + "WHERE (((statusviews.viewname)=\"%s\"));",newviewname); + + + cbrs->QueryReadOnly(q); + if(!cbrs->IsEmpty()) + { + str.Format("Overwrite existing \"%s\" view with new settings?",newviewname); + if(AfxMessageBox(str,MB_YESNO)!=IDYES) + { + DeActivate(); + return; + + } + else + overwrite=true; + } + + + dv.viewname=newviewname; + + //GET PROFILE + m_rc.WriteProfile(&dv.viewprofile); + + if(overwrite) + { + q.Format("SELECT statusviews.* FROM statusviews " + "WHERE (((statusviews.viewname)=\"%s\"));",dv.viewname); + cbrs->Query(q); + } + else + {//add new record + q.Format("SELECT statusviews.* FROM statusviews WHERE (((statusviews.id)=0));"); + cbrs->Query(q); + cbrs->AddNewRecord(); + + } + + //UPDATE EACH FIELD + cbrs->UpdateField("viewname",&dv.viewname); + cbrs->UpdateField("viewprofile",&dv.viewprofile); + cbrs->UpdateField("client",&dv.client); + cbrs->UpdateField("zone",&dv.zone); + cbrs->UpdateField("postal",&dv.postal); + cbrs->UpdateField("city",&dv.city); + cbrs->UpdateField("workorder",&dv.workorder); + cbrs->UpdateField("invoice",&dv.invoice); + cbrs->UpdateField("closed",&dv.closed); + cbrs->UpdateField("closeddate",&dv.closeddate); + cbrs->UpdateField("date",&dv.date); + cbrs->UpdateField("ourref",&dv.ourrefnumber); + cbrs->UpdateField("status",&dv.status); + + cbrs->UpdateField("onsite",&dv.onsite); + cbrs->UpdateField("schedstart",&dv.schedstart); + cbrs->UpdateField("scheddatestart",&dv.scheddatestart); + cbrs->UpdateField("scheddateend",&dv.scheddateend); + cbrs->UpdateField("schedenddate",&dv.schedenddate); + cbrs->UpdateField("schedtech",&dv.schedtech); + cbrs->UpdateField("wocreatedate",&dv.wocreateddate); + cbrs->UpdateField("woentrydate",&dv.woentrydate); + cbrs->UpdateField("woentrydatetype",&dv.woentrydatetype); + cbrs->UpdateField("lastactivity",&dv.lastactivity); + cbrs->UpdateField("sqlcriteria",&dv.sqlcriteria); + cbrs->UpdateField("sqlorderby",&dv.sqlorderby); + cbrs->UpdateField("preview",&dv.preview); + + //Last modified 07/30/2001 - added category/type and project column + //COLUMNMOD + cbrs->UpdateField("category",&dv.category); + cbrs->UpdateField("project",&dv.project); + + //created days + cbrs->UpdateField("createddays",&dv.lCreatedDays); + + + //SAVE + cbrs->SaveRecord(); + + + //REFRESH PICK LIST + FillViewList(); + + + + if(!overwrite) + { + q.Format("SELECT statusviews.id FROM statusviews " + "WHERE (((statusviews.viewname)=\"%s\"));",dv.viewname); + cbrs->QueryReadOnly(q); + cbrs->FetchField("id",&dv.id); + //CENTRE ON NEW VIEW + m_cbViews.Select(dv.id); + } + DeActivate(); + + + +} + + + + + + +//****************************************** +void STAT::OnLbldeleteview() +{ + CString q; + + + q=m_cbViews.GetCurrentRowText(); + + + if(q=="< default >") + { + AfxMessageBox("You can not delete the default view"); + return; + + } + + + q.Format("DELETE statusviews.*, statusviews.id " + "FROM statusviews " + "WHERE (((statusviews.id)=%s));",m_cbViews.GetCurrentRowID()); + cbrs->Ex(q); + cbrs->Close(); + ///cbrs=NULL; + FillViewList(); + OnCloseupCbviews(); +} + + +//****************************************** +void STAT::OnLblchoosefields() +{ + CDispatchFieldsDlg d; + d.SetReturnVariable(&dv); + if(d.DoModal()==IDOK) + { + m_pApp->m_bRefreshStatScreen=true; + DisplayColumns(); + FillView(); + } + + if(AfxMessageBox("Do you want to save changes to this view?",MB_YESNO) ==IDYES) + OnLblsaveview(); + +} + +//================================ +void STAT::FillViewList() +{ + CString strData,strIndex; + long lData; + m_cbViews.Clear(); + + + + cbrs->QueryReadOnly("SELECT statusviews.* FROM statusviews ORDER BY statusviews.viewname;"); + + + if(cbrs->IsEmpty()) + { + DeActivate(); + return; + + } + + do{ + cbrs->FetchField("id",&lData); + cbrs->FetchField("viewname",&strData); + strIndex.Format("%u",lData); + m_cbViews.AddRow(strData,strIndex); + + }while(cbrs->MoveForward()); + //user may have deleted view one + //so select first in list instead + if(m_strSelectedView=="1") + m_cbViews.SetCurSel(0); + else + m_cbViews.Select(m_strSelectedView); + DeActivate(); +} + +//=============================== +void STAT::OnCloseupCbviews() +{ + CString str,q; + str=m_cbViews.GetCurrentRowID(); + if(!FirstRun && str==m_strSelectedView) + { + + return;//no change + } + + + //save users new view preference + m_strSelectedView=str; + q.Format("UPDATE users SET users.statview = \"%s\" " + "WHERE (((users.id)=%u));",str,m_pApp->m_lusrID); + cbrs->Ex(q); + + //load settings for this view then + q.Format("SELECT statusviews.* FROM statusviews WHERE (((statusviews.id)=%s));",m_strSelectedView); + cbrs->QueryReadOnly(q); + if(cbrs->IsEmpty()) + { + DeActivate(); + return; + + } + //UPDATE EACH FIELD + cbrs->FetchField("viewname",&dv.viewname); + cbrs->FetchField("viewprofile",&dv.viewprofile); + cbrs->FetchField("client",&dv.client); + cbrs->FetchField("zone",&dv.zone); + cbrs->FetchField("postal",&dv.postal); + cbrs->FetchField("city",&dv.city); + cbrs->FetchField("workorder",&dv.workorder); + cbrs->FetchField("invoice",&dv.invoice); + cbrs->FetchField("closed",&dv.closed); + cbrs->FetchField("closeddate",&dv.closeddate); + cbrs->FetchField("onsite",&dv.onsite); + cbrs->FetchField("schedstart",&dv.schedstart); + cbrs->FetchField("date",&dv.date); + cbrs->FetchField("ourref",&dv.ourrefnumber); + cbrs->FetchField("custref",&dv.custrefnumber); + cbrs->FetchField("status",&dv.status); + + + cbrs->FetchField("scheddatestart",&dv.scheddatestart); + cbrs->FetchField("scheddateend",&dv.scheddateend); + cbrs->FetchField("woentrydate",&dv.woentrydate); + cbrs->FetchField("woentrydatetype",&dv.woentrydatetype); + cbrs->FetchField("schedenddate",&dv.schedenddate); + cbrs->FetchField("schedtech",&dv.schedtech); + cbrs->FetchField("wocreatedate",&dv.wocreateddate); + cbrs->FetchField("lastactivity",&dv.lastactivity); + cbrs->FetchField("sqlcriteria",&dv.sqlcriteria); + cbrs->FetchField("sqlorderby",&dv.sqlorderby); + cbrs->FetchField("preview",&dv.preview); + cbrs->FetchField("virtualreport",&dv.virtualreport); + + //Last modified 07/30/2001 - added category/type column + //COLUMNMOD + cbrs->FetchField("category",&dv.category); + cbrs->FetchField("project",&dv.project); + // created days 10/11/2002 + cbrs->FetchField("createddays",&dv.lCreatedDays); + + DeActivate(); + + + //modified 07/30/2001 was set to x<17 explicitly changed to STATCOLUMNCOUNT + for(int x=0;xAllowed(RWORKORDER,true); + if(x!=1)//no write allowed + { + m_pApp->SecurityWarning(); + return; + } + CWOHeaderDlg wo; + wo.SetWorkorderID("0"); + if(wo.DoModal()==IDOK) + { + m_pApp->m_bRefreshStatScreen=true; + FillView(); + } + + +} + +void STAT::OnBtnnewqwo() +{ + + int x=m_pApp->Allowed(RWORKORDER,true); + if(x!=1)//no write allowed + { + m_pApp->SecurityWarning(); + return; + } + + CString temp="0"; + + //This is to work around a bug, if previous + //qwo deleted a workorder + //the next save goes gibberish for some reason? + //Recordset corruption probably, this fixes + + CSimpleWODlg qwo; + + qwo.SetWorkorderID(&temp); + if(qwo.DoModal()==IDOK) + { + m_pApp->m_bRefreshStatScreen=true; + FillView(); + } + +} + + + +void STAT::OnBtnprint() +{ + CString q,parameters,str; + if(dv.preview) + parameters="True AS zShowNotes, "; + else + parameters="False AS zShowNotes, "; + + str.Format("\"%s\" AS zCurrentUser, ",m_pApp->m_strCurrentUserName); + parameters = parameters + str; + + /*PRISTINE VERSION OF 1.9.3.0 query +q.Format("SELECT %s " + "IIf([wo].[anytime]=True,[wo].[created],[wo].[starttime]) AS cdate, probs.id AS PROBID, " + "probs.brief, probs.notes AS PROBDETAILS, wo.clientcontact, wo.notes AS wonotes, wo.invoice, " + "IIf(IsNull([company]),[clients]![last] & \", \" & [clients]![first],[company]) AS clientcompany, " + "wo.anytime, wo.starttime, wo.stoptime, users.initials, users_1.initials AS INIT2, " + "users_2.initials AS INIT3, users_3.initials AS INIT4, wo.created, wo.modified, wo.onsite, " + "wo.closed, wo.prob_found, wo.prob_reported, wo.action_taken, clients.postal, clients.city, " + "clients.technotes, clients.generalnotes, clients.acctnumber, zones.name AS zonename, wo.quick, " + "wo.id, wo.ourref, wo.clientrefnum, probstat.notes AS wostatus " +"FROM (((probs RIGHT JOIN (((((wo LEFT JOIN users ON wo.assigntech = users.id) LEFT JOIN " +"clients ON wo.client = clients.id) LEFT JOIN zones ON clients.czone = zones.id) LEFT JOIN " +"projects ON wo.project = projects.id) LEFT JOIN probstat ON wo.status = probstat.id) ON probs.wolink = wo.id) " +"LEFT JOIN users AS users_1 ON wo.assigntech2 = users_1.id) LEFT JOIN users AS users_2 " +"ON wo.assigntech3 = users_2.id) LEFT JOIN users AS users_3 ON wo.assigntech4 = users_3.id %s %s;",parameters, dv.sqlcriteria, dv.sqlorderby); + + */ + q.Format("SELECT %s " + "IIf([wo].[anytime]=True,[wo].[created],[wo].[starttime]) AS cdate, probs.id AS PROBID, " + "probs.brief, probs.notes AS PROBDETAILS, wo.clientcontact, wo.notes AS wonotes, wo.invoice, " + "IIf(IsNull([company]),[clients]![last] & \", \" & [clients]![first],[company]) AS clientcompany, " + "wo.anytime, wo.starttime, wo.stoptime, users.initials, users_1.initials AS INIT2, " + "users_2.initials AS INIT3, users_3.initials AS INIT4, wo.created, wo.modified, wo.onsite, " + "wo.closed, wo.prob_found, wo.prob_reported, wo.action_taken, clients.postal, clients.city, " + "clients.technotes, clients.generalnotes, clients.acctnumber, zones.name AS zonename, wo.quick, " + "wo.id, wo.ourref, wo.clientrefnum, probstat.notes AS wostatus " +"FROM wotypes RIGHT JOIN ((((probs RIGHT JOIN (((((wo LEFT JOIN users ON wo.assigntech = users.id) LEFT JOIN " + +"clients ON wo.client = clients.id) LEFT JOIN zones ON clients.czone = zones.id) LEFT JOIN " +"projects ON wo.project = projects.id) LEFT JOIN probstat ON wo.status = probstat.id) ON probs.wolink = wo.id) " +"LEFT JOIN users AS users_1 ON wo.assigntech2 = users_1.id) LEFT JOIN users AS users_2 " +"ON wo.assigntech3 = users_2.id) LEFT JOIN users AS users_3 ON wo.assigntech4 = users_3.id) ON wotypes.id=wo.type " +"%s %s;",parameters, dv.sqlcriteria, dv.sqlorderby); + + + + +#ifdef _DEBUG + m_pApp->ShowStuff(q); +#endif + + + + + rsPrint->Close(); + rsPrint->QueryReadOnly(q); + rsPrint->QueryReadOnly(q); + m_pApp->PrintCMReportRDC(dv.virtualreport,rsPrint->RecordSetPointer()); + #ifdef _DEBUG + m_pApp->CreateTTX("wostatus.ttx",rsPrint->RecordSetPointer()); +#endif + // + + DeActivate(); +} + + + +void STAT::Activate() +{ + +#ifdef _WTF_ + AfxMessageBox("STAT activate"); +#endif + rs=m_pApp->rsPool->GetRS("STAT RS"); + cbrs=m_pApp->rsPool->GetRS("STAT CBRS"); + brs=m_pApp->rsPool->GetRS("STAT brs"); + rsPrint=m_pApp->rsPool->GetRSPrint("STAT RSPRINT"); + + //AfxMessageBox("Activate"); + //ShowWindow(SW_MAXIMIZE); + + //if were supposed to refresh the stat screen then.. + + FillView(); + + //Hide add wo buttons if not allowed + int x=m_pApp->Allowed(RWORKORDER,true); + if(x!=1)//no write allowed + { + m_btnNewQWO.EnableWindow(FALSE); + m_btnNewSTWO.EnableWindow(FALSE); + } + + +} + +void STAT::DeActivate() +{ + //AfxMessageBox("Deactivate"); +#ifdef _WTF_ + AfxMessageBox("STAT activate"); +#endif + + //AfxMessageBox("STAT::DeActivate()"); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&cbrs->m_nID); + m_pApp->rsPool->ReleaseRS(&brs->m_nID); + m_pApp->rsPool->ReleaseRS(&rsPrint->m_nID); + //AfxMessageBox("DONE: STAT::DeActivate()"); + +} + +void STAT::OnBtneditwonum() +{ + + CString q; + CString strWO; + + + bool bquick; + m_edWONumber.GetWindowText(strWO); + if(strWO.IsEmpty()) return; + + + + q.Format("SELECT wo.quick FROM wo WHERE (((wo.id)=%s));",strWO); + cbrs->QueryReadOnly(q); + if(cbrs->IsEmpty()) + { + q.Format("There is no workorder %s",strWO); + AfxMessageBox(q); + DeActivate(); + return; + } + + cbrs->FetchField("quick",&bquick); + + cbrs->Close(); + + if(bquick) + { + CSimpleWODlg qwo; + qwo.SetWorkorderID(&strWO); + qwo.DoModal(); + + } + else + { + CWOHeaderDlg wo; + wo.SetWorkorderID(strWO); + wo.DoModal(); + + } + + FillView(); + + +} + +void STAT::OnBtnrefresh() +{ + + m_pApp->m_bRefreshStatScreen=true; + + FillView(); + +} + + + +void STAT::DoHelp() +{ + //AfxGetApp()->WinHelp(IDD_STAT_FORM); + + //AfxMessageBox("here's your help."); +} + +void STAT::OnBtnclientnotes() +{ + + CString strWorkorderID,q; + int x; + long lClient; + x=m_rc.GetFirstSelectedItem(); + if(x<0) + { + AfxMessageBox("No list item is selected"); + return;//no selection + } + + strWorkorderID=m_rc.GetItemText(x,11); + strWorkorderID.Remove('*'); + + q.Format("SELECT wo.client FROM wo " + "WHERE (((wo.id)=%s));",strWorkorderID); + + brs->Query(q); + if(brs->IsEmpty()) + { + AfxMessageBox("Can't locate a client for that workorder"); + DeActivate(); + return; + } + brs->FetchField("client",&lClient); + DeActivate(); + q.Format("%u",lClient); + + CContactsViewDlg d; + d.Setup(q); + d.DoModal(); + + +} + + + +void STAT::LayoutControls() +{ + + + + CRect rectCtl; + GetWindowRect(rectStat); + + + int nOffset=rectStat.top; + int nLastBottom,nRight,nLeft; + int nHeight,nWidth; + + + m_rc.GetWindowRect(rectCtl); + + rectCtl.right=rectStat.right-73; + rectCtl.top-=nOffset; + rectCtl.left=13; + rectCtl.bottom=rectStat.bottom-70-nOffset; + m_rc.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + nRight=rectCtl.right; + + + m_btnEditWO.GetWindowRect(rectCtl); + nWidth=rectCtl.Width(); + rectCtl.right=nRight; + rectCtl.left=nRight-nWidth; + rectCtl.top-=nOffset; + rectCtl.bottom-=nOffset; + m_btnEditWO.MoveWindow(rectCtl,TRUE); + + m_edWONumber.GetWindowRect(rectCtl); + nWidth=rectCtl.Width(); + rectCtl.right=nRight; + rectCtl.left=nRight-nWidth; + rectCtl.top-=nOffset; + rectCtl.bottom-=nOffset; + m_edWONumber.MoveWindow(rectCtl,TRUE); + nLeft=rectCtl.left; + + //set contact field to grow to the right + m_lblContactInfo.GetWindowRect(rectCtl); + //nWidth=rectCtl.Width(); + rectCtl.right=nLeft-5; + //rectCtl.left=nRight-nWidth; + rectCtl.top-=nOffset; + rectCtl.bottom-=nOffset; + m_lblContactInfo.MoveWindow(rectCtl,TRUE); + + + + + m_btnNewQWO.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom+25; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnNewQWO.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + + m_btnNewSTWO.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnNewSTWO.MoveWindow(rectCtl,TRUE); + + m_btnRefresh.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnRefresh.MoveWindow(rectCtl,TRUE); + + m_btnClientNotes.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnClientNotes.MoveWindow(rectCtl,TRUE); + + m_btnPrint.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnPrint.MoveWindow(rectCtl,TRUE); + +} + +void STAT::OnSize(UINT nType, int cx, int cy) +{ + CFormView::OnSize(nType, cx, cy); + if(cx>m_nCX)//to cut down on number of times called + { + m_nCX=cx; + if(m_btnPrint.m_hWnd) + { + LayoutControls(); + } + } +} + + + + +void STAT::OnMouseMove(UINT nFlags, CPoint point) +{ + if(m_bFreshStatsAwait) + { m_bFreshStatsAwait=false; + m_lblContactInfo.SetWindowText(m_strStats); + } + CFormView::OnMouseMove(nFlags, point); +} + + +// Fetches useful stats from database do display at top +//called by FillView when there is a refresh required in the view only +void STAT::GetStats(void) +{ + long lWOCount=0; + long lOpenCount=0; + if(rs->QueryReadOnly("SELECT Count(wo.id) AS WOCOUNT FROM wo;")) + { + + rs->FetchField("WOCOUNT",&lWOCount); + if(lWOCount<1) + { + m_strStats.Format("\t There are no work orders entered in AyaNova. Stats not available"); + m_bFreshStatsAwait=true; + return; + } + + if(rs->QueryReadOnly("SELECT Count(wo.id) AS OPENCOUNT FROM wo GROUP BY wo.closed HAVING (((wo.closed)=#3/12/1968#));")) + { + if(rs->IsEmpty()) + lOpenCount=0; + else + rs->FetchField("OPENCOUNT", &lOpenCount); + + } + + + } + m_strStats.Format("\t%u total workorders in AyaNova, %u are open",lWOCount,lOpenCount); + m_bFreshStatsAwait=true; + +} + +BOOL STAT::OnHelpInfo(HELPINFO* pHelpInfo) +{ +WinHelp (0x00020000 + IDD_STAT_FORM,HELP_CONTEXT); + return TRUE; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.h new file mode 100644 index 0000000..7e15811 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/STAT.h @@ -0,0 +1,150 @@ +#if !defined(AFX_STAT_H__B3971464_FC37_11D3_964F_00C0F02C4B69__INCLUDED_) +#define AFX_STAT_H__B3971464_FC37_11D3_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// STAT.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// STAT form view + +#ifndef __AFXEXT_H__ +#include +#endif + + +#include "reportctrl.h" +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +#include "GetStringDlg.h" +#include "DispatchView.h" +#include "WOHeaderDlg.h" +#include "SimpleWODlg.h" +#include "DispatchFieldsDlg.h" +//Last modified 07/30/2001 +//COLUMNMOD +#define STATCOLUMNCOUNT 20 + +class STAT : public CFormView +{ +public: + STAT(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(STAT) +BOOL bColumnSortAsc[STATCOLUMNCOUNT]; + bool FirstRun; + CString m_strQuery; + CString m_strSelectedView; + void FillViewList(); + void DisplayColumns(); + int m_nFldCount; + CDispatchView dv; + + + bool m_bShowDescription; + void FillView(); + + CSpApp* m_pApp; + CImageList m_ilReport; + void OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnRvnItemClick(NMHDR* pNMHDR, LRESULT* pResult); + void OnRvnItemDrawPreview(NMHDR* pNMHDR, LRESULT* pResult); + void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult); + //The Extra recordset is for filling combo boxes + GZRset* rs; + GZRset* cbrs; + GZRset* brs;//used for gathering briefs from woprobs + GZRset* rsPrint; + CStringList lsNotes; +// Form Data +public: + //{{AFX_DATA(STAT) + enum { IDD = IDD_STAT_FORM }; + CButton m_btnClientNotes; + CButton m_btnRefresh; + CButton m_btnNewSTWO; + CButton m_btnNewQWO; + CButton m_btnEditWO; + CButton m_btnPrint; + CLabel m_lblContactInfo; + CEdit m_edWONumber; + CgzCombo m_cbViews; + CLabel m_lblChooseDisplayFields; + CLabel m_lblSaveView; + CLabel m_lblDeleteView; + CReportCtrl m_rc; + //}}AFX_DATA +protected: + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(STAT) + public: + virtual void OnInitialUpdate(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +public: + + void DoHelp(); + + void DeActivate(); + void Activate(); + virtual ~STAT(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(STAT) + afx_msg void OnBtndone(); + afx_msg void OnLblsaveview(); + afx_msg void OnLbldeleteview(); + afx_msg void OnLblchoosefields(); + afx_msg void OnCloseupCbviews(); + afx_msg void OnBtnnewwo(); + afx_msg void OnBtnnewqwo(); + afx_msg void OnBtnprint(); + afx_msg void OnBtneditwonum(); + afx_msg void OnBtnrefresh(); + afx_msg void OnBtnclientnotes(); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + + int m_nCX; + CRect rectStat; + + void LayoutControls(); +public: + + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + // Fetches useful stats from database do display at top + void GetStats(void); + // true if there are new stats to display else false if none + bool m_bFreshStatsAwait; +private: + // Stats to display at top display area where address normally displays for clicked workorder item + CString m_strStats; +public: + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STAT_H__B3971464_FC37_11D3_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Scdata.sc b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Scdata.sc new file mode 100644 index 0000000000000000000000000000000000000000..127b7a5ea5bdd00ea7522bf0516bfb1ca0238ca1 GIT binary patch literal 2457600 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 Vfw4Ls?uzy(;}W=q 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%0D=F_%pocNuyjkC}syC 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%0DIx_0N^(x}v%yz&}*;1kMdx!Bwd3u9yNdP1H{2 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�M6h|>>K3Ip+jcouwtnhNe;X>fg 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%0Ay3s;)0LAiq(m^td7ZN5TNS40+1PFdB?L3H~ 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 CP5Z$B literal 0 HcmV?d00001 diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.cpp new file mode 100644 index 0000000..337b0e8 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.cpp @@ -0,0 +1,387 @@ +// SchedGrps.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "SchedGrps.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSchedGrps dialog + + +CSchedGrps::CSchedGrps(CWnd* pParent /*=NULL*/) +: CDialog(CSchedGrps::IDD, pParent) +, m_strSelectedGroup(_T("")) +{ + //{{AFX_DATA_INIT(CSchedGrps) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + //Initialize recordset pointer + rs=m_pApp->rsPool->GetRS("CSchedGrpsDlg"); + m_bAddMode=false; +} + +CSchedGrps::~CSchedGrps() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CSchedGrps::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSchedGrps) + DDX_Control(pDX, IDC_EDNAME, m_edName); + DDX_Control(pDX, IDC_CBTECHS, m_ckcbTechs); + DDX_Control(pDX, IDC_CBGROUP, m_cbGroups); + DDX_Control(pDX, IDC_BTNDONE, m_btnDone); + DDX_Control(pDX, IDC_BTNDELGRP, m_btnDelete); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSchedGrps, CDialog) +//{{AFX_MSG_MAP(CSchedGrps) +ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) +ON_BN_CLICKED(IDC_BTNDELGRP, OnBtndelgrp) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) +ON_CBN_CLOSEUP(IDC_CBGROUP, OnCloseupCbgroup) +ON_CBN_CLOSEUP(IDC_CBTECHS, OnCloseupCbtechs) + ON_EN_KILLFOCUS(IDC_EDNAME, OnKillfocusEdname) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSchedGrps message handlers + +BOOL CSchedGrps::OnInitDialog() +{ + CDialog::OnInitDialog(); + Security(); + FillTechList(); + FillGroups(); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + + +void CSchedGrps::OnOK() +{} + +void CSchedGrps::OnBtnadd() +{ + if(m_bAddMode)//user clicked on save + { + CString strData,q; + long lData; + m_edName.GetWindowText(strData); + if(strData.IsEmpty()) + { + AfxMessageBox("Name can't be blank"); + return; + } + + //Good to go... + q.Format("INSERT INTO schdgrps ( name ) SELECT \"%s\" AS Expr1;",strData); + rs->Ex(q,&lData); + m_strSelectedGroup.Format("%u",lData); + rs->Close(); + m_bAddMode=false; + m_btnDelete.SetWindowText("Delete"); + m_btnAdd.SetWindowText("Add"); + m_ckcbTechs.EnableWindow(TRUE); + m_btnDone.ShowWindow(TRUE); + m_cbGroups.EnableWindow(FALSE); + FillGroups(); + } + else//user clicked on ADD + { + m_ckcbTechs.SelectAll(FALSE); + m_bAddMode=true; + m_edName.SetWindowText(""); + m_edName.EnableWindow(TRUE); + m_btnAdd.SetWindowText("SAVE"); + m_btnDelete.SetWindowText("CANCEL"); + m_ckcbTechs.SetWindowText(""); + m_ckcbTechs.EnableWindow(FALSE); + m_btnDone.ShowWindow(FALSE); + m_cbGroups.EnableWindow(FALSE); + m_edName.SetFocus(); + } + +} + +void CSchedGrps::OnBtndelgrp() +{ + + if(m_bAddMode)//user clicked on cancel + { + + m_bAddMode=false; + m_btnDelete.SetWindowText("Delete"); + m_btnAdd.SetWindowText("Add"); + m_ckcbTechs.EnableWindow(TRUE); + m_btnDone.ShowWindow(TRUE); + m_cbGroups.EnableWindow(FALSE); + FillGroups(); + OnCloseupCbgroup(); + return; + } + + CString q,strGroup; + strGroup=m_cbGroups.GetCurrentRowID(); + //delete all schdets that match master id first + q.Format("DELETE schdets.*, schdets.grpid FROM schdets WHERE (((schdets.grpid)=%s));", + strGroup); + rs->Ex(q); + + //delete group itself + q.Format("DELETE schdgrps.*, schdgrps.id FROM schdgrps WHERE (((schdgrps.id)=%s));", + strGroup); + rs->Ex(q); + rs->Close(); + + FillGroups(); + +} + +void CSchedGrps::OnBtndone() +{ + CDialog::OnOK(); + +} + +void CSchedGrps::OnCloseupCbgroup() +{ + //if(m_strSelectedGroup==m_cbGroups.GetCurrentRowID()) return; + m_strSelectedGroup==m_cbGroups.GetCurrentRowID(); + m_edName.SetWindowText(m_cbGroups.GetCurrentRowText()); + UpdateSelections(); +} + +void CSchedGrps::OnCloseupCbtechs() +{ + SaveSelections(); + +} + +//Fill the list of techs +void CSchedGrps::FillTechList() +{ + CString strData; + m_ckcbTechs.SelectAll(FALSE); + //m_ckcbTechs.Clear(); + + rs->QueryReadOnly(strData="SELECT users.id, [last] & \", \" & [first] & \" id:\" & [id] AS name " + "FROM users " + "WHERE (((users.id)<>1) AND ((users.tech)=True)) " + "ORDER BY users.last;"); + + if(rs->IsEmpty()) + return; + + do{ + rs->FetchField("name",&strData); + m_ckcbTechs.AddString(strData); + + }while(rs->MoveForward()); + + +} + +void CSchedGrps::FillGroups() +{ + CString strData,strIndex; + long lData; + m_cbGroups.Clear(); + + rs->QueryReadOnly("SELECT schdgrps.name, schdgrps.id FROM schdgrps ORDER BY schdgrps.name;"); + if(rs->IsEmpty()) + { + m_btnDelete.EnableWindow(FALSE); + m_cbGroups.EnableWindow(FALSE); + m_edName.EnableWindow(FALSE); + m_ckcbTechs.EnableWindow(FALSE); + + return; + } + else + { + //if there is data then enable controls + if(!m_bReadOnly) + { + m_btnDelete.EnableWindow(TRUE); + m_cbGroups.EnableWindow(TRUE); + m_edName.EnableWindow(TRUE); + m_ckcbTechs.EnableWindow(TRUE); + } + } + + do{ + rs->FetchField("name",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbGroups.AddRow(strData,strIndex); + + }while(rs->MoveForward()); + + if(m_strSelectedGroup.IsEmpty()) + { + m_cbGroups.SetCurSel(0); + //m_strSelectedGroup=m_cbGroups.GetCurrentRowID(); + } + else + m_cbGroups.Select(m_strSelectedGroup); + + OnCloseupCbgroup(); +} + + + + +//update selected techs +void CSchedGrps::UpdateSelections() +{ + CString q,strTemp; + long lData; + long lCurrentTechID; + int i,nStart,nLength,nChars,nCount; + //int x=m_ckcbTechs.GetCount(); + + //clear all checks + m_ckcbTechs.SelectAll(FALSE); + + //cycle through all sched techs + q.Format("SELECT schdets.techid FROM schdets WHERE (((schdets.grpid)=%s));", + m_cbGroups.GetCurrentRowID()); + rs->QueryReadOnly(q); + if(rs->IsEmpty()) + return; + nCount=m_ckcbTechs.GetCount(); + //loop through all schdets records and ... + do{ + rs->FetchField("techid",&lData); + + //compare id's to checkcombo last characters after "ID:" + CString str, str2; + + for (i=0;i < nCount;i++) + { + m_ckcbTechs.GetLBText( i, strTemp ); + nLength=strTemp.GetLength(); + nStart=strTemp.ReverseFind(':'); + if(nStart!=-1) + { + nChars=nLength-nStart; + strTemp=strTemp.Right(nChars-1); + lCurrentTechID=atol(strTemp); + if(lCurrentTechID==lData) + { + m_ckcbTechs.SetCheck(i,TRUE); + break; + } + + } + } + + + }while(rs->MoveForward()); + + + +} + +//save selected techs +void CSchedGrps::SaveSelections() +{ + CString q,strTemp,strGroup; + int i,nStart,nLength,nChars,nCount; + + nCount=m_ckcbTechs.GetCount(); + strGroup=m_cbGroups.GetCurrentRowID(); + //delete all schdets that match master id first + q.Format("DELETE schdets.*, schdets.grpid FROM schdets WHERE (((schdets.grpid)=%s));", + strGroup); + rs->Ex(q); + + //then put in all the schdets from the list + + for (i=0;i < nCount;i++) + { + if(m_ckcbTechs.GetCheck(i)) + { + m_ckcbTechs.GetLBText( i, strTemp ); + nLength=strTemp.GetLength(); + nStart=strTemp.ReverseFind(':'); + if(nStart!=-1) + { + nChars=nLength-nStart; + strTemp=strTemp.Right(nChars-1); + + //insert into query + q.Format("INSERT INTO schdets ( grpid, techid ) " + "SELECT %s , %s;",strGroup,strTemp); + rs->Ex(q); + + } + } + } + +} + +void CSchedGrps::OnKillfocusEdname() +{ + if(m_bAddMode) return;//don't do this if adding a new record +//save new list name +CString q,strData, strIndex; + +m_edName.GetWindowText(strData); +strIndex=m_cbGroups.GetCurrentRowID(); + +if(strData.IsEmpty()) +{ + AfxMessageBox("Name can not be blank"); + return; +} + +q.Format("UPDATE schdgrps SET schdgrps.name = \"%s\" WHERE (((schdgrps.id)=%s));", + strData,strIndex); + +rs->Ex(q); +rs->Close(); +FillGroups(); +} + + + +void CSchedGrps::Security() +{ +m_bReadOnly=false; + int x=m_pApp->Allowed(RSCHEDGROUPS,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + + m_bReadOnly=true; + m_btnAdd.ShowWindow(FALSE); + m_btnDelete.ShowWindow(FALSE); + + m_edName.SetReadOnly(TRUE); + m_ckcbTechs.EnableWindow(FALSE); + + + + } +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.h new file mode 100644 index 0000000..00431d5 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SchedGrps.h @@ -0,0 +1,72 @@ +#if !defined(AFX_SCHEDGRPS_H__38B82B4B_3268_43D1_8515_CBA5FA723415__INCLUDED_) +#define AFX_SCHEDGRPS_H__38B82B4B_3268_43D1_8515_CBA5FA723415__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SchedGrps.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSchedGrps dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "checkcombobox.h" +class CSchedGrps : public CDialog +{ +// Construction +public: + bool m_bAddMode; + void SaveSelections(); + void UpdateSelections(); + void FillGroups(); + void FillTechList(); + ~CSchedGrps(); + CSchedGrps(CWnd* pParent = NULL); // standard constructor +CSpApp* m_pApp; +GZRset* rs; +// Dialog Data + //{{AFX_DATA(CSchedGrps) + enum { IDD = IDD_DLG_SCHED_GRPS }; + CEdit m_edName; + CCheckComboBox m_ckcbTechs; + CgzCombo m_cbGroups; + CButton m_btnDone; + CButton m_btnDelete; + CButton m_btnAdd; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSchedGrps) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSchedGrps) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnBtnadd(); + afx_msg void OnBtndelgrp(); + afx_msg void OnBtndone(); + afx_msg void OnCloseupCbgroup(); + afx_msg void OnCloseupCbtechs(); + afx_msg void OnKillfocusEdname(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + bool m_bReadOnly; + void Security(); +public: + CString m_strSelectedGroup; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SCHEDGRPS_H__38B82B4B_3268_43D1_8515_CBA5FA723415__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.cpp new file mode 100644 index 0000000..7780e5a --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.cpp @@ -0,0 +1,90 @@ +// Schedule.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "Schedule.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSchedule dialog + + +CSchedule::CSchedule(CWnd* pParent /*=NULL*/) +: CDialog(CSchedule::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSchedule) + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + rs=new GZRset("Error: Schedule screen"); + rs->SetConnect(m_pApp->strConnectString); +} + +CSchedule::~CSchedule() +{ + if(rs!=NULL) + delete rs; +} + +void CSchedule::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSchedule) + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSchedule, CDialog) +//{{AFX_MSG_MAP(CSchedule) +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSchedule message handlers + +BOOL CSchedule::OnInitDialog() +{ + CDialog::OnInitDialog(); + + ShowWindow(SW_MAXIMIZE); + m_sched.SetTitleText("Technician"); + //m_sched.SetRulerDays(TRUE); + + FillTechList(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CSchedule::FillTechList() +{ + CString q; + CString strData; + short x; + long lData; + 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;"; + rs->QueryReadOnly(q); + if(rs==NULL) + { + AfxMessageBox("There are no active technicians!"); + return; + + + } + + do { + rs->FetchField("fullname",&strData); + m_sched.AddItem(strData); + x=m_sched.GetListIndex(); + }while(rs->MoveForward()); + + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.h new file mode 100644 index 0000000..e76f716 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/Schedule.h @@ -0,0 +1,52 @@ +//{{AFX_INCLUDES() +#include "ctschedule.h" +//}}AFX_INCLUDES +#if !defined(AFX_SCHEDULE_H__9342C7A1_B94B_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_SCHEDULE_H__9342C7A1_B94B_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Schedule.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSchedule dialog +#include "gzrset.h" + +class CSchedule : public CDialog +{ +// Construction +public: + void FillTechList(); + ~CSchedule(); + CSchedule(CWnd* pParent = NULL); // standard constructor + GZRset* rs; + CSpApp* m_pApp; +// Dialog Data + //{{AFX_DATA(CSchedule) + enum { IDD = IDD_SCHEDULE }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSchedule) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSchedule) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SCHEDULE_H__9342C7A1_B94B_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.cpp new file mode 100644 index 0000000..4ad0bba --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.cpp @@ -0,0 +1,2105 @@ +// ScheduleFrm.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "ScheduleFrm.h" +#include "WOHeaderDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +//memory leak debugging help +#define _CRTDBG_MAP_ALLOC +#include +#include +#define MARTIN 1 +#define DAYSTOCACHE 15 +///////////////////////////////////////////////////////////////////////////// +// CScheduleFrm +/* +View scheduled workorders in the system visually + + Create new workorders by clicking and dragging a bar of time with the mouse + + Drag an existing workorder to a different time period + + Drag an existing workorder to a different technician + + Positioning the mouse over a time bar shows the client and workorder number at the top + + Double click on a time bar to open that workorder for editing + + View a day, week, two weeks or a month at a time + + Print the schedule as it appears onscreen (will print in color if your printer supports it) + + Change the start or end time of a workorder by clicking and dragging the ends of a time bar + + + +*/ +IMPLEMENT_DYNCREATE(CScheduleFrm, CFormView) + +CScheduleFrm::CScheduleFrm() +: CFormView(CScheduleFrm::IDD) +, m_bShowProblemDetailsInStatusDisplay(false) +{ + //{{AFX_DATA_INIT(CScheduleFrm) + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + m_dt1900.SetDate(1900,1,1); + m_nZoomFactor=60; + m_bRefresh=true; + m_bLayoutDone=false; + m_nTotalAllocated=0; + m_bTimerIsActive=false; + m_bZoneView=true; + +} + +CScheduleFrm::~CScheduleFrm() +{ + //KillTimer(1); + //ClearTimeBarObjects(); +} + +void CScheduleFrm::DoDataExchange(CDataExchange* pDX) +{ + CFormView::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CScheduleFrm) + DDX_Control(pDX, IDC_LBLZONE, m_lblZone); + DDX_Control(pDX, IDC_CBZONE, m_cbZone); + DDX_Control(pDX, IDC_BTNBACK, m_btnBack); + DDX_Control(pDX, IDC_BTNFORWARD, m_btnForward); + DDX_Control(pDX, IDC_BTNPRINT, m_btnPrint); + DDX_Control(pDX, IDC_LBLVIEW, m_lblView); + DDX_Control(pDX, IDC_LBLSTARTDATE, m_lblStartDate); + DDX_Control(pDX, IDC_BTNREFRESH, m_btnRefresh); + DDX_Control(pDX, IDC_CKLOCk, m_ckLock); + DDX_Control(pDX, IDC_RDWEEK, m_rdWeek); + DDX_Control(pDX, IDC_RDMONTH, m_rdMonth); + DDX_Control(pDX, IDC_RDDAY, m_rdDay); + DDX_Control(pDX, IDC_LBLWODETAILS, m_lblDetails); + DDX_Control(pDX, IDC_DTDATE, m_dtDate); + DDX_Control(pDX, IDC_CTSCHED, m_sc); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CScheduleFrm, CFormView) +//{{AFX_MSG_MAP(CScheduleFrm) +ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTDATE, OnDatetimechangeDtdate) +ON_BN_CLICKED(IDC_BTNPRINT, OnBtnprint) +ON_BN_CLICKED(IDC_BTNBACK, OnBtnback) +ON_BN_CLICKED(IDC_BTNFORWARD, OnBtnforward) +ON_BN_CLICKED(IDC_RDDAY, OnRdday) +ON_BN_CLICKED(IDC_RDMONTH, OnRdmonth) +ON_BN_CLICKED(IDC_RDWEEK, OnRdweek) +ON_BN_CLICKED(IDC_BTNREFRESH, OnBtnrefresh) +ON_BN_CLICKED(IDC_CKLOCk, OnCKLOCk) +ON_CBN_CLOSEUP(IDC_CBZONE, OnCloseupCbzone) +ON_WM_TIMER() +//}}AFX_MSG_MAP +ON_WM_HELPINFO() +ON_WM_DESTROY() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CScheduleFrm diagnostics + +#ifdef _DEBUG +void CScheduleFrm::AssertValid() const +{ + CFormView::AssertValid(); +} + +void CScheduleFrm::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CScheduleFrm message handlers + +void CScheduleFrm::Activate() +{ + + m_ulHighLightedBar=RGB(255,0,0); + m_ulStandardBar=RGB(0,0,255); + FillZoneList(); + FillView(); + if(!m_bTimerIsActive) + { + + //AUTOREFRESH TIMER + if(m_pApp->m_lSchedRefreshSecs!=0) + m_nTimer = SetTimer(1, 1000*m_pApp->m_lSchedRefreshSecs, 0); + //m_nTimer = SetTimer(1, 6000, 0); + + m_bTimerIsActive=true; + } +} + +void CScheduleFrm::DeActivate() +{ + KillTimer(1); + m_bTimerIsActive=false; + +} + +void CScheduleFrm::OnInitialUpdate() +{ + CFormView::OnInitialUpdate(); + m_lblDetails.SetFontName("MS Sans Serif"); + m_lblDetails.SetFontSize(8); + m_lblDetails.SetFontBold(FALSE); + m_lblDetails.SetTextColor(RGB(0,0,0)); + m_lblDetails.SetBkColor(RGB(255,255,255)); + + //performance stats + m_dLast=m_dFastest=m_dSlowest=m_dAverage=0; + m_uiRefreshCount=0; + + //start off with a day view + m_nDayWeekMonth=0;//0-day 1=week 2=Month shown in view + m_rdDay.SetCheck(TRUE); + m_ckLock.SetCheck(TRUE); + m_bLocked=true; + m_bUndoing=false; + //lock so that get time bar object won't change it because of another even somewhere + m_bUpdating=false; + //m_nBarStyleOverlapping=m_sc.AddBarStyle(8,-2);//<<<<<<<<<<<<m_lSchedWindowDays/2; + + + long lTechID,lWOID, lStatID, lDaysStart,lDaysEnd,lMinStart,lMinEnd; + + //time bar status stuff + CString strStatus,strWONOTES,strZoneQ; + long lRed,lGreen,lBlue; + + bool bActive,bFirstRunThrough,bContinue; + int count=0; + int nBar;//used for time bar colors to retrieve and set bar value + + //added 07/27/01 to accomodate multi-tech scheduled + long lThisTech; + bool bMatchingTech; + int nTech; + int nMatchingTechNumber; + + + bFirstRunThrough=true;//used to show non-assigned items + + //flag used by OnItemMove... to indicate that nothing was + //ever highlighted before + m_nOldIndex=m_nOldBar=0; + + //Get the date from the control + m_dtDate.GetTime(dtStart); + + //set the default fore text to white to contrast with + //every likely color + m_sc.SetBarDefForeColor(RGB(255,255,255)); + //set time scroll value to something past the possible values + //this is used to determine the earliest date in the schedule + //and thus, scroll the schedule to it automatically + //a thousand years give or take oughta do... + dtTimeScrollStart.SetDate(3000,1,1); + //dtTimeScrollStart=COleDateTime::GetCurrentTime(); + + m_sc.SetBarDefBackColor(m_ulStandardBar); + //m_sc.SetTimeStart(); + + + //if it's not a forced refresh, see if it's within the window + if(!m_bRefresh) + { + if(dtStart > m_dtWindowStop || dtStart < m_dtWindowStart) + { + m_bRefresh=true; + dtSpan.SetDateTimeSpan(lWindowSize,0,0,0); + m_dtWindowStart=dtStart-dtSpan; + m_dtWindowStop=dtStart+dtSpan; + + + + + } + + } + else + { + dtSpan.SetDateTimeSpan(lWindowSize,0,0,0); + m_dtWindowStart=dtStart-dtSpan; + m_dtWindowStop=dtStart+dtSpan; + + } + //***************************************************************** + + + //******************************************************* + //Clear the previous schedule if any + if(m_bRefresh) + { + m_sc.ClearSchedule(); + //added 07/27/01 to account for changes to sched markers + m_sc.ClearColorBars(); + ClearTimeBarObjects(); + } + //******************************************************** + + + + //Set the zoom factor in the control + //hours or days (maybe weeks...who knows?) + if(m_nDayWeekMonth==0) + { + m_sc.SetWeekends(0); + m_sc.SetTimeType(0);//0=hours,1=days,2=weeks + m_sc.SetTimeDistance(m_nZoomFactor); + m_sc.SetPrintTimeDistance(m_nZoomFactor); + m_sc.SetBarTipSize(5);//5 is default + m_sc.SetBarTipExtension(5); + + m_sc.SetRulerDivisions(4); + + } + else + { + m_sc.SetWeekends(65); + m_sc.SetTimeType(1); + m_sc.SetRulerDivisions(0); + m_sc.SetTimeDistance(75); + m_sc.SetPrintTimeDistance(75); + m_sc.SetBarTipSize(-200);//5 is default + m_sc.SetBarTipExtension(-200); + + + } + + + dtEnd=dtStart+dtSpan; + + //Set the start and end dates in the control + + + //start date days since 1900 + + dtSpan=m_dtWindowStart-m_dt1900; + lDaysStart=(long)dtSpan.GetTotalDays(); + + //end date days since 1900 + dtSpan=m_dtWindowStop-m_dt1900; + lDaysEnd=(long)dtSpan.GetTotalDays(); + + m_sc.SetDateStart(lDaysStart); + m_sc.SetDateEnd(lDaysEnd); + + + + //read from the database if it's a refresh situation + if(m_bRefresh) + { + CWaitCursor cw; + + //Start timing here + m_uiRefreshCount++; + + + + + + m_bRefresh=false; + //Initialize recordset pointer + pTimerSQL.Start(TRUE); + rs=m_pApp->rsPool->GetRS("CScheduleFrm::FillView (RS)"); + rs2=m_pApp->rsPool->GetRS("CScheduleFrm::FillView (RS2)"); + rs3=m_pApp->rsPool->GetRS("CScheduleFrm::FillView (RS3)"); + pTimerSQL.Stop(); + + + + + + + + //If by zone..... + if(m_bZoneView) + { + //SELECT USERS BY ZONE + strZoneQ=m_cbZone.GetCurrentRowID(); + if(strZoneQ=="0") + strZoneQ.Empty(); + else + { + strZoneQ.Format("AND ((users.defzone)=%s)",m_cbZone.GetCurrentRowID()); + + } + + q.Format("SELECT users.id, users.active, [last] & \", \" & [first] AS fullname FROM users " + "WHERE (((users.id)<>1) AND ((users.tech)=True) %s ) " + "ORDER BY users.last;",strZoneQ); + } + //------------------------------------------------------------------------------------------- + else + { + //else if by group + //SELECT USERS BY GROUP + strZoneQ=m_cbZone.GetCurrentRowID(); + q.Format("SELECT users.id, users.active, [last] & \", \" & [first] AS fullname " + "FROM schdets LEFT JOIN users ON schdets.techid = users.id " + "WHERE (((schdets.grpid)=%s) AND ((users.tech)=True) AND ((users.id)<>1)) " + "ORDER BY users.last;",strZoneQ); + + + } + //------------------------------------------------------------------------------------------- + + + + pTimerSQL.Start(FALSE); + rs->QueryReadOnly(q); + pTimerSQL.Stop(); + if(rs->IsEmpty()) + { + //AfxMessageBox("There are no technicians for this zone"); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs2->m_nID); + m_pApp->rsPool->ReleaseRS(&rs3->m_nID); + //don't bother updatnig timer + return; + + + } + bContinue=true; + + + do { + if(bFirstRunThrough) + { + strData="To be assigned"; + lTechID=0; + bActive=true; + bFirstRunThrough=false; + } + else + { + pTimerSQL.Start(FALSE); + rs->FetchField("fullname",&strData); + rs->FetchField("id",&lTechID); + rs->FetchField("active",&bActive); + pTimerSQL.Stop(); + bContinue=rs->MoveForward(); + } + m_sc.AddItem(strData); + strData.Format("%u",lTechID); + m_sc.SetListCargo(count+1,strData); + count++; + + if(!bActive) + { + m_sc.SetListReadOnly((short)count,TRUE); + m_sc.SetListItemBackColor((short)count,(unsigned long)RGB(128,128,128));// dark gray + + } + else + m_sc.SetListItemBackColor((short)count,(unsigned long)RGB(255,255,255));//white + + + + + + //********************************************** + //********* SHOW TECH TIME OFF BARS ************ + //********* Added 07/24/2001 ******************* + //********************************************** + //FIND ALL ITEMS FOR THIS TECH BETWEEN + //m_dtWindowStart and m_dtWindowEnd + //And then insert time bar in the m_nBarStyleTimeOff style + //********************************************** + if(lTechID!=0) + { + q.Format("SELECT schedmarkers.startdate, schedmarkers.enddate, schedmarkers.notes, schedmarkers.red, schedmarkers.green, schedmarkers.blue " + "FROM schedmarkers " + "WHERE (((schedmarkers.link)=%u) AND " + "((schedmarkers.startdate) Between #%s# And #%s#));",lTechID, + m_dtWindowStart.Format(_T("%m/%d/%Y %H:%M:%S")),m_dtWindowStop.Format(_T("%m/%d/%Y %H:%M:%S"))); + + //m_pApp->ShowStuff(q); + + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty()) + { + do { + rs2->FetchField("notes",&strData); + rs2->FetchField("startdate",&dtSchedStart); + rs2->FetchField("enddate",&dtSchedEnd); + rs2->FetchField("red",&lRed); + rs2->FetchField("green",&lGreen); + rs2->FetchField("blue",&lBlue); + + //start date days since 1900 + dtSpan=dtSchedStart-m_dt1900; + lDaysStart=(long)dtSpan.GetTotalDays();//<---********** + + //end date days since 1900 + dtSpan=dtSchedEnd-m_dt1900; + lDaysEnd=(long)dtSpan.GetTotalDays();//<---------************ + + //Start time minutes since midnight + //set dttemp to 1 second after midnight + dtTemp.SetDateTime( + dtSchedStart.GetYear(), + dtSchedStart.GetMonth(), + dtSchedStart.GetDay(),0,0,0); + dtSpan=dtSchedStart-dtTemp; + lMinStart = (long) dtSpan.GetTotalMinutes();//<---********** + + //q.Format("Start time:%s Midnight:%s, minutes:%u",dtSchedStart.Format(),dtTemp.Format(),lMinStart); + //AfxMessageBox(q); + //End time hours since midnight + //set dttemp to 1 second after midnight + dtTemp.SetDateTime( + dtSchedEnd.GetYear(), + dtSchedEnd.GetMonth(), + dtSchedEnd.GetDay(),0,0,0); + dtSpan=dtSchedEnd-dtTemp; + lMinEnd = (long) dtSpan.GetTotalMinutes();//<-------********* + + //Insert the bar + nBar=m_sc.AddKeyTimeBar(count,lMinStart,lMinEnd,lDaysStart,lDaysEnd,"off");//all off hours have cargo text id value of off + m_sc.SetBarText(count,nBar,strData);//set text as specified in schedmarker record + m_sc.SetBarBackColor(count,nBar,RGB(lRed,lGreen,lBlue));//set back color + + m_sc.SetBarForeColor(count,nBar,RGB(0,0,0));//set text black + //m_sc.SetBarTextAlign(count,nBar,2);//set to centered text + m_sc.SetBarStyle(count,nBar,m_nBarStyleTimeOff);//set to the style for off hours defined in initinstance + + }while(rs2->MoveForward()); + + + } + + + }//endif techid<>0 + else//tech ID is zero so here is where the milestone bar should go if it's a full day back color (shop closed etc) + { + //********************************************** + //********* SET SHOP CLOSED DAYS *************** + //********************************************** + //FIND ALL ITEMS BETWEEN m_dtWindowStart and m_dtWindowEnd + + //And then use the m_sc.AddColorBar to color the background + + //link=0 because non-zero means a tech time off and zero means whole office + //closed + //********************************************** + q.Format("SELECT schedmarkers.startdate, schedmarkers.enddate, schedmarkers.notes, schedmarkers.red, schedmarkers.green, schedmarkers.blue " + "FROM schedmarkers " + "WHERE (((schedmarkers.link)=0) AND " + "((schedmarkers.startdate) Between #%s# And #%s#));", + m_dtWindowStart.Format(_T("%m/%d/%Y 0:0:0")),m_dtWindowStop.Format(_T("%m/%d/%Y 23:59:59"))); + + //m_pApp->ShowStuff(q); + + rs2->QueryReadOnly(q); + if(!rs2->IsEmpty()) + { + do { + rs2->FetchField("notes",&strData); + rs2->FetchField("startdate",&dtSchedStart); + rs2->FetchField("enddate",&dtSchedEnd); + rs2->FetchField("red",&lRed); + rs2->FetchField("green",&lGreen); + rs2->FetchField("blue",&lBlue); + + + //start date days since 1900 + dtSpan=dtSchedStart-m_dt1900; + lDaysStart=(long)dtSpan.GetTotalDays();//<---********** + + //end date days since 1900 + dtSpan=dtSchedEnd-m_dt1900; + lDaysEnd=(long)dtSpan.GetTotalDays();//<---------************ + + //Start time minutes since midnight + //set dttemp to 1 second after midnight + dtTemp.SetDateTime( + dtSchedStart.GetYear(), + dtSchedStart.GetMonth(), + dtSchedStart.GetDay(),0,0,0); + dtSpan=dtSchedStart-dtTemp; + lMinStart = (long) dtSpan.GetTotalMinutes();//<---********** + + //q.Format("Start time:%s Midnight:%s, minutes:%u",dtSchedStart.Format(),dtTemp.Format(),lMinStart); + //AfxMessageBox(q); + //End time hours since midnight + //set dttemp to 1 second after midnight + dtTemp.SetDateTime( + dtSchedEnd.GetYear(), + dtSchedEnd.GetMonth(), + dtSchedEnd.GetDay(),0,0,0); + dtSpan=dtSchedEnd-dtTemp; + lMinEnd = (long) dtSpan.GetTotalMinutes();//<-------********* + + //Insert the backcolor as appropriate + m_sc.AddColorBar(lMinStart,lMinEnd,lDaysStart,lDaysEnd,RGB(lRed,lGreen,lBlue)); + //Insert the bar + nBar=m_sc.AddKeyTimeBar(count,lMinStart,lMinEnd,lDaysStart,lDaysEnd,"off");//all off hours have cargo text id value of off + m_sc.SetBarText(count,nBar,strData);//set text as specified in schedmarker record + //m_sc.SetBarBackColor(count,nBar,RGB(255,128,0));//set back orange + + m_sc.SetBarForeColor(count,nBar,RGB(0,0,0));//set text black + //m_sc.SetBarTextAlign(count,nBar,2);//set to centered text + //m_sc.SetBarTextWrap(TRUE); + m_sc.SetBarStyle(count,nBar,m_nBarStyleAllDayText);//set to the style for off hours defined in initinstance + + + }while(rs2->MoveForward()); + + + }//endif !rs2 empty + + }//endif ltechid=0 (not assigned) + //************************************************ + + + + + + + + + //Fill view + //Modified 07/26/01 - added the wotech 2,3,4 in OR statement all else the same + //PROBLEM: START TIMES SHOULD BE FOR EACH TECH SEPARATELY. + //LIKE THIS: + /* + SELECT wo.id, wo.assigntech, wo.starttime, wo.stoptime, wo.assigntech2, wo.starttime2, wo.stoptime2, wo.assigntech3, wo.starttime3, wo.stoptime3, wo.assigntech4, wo.starttime4, wo.stoptime4, wo.notes, clients.company, clients.last, clients.first, clients.bizphone, probstat.notes AS thestatus, projects.name AS projectname + FROM wotypes RIGHT JOIN ((probstat RIGHT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON probstat.id = wo.status) LEFT JOIN projects ON wo.project = projects.id) ON wotypes.id = wo.type + WHERE (((wo.anytime)=False) AND ((wo.closed)=#3/12/1968#) AND ((wo.quick)=False)) AND + + ( (((wo.assigntech)=2) AND ((wo.starttime) Between #7/1/2001# And #9/1/2001 23:59:59#)) OR + (((wo.assigntech2)=2) AND ((wo.starttime2) Between #7/1/2001# And #9/1/2001 23:59:59#)) OR + (((wo.assigntech3)=2) AND ((wo.starttime3) Between #7/1/2001# And #9/1/2001 23:59:59#)) OR + (((wo.assigntech4)=2) AND ((wo.starttime4) Between #7/1/2001# And #9/1/2001 23:59:59#)) ) + ORDER BY wo.assigntech; + + + */ + /* + q.Format("SELECT wo.id, wo.anytime, " + "wo.assigntech, wo.starttime, wo.stoptime, " + "wo.assigntech2, wo.starttime2, wo.stoptime2, " + "wo.assigntech3, wo.starttime3, wo.stoptime3, " + "wo.assigntech4, wo.starttime4, wo.stoptime4, " + "wo.notes, wo.closed, clients.company, clients.last, clients.first, probstat.id as statid, probstat.red, probstat.green, probstat.blue, probstat.notes as thestatus, projects.name AS projectname " + "FROM (probstat RIGHT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON probstat.id = wo.status) LEFT JOIN projects ON wo.project = projects.id " + "WHERE (((wo.starttime) Between #%s# And #%s#) AND ((wo.quick)=False) AND ((wo.anytime)=False) AND ((wo.assigntech)=%u) OR ((wo.assigntech2)=%u) OR ((wo.assigntech3)=%u) OR ((wo.assigntech4)=%u)) " + "ORDER BY wo.assigntech;",m_dtWindowStart.Format(_T("%m/%d/%Y 0:0:0")),m_dtWindowStop.Format(_T("%m/%d/%Y 23:59:59")),lTechID,lTechID,lTechID,lTechID); + */ + + CString strSTART=m_dtWindowStart.Format(_T("%m/%d/%Y 0:0:0")); + CString strSTOP=m_dtWindowStop.Format(_T("%m/%d/%Y 23:59:59")); + q.Format("SELECT wo.id, wo.anytime, " + "wo.assigntech, wo.starttime, wo.stoptime, " + "wo.assigntech2, wo.starttime2, wo.stoptime2, " + "wo.assigntech3, wo.starttime3, wo.stoptime3, " + "wo.assigntech4, wo.starttime4, wo.stoptime4, " + "wo.notes, wo.closed, clients.company, clients.bizphone, clients.last, clients.first, probstat.id as statid, probstat.red, probstat.green, probstat.blue, probstat.notes as thestatus, projects.name AS projectname " + "FROM (probstat RIGHT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON probstat.id = wo.status) LEFT JOIN projects ON wo.project = projects.id " + "WHERE (((wo.quick)=False) AND ((wo.anytime)=False)) AND " + + "( (((wo.assigntech)=%u) AND ((wo.starttime) Between #%s# And #%s#)) OR " + "(((wo.assigntech2)=%u) AND ((wo.starttime2) Between #%s# And #%s#)) OR " + "(((wo.assigntech3)=%u) AND ((wo.starttime3) Between #%s# And #%s#)) OR " + "(((wo.assigntech4)=%u) AND ((wo.starttime4) Between #%s# And #%s#)) );", + //"ORDER BY wo.assigntech;", + + lTechID,strSTART,strSTOP, + lTechID,strSTART,strSTOP, + lTechID,strSTART,strSTOP, + lTechID,strSTART,strSTOP + + ); + +#ifdef _DEBUG + //m_pApp->ShowStuff(q); +#endif + + + + //*********************************************************************************** + + + //************************************************************************************ + pTimerSQL.Start(FALSE); + rs2->QueryReadOnly(q); + pTimerSQL.Stop(); + if(!rs2->IsEmpty()) + { + do{ + + + + pTimerSQL.Start(FALSE); + rs2->FetchField("projectname",&strProjectName); + rs2->FetchField("statid",&lStatID); + rs2->FetchField("red",&lRed); + rs2->FetchField("green",&lGreen); + rs2->FetchField("blue",&lBlue); + rs2->FetchField("thestatus",&strStatus); + rs2->FetchField("notes",&strWONOTES); + +#ifdef _DEBUG + rs2->FetchField("anytime",&bMatchingTech); + ASSERT (bMatchingTech==false); +#endif + + + rs2->FetchField("id",&lWOID); + strWOID.Format("%u",lWOID); + rs2->FetchField("company",&strClient); + rs2->FetchField("bizphone",&strTemp); + strData.Format("%s %s",strClient,strTemp); + strClient=strData; + pTimerSQL.Stop(); + + //START OF 4 TIMES LOOP + //Pick out each incident for this tech and insert a time bar for each one + for(nTech=0;nTech<4;nTech++) + { + + bMatchingTech=false; + nMatchingTechNumber=0; + + /*if(lWOID==67) + lThisTech=-2;*/ + + switch (nTech) + { + case 0: + rs2->FetchField("assigntech",&lThisTech); + if(lThisTech==lTechID) + { + bMatchingTech=true; + nMatchingTechNumber=1; + rs2->FetchField("starttime",&dtSchedStart); + rs2->FetchField("stoptime",&dtSchedEnd); + } + break; + case 1: + rs2->FetchField("assigntech2",&lThisTech); + if(lThisTech==lTechID) + { + bMatchingTech=true; + nMatchingTechNumber=2; + rs2->FetchField("starttime2",&dtSchedStart); + rs2->FetchField("stoptime2",&dtSchedEnd); + } + break; + case 2: + rs2->FetchField("assigntech3",&lThisTech); + if(lThisTech==lTechID) + { + bMatchingTech=true; + nMatchingTechNumber=3; + rs2->FetchField("starttime3",&dtSchedStart); + rs2->FetchField("stoptime3",&dtSchedEnd); + } + break; + case 3: + rs2->FetchField("assigntech4",&lThisTech); + if(lThisTech==lTechID) + { + bMatchingTech=true; + nMatchingTechNumber=4; + rs2->FetchField("starttime4",&dtSchedStart); + rs2->FetchField("stoptime4",&dtSchedEnd); + } + break; + } + + if(bMatchingTech) + { + //calculate weird days and minutes + //timebars are set based on days since + //jan 1 1900 and time is based on + //minutes since midnight. + //lDaysStart,lDaysEnd,lMinStart,lMinEnd; + + //start date days since 1900 + dtSpan=dtSchedStart-m_dt1900; + lDaysStart=(long)dtSpan.GetTotalDays(); + + //end date days since 1900 + dtSpan=dtSchedEnd-m_dt1900; + lDaysEnd=(long)dtSpan.GetTotalDays(); + + //Start time minutes since midnight + //set dttemp to 1 second after midnight + dtTemp.SetDateTime( + dtSchedStart.GetYear(), + dtSchedStart.GetMonth(), + dtSchedStart.GetDay(),0,0,0); + dtSpan=dtSchedStart-dtTemp; + lMinStart = (long) dtSpan.GetTotalMinutes(); + + //q.Format("Start time:%s Midnight:%s, minutes:%u",dtSchedStart.Format(),dtTemp.Format(),lMinStart); + //AfxMessageBox(q); + //End time hours since midnight + //set dttemp to 1 second after midnight + dtTemp.SetDateTime( + dtSchedEnd.GetYear(), + dtSchedEnd.GetMonth(), + dtSchedEnd.GetDay(),0,0,0); + dtSpan=dtSchedEnd-dtTemp; + lMinEnd = (long) dtSpan.GetTotalMinutes(); + + + //q.Format("End time: time:%s midnight:%s, Minutes:%u",dtSchedEnd.Format(),dtTemp.Format(),lMinEnd); + //AfxMessageBox(q); + + //Insert the time bar + + if(!strStatus.IsEmpty()) + strStatus=" Status: " + strStatus; + + if(!strProjectName.IsEmpty()) + strProjectName=", PROJECT: " + strProjectName; + + if(m_bShowProblemDetailsInStatusDisplay) + { + strTemp.Format("SELECT probs.brief FROM probs WHERE (((probs.wolink)=%u) " + "AND ((probs.brief) Is Not Null));",lWOID); + if(rs3->QueryReadOnly(strTemp)) + { + if(!rs3->IsEmpty()) + { + strWONOTES+="\r\n"; + nCounter=0; + do{ + if(rs3->FetchField("brief",&strTemp)) + { + nCounter++; + strData.Format("%u) %s, ",nCounter,strTemp); + strWONOTES+=strData; + } + + }while(rs3->MoveForward()); + strWONOTES.TrimRight(' '); + strWONOTES.TrimRight(','); + + } + + } + + } + + //strData.Format("%s - workorder #:%u, Tech#:%i, %s%s\r\n%s",strClient,lWOID, nMatchingTechNumber, strStatus,strProjectName, strWONOTES); + strData.Format("%s - WO %u, Tech %i, %s%s, Notes: %s",strClient,lWOID, nMatchingTechNumber, strStatus,strProjectName, strWONOTES); + //strStatus.Format("%u",lWOID);//original value without tech number + strStatus.Format("%u,%i",lWOID,nMatchingTechNumber); + nBar=m_sc.AddKeyTimeBar(count,lMinStart,lMinEnd,lDaysStart,lDaysEnd,strStatus); + m_sc.SetBarBackColor(count,nBar,RGB(lRed,lGreen,lBlue)); + + + //flag overlapping bars + if(m_sc.FindFirstBar(count,nBar,count)>0) + m_sc.SetBarStyle(count,nBar,m_nBarStyleOverlapping); + + + /*************************///allocate and store a new timebar data object + m_ptbData=new CScheduleTimeBarData; + m_ptbData->m_lStatus=lStatID; + m_ptbData->m_lWOID=lWOID; + m_ptbData->m_lDateEnd=lDaysEnd; + m_ptbData->m_lDateStart=lDaysStart; + m_ptbData->m_lTimeEnd=lMinEnd; + m_ptbData->m_lTimeStart=lMinStart; + m_ptbData->m_lTechID=lTechID; + + //added o7/27/01 to accomodate multitech situation + m_ptbData->m_nTechNumber=nMatchingTechNumber; + + m_ptbData->m_strDisplayData=strData;//from above + m_ptbData->m_nID=arBar.Add(m_ptbData); + m_nTotalAllocated++; + + + }//end of ifbmatchingtech + + //pTimerSQL.Start(TRUE); + + //pTimerSQL.Stop(); + }//END OF 4 TECHS FOR NEXT LOOP HERE + }while(rs2->MoveForward()); + } + + }while(bContinue); + + //release the recordsets no longer needed + pTimerSQL.Start(FALSE); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&rs2->m_nID); + m_pApp->rsPool->ReleaseRS(&rs3->m_nID); + pTimerSQL.Stop(); + + //********************************************* + //end of if(m_bRefresh...check + + }//if brefresh + + + //--------------------------------------------------------------- + //GET TIMING STATS + //stop timer + pTimerSQL.Stop(); + pTimer.Stop();//overall timer + //get this time in ms + m_dLast=pTimerSQL.Elapsed(); + m_dOverallTime=pTimer.Elapsed(); + + + //add to average time + m_dAverage+=m_dLast; + + //set lowest time + if(m_dLast>m_dSlowest || m_dSlowest==0) + m_dSlowest=m_dLast; + + //set fastest time + if(m_dLastm_bDefSchedOneDay) + { + m_sc.SetDateStart(lDaysStart); + m_sc.SetDateEnd(lDaysStart); + } + } + //scroll over... + m_sc.TimeScroll(lDaysStart,m_lUserStartHour*60); + + m_sc.ReDraw(FALSE); + + + + +} + + + + + + + + + + + + + + +void CScheduleFrm::OnDatetimechangeDtdate(NMHDR* pNMHDR, LRESULT* pResult) +{ + FillView(); + *pResult = 0; +} + + + + + +void CScheduleFrm::OnBtnprint() +{ + + + long lStart,lEnd; + COleDateTime dtToday; + COleDateTimeSpan dtSpan; + + //Get the date from the control + m_dtDate.GetTime(dtToday); + + dtSpan=dtToday-m_dt1900; + lStart=(long)dtSpan.GetTotalDays(); + + //end date days since 1900 + dtSpan=dtToday-m_dt1900; + lEnd=(long)dtSpan.GetTotalDays(); + + m_sc.SetDateStart(lStart); + m_sc.SetDateEnd(lEnd); + + m_sc.PrintSchedule(); + + FillView(); + +} + +BEGIN_EVENTSINK_MAP(CScheduleFrm, CFormView) +//{{AFX_EVENTSINK_MAP(CScheduleFrm) +ON_EVENT(CScheduleFrm, IDC_CTSCHED, 16 /* ItemMove */, OnItemMoveCtsched, VTS_I2 VTS_I2) +ON_EVENT(CScheduleFrm, IDC_CTSCHED, 4 /* BarDblClick */, OnBarDblClickCtsched, VTS_I2 VTS_I2) +ON_EVENT(CScheduleFrm, IDC_CTSCHED, 14 /* BarSizing */, OnBarSizingCtsched, VTS_I2 VTS_I2 VTS_I2 VTS_I4 VTS_I4 VTS_I4 VTS_I4) +ON_EVENT(CScheduleFrm, IDC_CTSCHED, 13 /* BarChanged */, OnBarChangedCtsched, VTS_I2 VTS_I2 VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4) +ON_EVENT(CScheduleFrm, IDC_CTSCHED, 8 /* BarAdded */, OnBarAddedCtsched, VTS_I2 VTS_I2 VTS_BOOL VTS_BOOL) +ON_EVENT(CScheduleFrm, IDC_CTSCHED, 2 /* BarRightClick */, OnBarRightClickCtsched, VTS_I2 VTS_I2) +//}}AFX_EVENTSINK_MAP +END_EVENTSINK_MAP() + + + +//MOUSE OVER +void CScheduleFrm::OnItemMoveCtsched(short nIndex, short nBar) +{ + //do nothing if in the middle of an update + if(m_bUpdating) return; + + //in the process of an adjustment? + if(!m_bLocked) + return; + + //not a time bar? + if(nBar==0) return; + //same time bar as last time? + //if((nBar==m_nOldBar) && (nIndex==m_nOldIndex)) return; + + /* + if(m_nOldBar!=0) + m_sc.SetBarText(m_nOldIndex,m_nOldBar,""); + */ + + //m_nOldIndex=nIndex; + // m_nOldBar=nBar; + //m_sc.SetBarText(nIndex,nBar,"*"); + + + + + //sets the public m_ptbData pointer to the correct record + GetTimeBarObject(nIndex,nBar); + + //Bring to front to help with overlapping issue + m_sc.BringToFront(nIndex,nBar); + + if(m_ptbData!=NULL) + m_lblDetails.SetWindowText(m_ptbData->m_strDisplayData); +} + + +//open the workorder just double clicked +void CScheduleFrm::OnBarDblClickCtsched(short nIndex, short nBar) +{ + CString strWOID; + //strWOID=GetWoIDFromTimeBar(nIndex,nBar); + + //sets the public m_ptbData pointer to the correct record + GetTimeBarObject(nIndex,nBar); + if(m_ptbData==NULL) + return; + + strWOID.Format("%u",m_ptbData->m_lWOID); + + /* + strWOID=m_sc.GetBarKeyID(nIndex,nBar); + if(strWOID=="off") return; + */ + CWOHeaderDlg wo; + wo.SetWorkorderID(strWOID); + m_bUpdating=true; + wo.DoModal(); + + FillView(); + m_bRefresh=true; + FillView(); + m_bUpdating=false; + +} + + +//show detailed times in top area to make +//adjustments easier while moving or sizing a time bar +void CScheduleFrm::OnBarSizingCtsched(short nIndex, short nBar, short nType, long lTimeStart, long lTimeEnd, long lDateStart, long lDateEnd) +{ + + //do nothing if in the middle of an update + if(m_bUpdating) return; + + COleDateTime dtStart, dtEnd; + COleDateTimeSpan dtSpan; + CString q; + + //convert start time + dtSpan.SetDateTimeSpan(lDateStart,0,lTimeStart,0); + dtStart=m_dt1900+dtSpan; + + //convert end time + dtSpan.SetDateTimeSpan(lDateEnd,0,lTimeEnd,0); + dtEnd=m_dt1900+dtSpan; + + + q.Format("%s -> %s",dtStart.Format(VAR_TIMEVALUEONLY), + dtEnd.Format(VAR_TIMEVALUEONLY), + m_sc.GetBarKeyID(nIndex,nBar)); //VAR_TIMEVALUEONLY + + m_lblDetails.SetWindowText(q); + +} + + +//Take a Schedule long date and long time value +//set passed OleDateTime variable accordingly + +void CScheduleFrm::SchedToOleDT(long lSchedDateValue, long lSchedTimeValue, COleDateTime *dt) +{ + COleDateTimeSpan dtSpan; + dtSpan.SetDateTimeSpan(lSchedDateValue,0,lSchedTimeValue,0); + *dt=m_dt1900+dtSpan; + +} + + + +//update the time and date and technician for this workorder +//THIS FUNCTION NOW OBSOLETE (RIGHT CLICK REPLACES IT) +//AND KEPT ONLY UNTIL CONFIRMED NOT REQUIRED +//FOR SOME OTHER REASON IN FUTURE +void CScheduleFrm::OnBarChangedCtsched(short nIndex, short nBar, LPCTSTR cKeyID, long lTimeStart, long lTimeEnd, long lDateStart, long lDateEnd) +{ + //BUGBUG; //this routine is not working with new multi-tech changes + if(m_bUndoing) + return; + Undo(nIndex,nBar); + return; + /* + //do nothing if in the middle of an update + if(m_bUpdating) return; + + if(m_bUndoing) + return; + //added 08/20/2001 - mouse over to confirm change was changing time bar selected + m_bUpdating=true; + + if(m_ckLock.GetCheck()==TRUE) + { + + + } + + + CString strTemp; + CString strTechNumber; + + GetTimeBarObject(nIndex,nBar); + if(m_ptbData==NULL) + { + m_bUpdating=false; + return; + } + + #ifdef MARTIN + //MARTIN TEST TEST TEST + strTemp.Format("Workorder %u has been changed - allow this?",m_ptbData->m_lWOID); + + if(AfxMessageBox(strTemp,MB_YESNO)==IDNO) + { + m_bUpdating=false; + Undo(nIndex,nBar); + return; + } + + #endif + + m_ptbData->m_lDateStart=lDateStart; + m_ptbData->m_lDateEnd=lDateEnd; + m_ptbData->m_lTimeStart=lTimeStart; + m_ptbData->m_lTimeEnd=lTimeEnd; + + CString q,strWOID; + COleDateTime dtStart,dtEnd; + COleDateTimeSpan dtSpan; + + //CWaitCursor wait; + + + //convert start time + dtSpan.SetDateTimeSpan(lDateStart,0,lTimeStart,0); + dtStart=m_dt1900+dtSpan; + + //convert end time + dtSpan.SetDateTimeSpan(lDateEnd,0,lTimeEnd,0); + dtEnd=m_dt1900+dtSpan; + + //get workorder number + // strWOID=GetWoIDFromTimeBar(nIndex,nBar); + strWOID=m_sc.GetBarKeyID(nIndex,nBar); + //******************** + //handle multiple techs added 08/20/2001 + + switch (m_ptbData->m_nTechNumber) + { + case 1: + strTechNumber="starttime"; + break; + case 2: + strTechNumber="starttime2"; + break; + case 3: + strTechNumber="starttime3"; + break; + case 4: + strTechNumber="starttime4"; + break; + } + + + + + //******************** + q.Format("UPDATE wo SET wo.%s = #%s#, wo.stoptime = #%s# " + "WHERE (((wo.id)=%u));",strTechNumber,dtStart.Format(_T("%m/%d/%Y %H:%M:%S")), + dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),m_ptbData->m_lWOID); + + + + rs=m_pApp->rsPool->GetRS("OnBarChangedCtsched recordset"); + + rs->Ex(q); + + //ADDED 07/24/2001 AS IT WAS NOTICED THAT A DRAG CHANGE DOESN'T CATCH + //THE FIRST TIME. + rs->Close(); + rs->QueryReadOnly("SELECT defaults.* FROM defaults;"); + rs->Close(); + + + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + + m_bUpdating=false; + //relock + m_ckLock.SetCheck(TRUE); + m_bLocked=true; + + m_bRefresh=true; + FillView(); + +*/ +} + + +//new workorder +void CScheduleFrm::OnBarAddedCtsched(short nIndex, short nBar, BOOL bMouseBar, BOOL bKeyedBar) +{ + //only proceed if added with the mouse + if(!bMouseBar) return; + //needed because fillview somehow + //causes endless loop as it thinks all + //bars added after first are moused for some obscure bug riddled reason + if(bKeyedBar) return; + + long lSchedRndMinutes;//used for rounding to nearest quarter hour + long lSchedRndHours;//used for rounding + + + int x=m_pApp->Allowed(RWORKORDER,true); + if(x!=1)//no write allowed + { + m_pApp->SecurityWarning(); + return; + } + + //pause the timer and other things + m_bUpdating=true; + + COleDateTimeSpan dtSpan; + CWOHeaderDlg wo; + + //Set the start date and time + + //round out to nearest quarter hour? + if(m_pApp->m_bDefSchedRnd==true) + { + //get user selection + //because it's only minutes set here first so that we can + //split out hours and minutes for rounding + dtSpan.SetDateTimeSpan(m_sc.GetBarDateStart(nIndex,nBar), + 0,m_sc.GetBarTimeStart(nIndex,nBar),0); + + //Get the hours and minutes + lSchedRndMinutes=dtSpan.GetMinutes(); + lSchedRndHours=dtSpan.GetHours(); + RoundTime(&lSchedRndMinutes,&lSchedRndHours); + + //Set the time and date again + dtSpan.SetDateTimeSpan(m_sc.GetBarDateStart(nIndex,nBar), + (int)lSchedRndHours,lSchedRndMinutes,0); + + + } + else + { + + dtSpan.SetDateTimeSpan(m_sc.GetBarDateStart(nIndex,nBar), + 0,m_sc.GetBarTimeStart(nIndex,nBar),0); + } + wo.m_oledtPresetStartDate=m_dt1900+dtSpan; + + + + //Set the end date and time + //round out to nearest quarter hour? + if(m_pApp->m_bDefSchedRnd==true) + { + //get user selection + //because it's only minutes set here first so that we can + //split out hours and minutes for rounding + dtSpan.SetDateTimeSpan(m_sc.GetBarDateEnd(nIndex,nBar), + 0,m_sc.GetBarTimeEnd(nIndex,nBar),0); + + //Get the hours and minutes + lSchedRndMinutes=dtSpan.GetMinutes(); + lSchedRndHours=dtSpan.GetHours(); + RoundTime(&lSchedRndMinutes,&lSchedRndHours); + + //Set the time and date again + dtSpan.SetDateTimeSpan(m_sc.GetBarDateEnd(nIndex,nBar), + (int)lSchedRndHours,lSchedRndMinutes,0); + + + } + else + { + + dtSpan.SetDateTimeSpan(m_sc.GetBarDateEnd(nIndex,nBar), + 0,m_sc.GetBarTimeEnd(nIndex,nBar),0); + } + wo.m_oledtPresetEndDate=m_dt1900+dtSpan; + + + + //Set the tech + wo.m_strSelTech=m_sc.GetListCargo(nIndex); + + + //Do the workorder + wo.DoModal(); + m_bRefresh=true; + FillView(); + + //release the timer and other functions + m_bUpdating=false; + + + +} + + + +void CScheduleFrm::OnBarRightClickCtsched(short nIndex, short nBar) +{ + //get a lock on things + m_bUpdating=true; + COleDateTime dtStart,dtEnd,dtOriginalStart,dtOriginalEnd; + long lRed,lGreen,lBlue,lStatus,lWOID; + CString strOriginalTech; + CString strTech,strTechNumber,strDateNumber; + bool bTechChange=false; + bool bStatusChange=false; + bool bDateChange=false; + //strTech=m_sc.GetListCargo(nIndex); + CString strStatus,q; + //sets the public m_ptbData pointer to the correct record + GetTimeBarObject(nIndex,nBar); + //ASSERT(m_ptbData!=NULL); + if(m_ptbData==NULL) return; + strTechNumber.Format("%i",m_ptbData->m_nTechNumber); + lWOID=m_ptbData->m_lWOID; + strStatus.Format("%u",m_ptbData->m_lStatus); + strOriginalTech.Format("%u",m_ptbData->m_lTechID); + strTech=strOriginalTech; + + + + CDlgDispStatPopup d; + + //set start and end date values + SchedToOleDT(m_ptbData->m_lDateStart,m_ptbData->m_lTimeStart,&dtStart); + dtOriginalStart=dtStart; + d.m_pdtStart=&dtStart; + + SchedToOleDT(m_ptbData->m_lDateEnd,m_ptbData->m_lTimeEnd,&dtEnd); + dtOriginalEnd=dtEnd; + d.m_pdtEnd=&dtEnd; + + + + + d.m_pstrSelectedStatus=&strStatus; + d.m_plRed=&lRed; + d.m_plGreen=&lGreen; + d.m_plBlue=&lBlue; + d.m_pstrSelectedTech=&strTech; + d.m_pstrSelectedTechNumber=&strTechNumber; + + //added for MASS 12/12/2001 + d.m_strWOInfo=m_ptbData->m_strDisplayData; + + if(d.DoModal()==IDCANCEL)//user cancelled? + { + m_bUpdating=false; + return; + } + + lStatus=atol(strStatus); + if(strTech!=strOriginalTech) + bTechChange=true; + + if(lStatus!=m_ptbData->m_lStatus) + bStatusChange=true; + + //check for differing date + if(dtEnd!=dtOriginalEnd || dtStart!=dtOriginalStart) + bDateChange=true; + + + + if(bStatusChange || bTechChange || bDateChange) + { + + rs=m_pApp->rsPool->GetRS("CScheduleFrm::OnBarRightClickCtsched"); + + + + //Only do a status change if there is one. + if(bStatusChange) + { + q.Format("Workorder %u\r\n\"%s\"\r\n\r\nStatus has changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); + + if(AfxMessageBox(q,MB_YESNO)==IDYES) + { + + + q.Format("UPDATE wo SET wo.status = %u WHERE (((wo.id)=%u));" + , lStatus, m_ptbData->m_lWOID); + + rs->Ex(q); + rs->Close(); + m_sc.SetBarBackColor(nIndex,nBar,RGB(lRed,lGreen,lBlue)); + m_ptbData->m_lStatus=lStatus; + } + + } + + + + //only do a tech change if there is one + if(bTechChange || bDateChange) + { + if(bTechChange && bDateChange) + { + q.Format("Workorder %u\r\n\"%s\"\r\n\r\nDate and technician have changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); + } + else + { + if(bDateChange) + q.Format("Workorder %u\r\n\"%s\"\r\n\r\nDate has changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); + else + q.Format("Workorder %u\r\n\"%s\"\r\n\r\nAssigned technician has changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); + } + + if(AfxMessageBox(q,MB_YESNO)==IDYES) + { + switch (m_ptbData->m_nTechNumber) + { + case 1: + strTechNumber=""; + break; + case 2: + strTechNumber="2"; + break; + case 3: + strTechNumber="3"; + break; + case 4: + strTechNumber="4"; + break; + } + + + //updates date and time as well as tech at the same time either way + + q.Format("UPDATE wo SET wo.assigntech%s = %s, wo.starttime%s = #%s#, wo.stoptime%s = #%s# " + "WHERE (((wo.id)=%u));" + , strTechNumber,strTech, + strTechNumber,dtStart.Format(_T("%m/%d/%Y %H:%M:%S")), + strTechNumber,dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")), + m_ptbData->m_lWOID); + rs->Ex(q); + ///////////////////////////////////rs->Close(); + m_ptbData->m_lTechID=atol(strTech); + } + + } + + + + + + //axe the recordset + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + + + + } + + //release lock on things + m_bUpdating=false; + + if(bTechChange || bStatusChange || bDateChange) + { + m_bRefresh=true; + FillView(); + /* + //Added July 13th 2001 as refresh isn't catching the change + m_bRefresh=true; + FillView(); + */ + } + + +} + + + + + +//go back a day +void CScheduleFrm::OnBtnback() +{ + Scroll(false); +} + +//go ahead a day +void CScheduleFrm::OnBtnforward() +{ + Scroll(true); +} + +void CScheduleFrm::Scroll(bool bForward) +{ + COleDateTime dtStart; + COleDateTimeSpan dtSpan; + + + if(m_nDayWeekMonth==0)//1 day + dtSpan.SetDateTimeSpan(1,0,0,0); + else if(m_nDayWeekMonth==1)//one week + dtSpan.SetDateTimeSpan(8,0,0,0); + else if(m_nDayWeekMonth==2)//month + dtSpan.SetDateTimeSpan(31,0,0,0); + + m_dtDate.GetTime(dtStart); + if(bForward) + dtStart=dtStart+dtSpan; + else + dtStart=dtStart-dtSpan; + + m_dtDate.SetTime(dtStart); + FillView(); +} + +void CScheduleFrm::ZoomClick(int nItem) +{ + m_nDayWeekMonth=nItem; + m_rdDay.SetCheck(FALSE); + m_rdWeek.SetCheck(FALSE); + m_rdMonth.SetCheck(FALSE); + + switch (m_nDayWeekMonth) + { + + case 0: + m_rdDay.SetCheck(TRUE); + break; + case 1: + m_rdWeek.SetCheck(TRUE); + break; + default: + m_rdMonth.SetCheck(TRUE); + break; + } + + m_bRefresh=true; + FillView(); + +} + +void CScheduleFrm::OnRdday() +{ + ZoomClick(0); + +} + +void CScheduleFrm::OnRdmonth() +{ + ZoomClick(2); + +} + +void CScheduleFrm::OnRdweek() +{ + ZoomClick(1); + +} + +//get the users set preferences for start and stop times +//those values are used at the bottom of FillView to +//set the schedule hours window displayed +void CScheduleFrm::GetUserHoursPreferences() +{ + + CString q; + q.Format("SELECT users.defschedstarthour, users.defschedstophour " + "FROM users WHERE (((users.id)=%u));",m_pApp->m_lusrID); + rs->QueryReadOnly(q); + + rs->FetchField("defschedstarthour",&m_lUserStartHour); + rs->FetchField("defschedstophour",&m_lUserStopHour); + + + + +} + + +//set public pointer to time bar object in question +//sets to NULL if not found which currently only +//asserts, no other checking done. +void CScheduleFrm::GetTimeBarObject(short nIndex, short nBar) +{ + + int x; + int nComma=0,nLeft,nRight; + bool bNoMatch=true; + long lWOID; + int nTechNumber; + CString strWOID=m_sc.GetBarKeyID(nIndex,nBar); + ASSERT(!strWOID.IsEmpty()); + if(strWOID=="off") //added 07/24/01 to accomodate time off bars + { + m_ptbData=NULL;//indicates not a regular time bar + return; + } + + nComma=strWOID.Find(','); + if(nComma!=-1) + { + nLeft=nComma; + nRight=strWOID.GetLength()-nComma-1; + lWOID=atol(strWOID.Left(nLeft)); + nTechNumber=atoi(strWOID.Right(nRight)); + + ASSERT(lWOID!=0); + + //default signalling not a regular time bar + m_ptbData=NULL; + + for(x=0;xm_lWOID==lWOID && m_ptbData->m_nTechNumber==nTechNumber) + { + bNoMatch=false; + break; + } + } + } + if(bNoMatch) + m_ptbData=NULL;//added 07/24/01 to handle non-wo time bars for now + +} + + +//Force a refresh +void CScheduleFrm::OnBtnrefresh() +{ + + //m_bRefresh=true; + //FillView(); + + KillTimer(1); + m_bRefresh=true; + FillView(); + + + //AUTOREFRESH TIMER + if(m_pApp->m_lSchedRefreshSecs!=0) + m_nTimer = SetTimer(1, 1000*m_pApp->m_lSchedRefreshSecs, 0); + //m_nTimer = SetTimer(1, 6000, 0); + + m_bTimerIsActive=true; + +} + +void CScheduleFrm::OnCKLOCk() +{ + // TODO: Add your control notification handler code here + m_bLocked=m_ckLock.GetCheck() ? true:false; + +} + + + +void CScheduleFrm::Undo(short nIndex, short nBar) +{ + m_bUndoing=true; + GetTimeBarObject(nIndex,nBar); + //ADDED O7/24/2001 TO HANDLE SPECIAL TIME BARS + if(m_ptbData==NULL) + { + m_bUndoing=false; + m_bRefresh=true; + FillView(); + return; + } + m_sc.SetBarDateStart(nIndex,nBar,m_ptbData->m_lDateStart); + m_sc.SetBarDateEnd(nIndex,nBar,m_ptbData->m_lDateEnd); + m_sc.SetBarTimeStart(nIndex,nBar,m_ptbData->m_lTimeStart); + m_sc.SetBarTimeEnd(nIndex,nBar,m_ptbData->m_lTimeEnd); + + m_bUndoing=false; +} + + +//Modify layout to accomodate different windows sizes +void CScheduleFrm::LayoutControls() +{ + if(m_bLayoutDone) return; + + + + + CRect rectMain, rectCtl; + GetWindowRect(rectMain); + //this is the start of the window in question + int nOffset=rectMain.top; + int nLastBottom,nTopOfBottomRow; + int nHeight; + + m_lblDetails.GetWindowRect(rectCtl); + rectCtl.right=rectMain.right-50; + rectCtl.top-=nOffset; + rectCtl.bottom-=nOffset; + m_lblDetails.MoveWindow(rectCtl,TRUE); + + + m_sc.GetWindowRect(rectCtl); + rectCtl.right=rectMain.right-50; + rectCtl.top-=nOffset; + rectCtl.bottom=rectMain.bottom-85-nOffset; + m_sc.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + + m_ckLock.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.top=nLastBottom+1; + rectCtl.bottom=rectCtl.top+nHeight; + m_ckLock.MoveWindow(rectCtl,TRUE); + + m_lblStartDate.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.top=nLastBottom+5; + //preserve for other controls along bottom + nTopOfBottomRow=rectCtl.top; + rectCtl.bottom=rectCtl.top+nHeight; + m_lblStartDate.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + + m_dtDate.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.top=nLastBottom+1; + rectCtl.bottom=rectCtl.top+nHeight; + m_dtDate.MoveWindow(rectCtl,TRUE); + + m_lblZone.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.top=nTopOfBottomRow; + rectCtl.bottom=rectCtl.top+nHeight; + m_lblZone.MoveWindow(rectCtl,TRUE); + + + m_cbZone.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.top=nLastBottom+1; + rectCtl.bottom=rectCtl.top+nHeight; + m_cbZone.MoveWindow(rectCtl,TRUE); + + + m_lblView.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.top=nTopOfBottomRow; + rectCtl.bottom=rectCtl.top+nHeight; + m_lblView.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + + m_rdDay.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom-7; + rectCtl.top=rectCtl.bottom-nHeight; + m_rdDay.MoveWindow(rectCtl,TRUE); + + m_rdMonth.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom-7; + rectCtl.top=rectCtl.bottom-nHeight; + m_rdMonth.MoveWindow(rectCtl,TRUE); + + m_rdWeek.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom-7; + rectCtl.top=rectCtl.bottom-nHeight; + m_rdWeek.MoveWindow(rectCtl,TRUE); + + m_btnBack.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnBack.MoveWindow(rectCtl,TRUE); + + m_btnForward.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnForward.MoveWindow(rectCtl,TRUE); + + + + m_btnRefresh.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnRefresh.MoveWindow(rectCtl,TRUE); + + m_btnPrint.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + rectCtl.bottom=nLastBottom; + rectCtl.top=rectCtl.bottom-nHeight; + m_btnPrint.MoveWindow(rectCtl,TRUE); + + + + + //only execute once + m_bLayoutDone=true; + +} + + + +void CScheduleFrm::ClearTimeBarObjects() +{ + //delete all arBar objects + int x; + + if(m_nTotalAllocated>0) + { + for(x=0;xrsPool->GetRS("CScheduleFrm::FillZoneList()"); + + + //fill ZONES + m_cbZone.Clear(); + m_cbZone.AddRow(" < All Techs >","0"); + q="SELECT zones.id, zones.name FROM zones ORDER BY zones.name;"; + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + strData+=" zone"; + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbZone.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + + + //Fill groups + + q="SELECT schdgrps.id, schdgrps.name FROM schdgrps ORDER BY schdgrps.name;"; + + rs->QueryReadOnly(q); + if(!rs->IsEmpty()) + { + do + { + rs->FetchField("name",&strData); + strData+=" group"; + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbZone.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + + //------------------------------------------------ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_cbZone.SetCurSel(0); +} + +void CScheduleFrm::OnCloseupCbzone() +{ + CString strData,strID; + strID=m_cbZone.GetCurrentRowID(); + strData=m_cbZone.GetCurrentRowText(); + if(strData.Right(4)=="zone" || strID=="0") + m_bZoneView=true; + else + m_bZoneView=false;//by group + + m_bRefresh=true; + + FillView(); +} + + + + +void CScheduleFrm::OnTimer(UINT nIDEvent) +{ + + + if(nIDEvent==1 && !m_bUpdating) + { + + KillTimer(1); + m_bRefresh=true; + FillView(); + + + //AUTOREFRESH TIMER + if(m_pApp->m_lSchedRefreshSecs!=0) + m_nTimer = SetTimer(1, 1000*m_pApp->m_lSchedRefreshSecs, 0); + //m_nTimer = SetTimer(1, 6000, 0); + + m_bTimerIsActive=true; + + + + + + } + CFormView::OnTimer(nIDEvent); +} + +//round minutes to nearest quarter hour +void CScheduleFrm::RoundTime(long *lMinutes, long* lHours) +{ + if(*lMinutes==0) return; + if(*lMinutes==15) return; + if(*lMinutes==30) return; + if(*lMinutes==45) return; + + //FIRST QUARTER + //0-7 = 0 + if(*lMinutes>0 && *lMinutes<8) + { + *lMinutes=0; + return; + + } + + //8-14 = 15 + if(*lMinutes>7 && *lMinutes < 15) + { + *lMinutes=15; + return; + + } + + //SECOND QUARTER + //16-22 = 15 + if(*lMinutes>15 && *lMinutes < 23) + { + *lMinutes=15; + return; + + } + + //23-29 = 30 + if(*lMinutes>22 && *lMinutes < 30) + { + *lMinutes=30; + return; + + } + + //THIRD QUARTER + //31 - 37= 30 + if(*lMinutes>30 && *lMinutes < 38) + { + *lMinutes=30; + return; + + } + + //38-44 = 45 + if(*lMinutes>37 && *lMinutes < 45) + { + *lMinutes=45; + return; + + } + + //FOURTH QUARTER + //46 - 52 = 45 + if(*lMinutes>45 && *lMinutes < 53) + { + *lMinutes=45; + return; + + } + + //53-59 = 0 + if(*lMinutes>52 && *lMinutes < 60) + { + *lMinutes=0; + *lHours=*lHours+1; + return; + + } + + + + + +} + +BOOL CScheduleFrm::OnHelpInfo(HELPINFO* pHelpInfo) +{ +WinHelp (0x00020000 + IDD_SCHEDULEFRM_FORM,HELP_CONTEXT); + return TRUE; +} + +void CScheduleFrm::CleanupForExit(void) +{ + +} + +void CScheduleFrm::OnDestroy() +{ + KillTimer(1); + ClearTimeBarObjects(); + + CFormView::OnDestroy(); + + // TODO: Add your message handler code here +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.h new file mode 100644 index 0000000..818d57e --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.h @@ -0,0 +1,166 @@ +//{{AFX_INCLUDES() +#include "ctschedule.h" +//}}AFX_INCLUDES +#if !defined(AFX_SCHEDULEFRM_H__C5A2FB05_B94D_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_SCHEDULEFRM_H__C5A2FB05_B94D_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ScheduleFrm.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CScheduleFrm form view +#include +#ifndef __AFXEXT_H__ +#include +#endif + +#include "gzrset.h" +#include "label.h" +#include "DlgDispStatPopup.h" +#include "scheduletimebardata.h" +#include "perftimer.h" + +class CScheduleFrm : public CFormView +{ +public: +CScheduleFrm(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(CScheduleFrm) + GZRset* rs; + GZRset* rs2; + GZRset* rs3; + CSpApp* m_pApp; + //used by various calcs + COleDateTime m_dt1900; + CObArray arBar; + CScheduleTimeBarData * m_ptbData; + CPerfTimer pTimer; + CPerfTimer pTimerSQL; + double m_dFastest,m_dSlowest, m_dLast, m_dAverage, m_dOverallTime; + unsigned int m_uiRefreshCount; + bool m_bZoneView; + +// Form Data +public: + //{{AFX_DATA(CScheduleFrm) + enum { IDD = IDD_SCHEDULEFRM_FORM }; + CStatic m_lblZone; + CgzCombo m_cbZone; + CButton m_btnBack; + CButton m_btnForward; + CButton m_btnPrint; + CButton m_lblView; + CStatic m_lblStartDate; + CButton m_btnRefresh; + CButton m_ckLock; + CButton m_rdWeek; + CButton m_rdMonth; + CButton m_rdDay; + CLabel m_lblDetails; + CDateTimeCtrl m_dtDate; + CctSchedule m_sc; + //}}AFX_DATA + +// Attributes +public: + +// Operations +public: + + + bool m_bUpdating; + bool m_bTimerIsActive; + long m_lLastRefreshValue; + int m_nTimer; + int m_nBarStyleOverlapping; + int m_nBarStyleTimeOff;//added 07/24/01 to handle flagging tech time off + int m_nBarStyleAllDayText;//added 07/24/01 to handle descriptive text for all day backcolor + void FillZoneList(); + void ClearTimeBarObjects(); + int m_nTotalAllocated; + bool m_bUndoing; + +// long m_lBarDateStart; +// long m_lBarTimeStart; +// long m_lBarDateEnd; +// long m_lBarTimeEnd; + bool m_bLocked; + bool m_bRefresh; + COleDateTime m_dtWindowStart; + COleDateTime m_dtWindowStop; + void GetUserHoursPreferences(); + int m_nDayWeekMonth; + void ZoomClick(int nItem); + void Scroll(bool bForward); + int m_nZoomFactor; + void SchedToOleDT(long lSchedDateValue,long lSchedTimeValue, COleDateTime* dt); + short m_nOldBar; + short m_nOldIndex; + unsigned long m_ulHighLightedBar; + unsigned long m_ulStandardBar; + void FillView(); + void DeActivate(); + void Activate(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CScheduleFrm) + public: + virtual void OnInitialUpdate(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL +virtual ~CScheduleFrm(); +// Implementation +protected: + +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(CScheduleFrm) + afx_msg void OnDatetimechangeDtdate(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnBtnprint(); + afx_msg void OnItemMoveCtsched(short nIndex, short nBar); + afx_msg void OnBarDblClickCtsched(short nIndex, short nBar); + afx_msg void OnBarSizingCtsched(short nIndex, short nBar, short nType, long lTimeStart, long lTimeEnd, long lDateStart, long lDateEnd); + afx_msg void OnBarChangedCtsched(short nIndex, short nBar, LPCTSTR cKeyID, long lTimeStart, long lTimeEnd, long lDateStart, long lDateEnd); + afx_msg void OnBarAddedCtsched(short nIndex, short nBar, BOOL bMouseBar, BOOL bKeyedBar); + afx_msg void OnBarRightClickCtsched(short nIndex, short nBar); + afx_msg void OnBtnback(); + afx_msg void OnBtnforward(); + afx_msg void OnRdday(); + afx_msg void OnRdmonth(); + afx_msg void OnRdweek(); + afx_msg void OnBtnrefresh(); + afx_msg void OnCKLOCk(); + afx_msg void OnCloseupCbzone(); + afx_msg void OnTimer(UINT nIDEvent); + DECLARE_EVENTSINK_MAP() + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + void RoundTime(long* lMinutes, long* lHours); + bool m_bLayoutDone; + void LayoutControls(); + void Undo(short nIndex, short nBar); + void GetTimeBarObject(short nIndex, short nBar); + long m_lUserStopHour; + long m_lUserStartHour; +public: + bool m_bShowProblemDetailsInStatusDisplay; + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); + void CleanupForExit(void); + afx_msg void OnDestroy(); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SCHEDULEFRM_H__C5A2FB05_B94D_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.cpp new file mode 100644 index 0000000..7707dc3 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.cpp @@ -0,0 +1,27 @@ +// ScheduleTimeBarData.cpp: implementation of the CScheduleTimeBarData class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "sp.h" +#include "ScheduleTimeBarData.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CScheduleTimeBarData::CScheduleTimeBarData() +{ + +} + +CScheduleTimeBarData::~CScheduleTimeBarData() +{ + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.h new file mode 100644 index 0000000..e8a7a3f --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleTimeBarData.h @@ -0,0 +1,35 @@ +// ScheduleTimeBarData.h: interface for the CScheduleTimeBarData class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_SCHEDULETIMEBARDATA_H__1CC3DBEE_C239_4815_80FE_8D20E65E46A8__INCLUDED_) +#define AFX_SCHEDULETIMEBARDATA_H__1CC3DBEE_C239_4815_80FE_8D20E65E46A8__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CScheduleTimeBarData : public CObject +{ +public: + CScheduleTimeBarData(); + virtual ~CScheduleTimeBarData(); + long m_lWOID; + CString m_strDisplayData; + long m_lStatus; + int m_nID; + //used for undo function + long m_lDateStart; + long m_lTimeStart; + long m_lDateEnd; + long m_lTimeEnd; + + //used to fix martin problem hopefully + //stored here rather than using getcargo feature of sched control + //which seems to be overloading somehow + long m_lTechID; + int m_nTechNumber;//added 07/27/01 to accomodate multi tech situation + +}; + +#endif // !defined(AFX_SCHEDULETIMEBARDATA_H__1CC3DBEE_C239_4815_80FE_8D20E65E46A8__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.cpp new file mode 100644 index 0000000..3eac683 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.cpp @@ -0,0 +1,1091 @@ +// SimpleDate.cpp: implementation of the CSimpleDate class. +// +// Most of the date alogrithms used in this class can be found at +// http://www.capecod.net/~pbaum/date/date0.htm +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "SimpleDate.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +#pragma message( "Compiling " __FILE__ ) +#pragma message( "Last modified on " __TIMESTAMP__ ) + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +static int monthtotals[]= + { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 } ; + +static char* daysofweek[] = +{ + { "Sun" }, + { "Mon" }, + { "Tue" }, + { "Wed" }, + { "Thu" }, + { "Fri" }, + { "Sat" }, +} ; + +static char* days_of_week[] = +{ + { "Sunday" }, + { "Monday" }, + { "Tuesday" }, + { "Wednesday" }, + { "Thursday" }, + { "Friday" }, + { "Saturday" }, +} ; + +static char* monthsofyear[] = +{ + { "" }, + { "Jan" }, + { "Feb" }, + { "Mar" }, + { "Apr" }, + { "May" }, + { "Jun" }, + { "Jul" }, + { "Aug" }, + { "Sep" }, + { "Oct" }, + { "Nov" }, + { "Dec" }, +} ; + +static char* months_of_year[] = +{ + { "" }, + { "January" }, + { "February" }, + { "March" }, + { "April" }, + { "May" }, + { "June" }, + { "July" }, + { "August" }, + { "September" }, + { "October" }, + { "November" }, + { "December" }, +} ; + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::CSimpleDate +// Description : Simple Constructor object is set to todays date +// Return type : +//-------------------------------------------------------------------- +CSimpleDate::CSimpleDate(int FormatType) +{ + m_Format=FormatType; + SetToday(); + m_JulianDate=ConvertToJulian(); + SetTime(); +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::CSimpleDate +// Description : paramaterized constructor object is set to date in string. Parsing will be done based on formattype +// Return type : +// Argument : LPCSTR DateString +//-------------------------------------------------------------------- + +CSimpleDate::CSimpleDate(LPCSTR DateString,int FormatType) +{ + m_Format=FormatType; + ParseDateString(DateString); + m_JulianDate=ConvertToJulian(); + SetTime(); +} + + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::CSimpleDate +// Description : +// Return type : +// Argument : long JD +// Argument : int FormatType +//-------------------------------------------------------------------- +CSimpleDate::CSimpleDate(long JD,int FormatType) +{ + m_Format=FormatType; + m_JulianDate=JD; + ConvertFromJulian(); // note: m_JulianDate must be set prior to this call + SetTime(); +} + + + +//added constructor JC 10/05/00 +CSimpleDate::CSimpleDate( int month,int day,int year,int FormatType) +{ +m_Format=FormatType; +m_JulianDate=ConvertToJulian( month, day, year); + +//// Added initialization ///// +m_Year=year; +m_Month=month; +m_Day=day; +////////////////////////////// + +SetTime(); +} + + + + + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::~CSimpleDate +// Description : +// Return type : +//-------------------------------------------------------------------- +CSimpleDate::~CSimpleDate() +{ + +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::SetToday +// Description : +// Return type : BOOL +//-------------------------------------------------------------------- +BOOL CSimpleDate::SetToday() +{ + long time_val ; + struct tm *tm_ptr ; + + time( (time_t *)&time_val ) ; + tm_ptr = localtime( (time_t *)&time_val ) ; + + m_Year=1900 + tm_ptr->tm_year; + m_Month=tm_ptr->tm_mon + 1; + m_Day=tm_ptr->tm_mday; + return TRUE; +} + + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::IsValid +// Description : Hope that this is right and Y2K OK +// Return type : BOOL +//-------------------------------------------------------------------- +BOOL CSimpleDate::IsValid() +{ + int is_leap, month_days ; + + is_leap = ( m_Year%4 == 0 && m_Year%100 != 0 || m_Year%400 == 0 ) ? 1 : 0 ; + if(m_Month > 12 || m_Day > 31) + return FALSE; + month_days = monthtotals[ m_Month+1 ] - monthtotals[ m_Month] ; + if ( m_Month == 2 ) month_days += is_leap ; + + if ( m_Year < 0 || + m_Month < 1 || m_Month > 12 || + m_Day < 1 || m_Day > month_days ) + return FALSE ; + return TRUE; +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::ParseDateString +// Description : +// Return type : BOOL +// Argument : LPCSTR TheDate +//-------------------------------------------------------------------- +BOOL CSimpleDate::ParseDateString(LPCSTR TheDate) +{ + ParseDateString(TheDate,m_Month,m_Day,m_Year); + return TRUE; +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::ParseDateString +// Description : See CParseIt class in Parseit.cpp for details +// Return type : BOOL +// Argument : LPCSTR date +// Argument : int& m +// Argument : int& d +// Argument : int& y +//-------------------------------------------------------------------- +BOOL CSimpleDate::ParseDateString(LPCSTR date,int& m,int& d,int& y) +{ + CParseIt ParseIt(date,"/.-"); + ParseIt.Parse(); + int one,two,three; + one=two=three=0; + int N=ParseIt.GetNumFields(); + one=(int)ParseIt.GetField(1); + if(N > 1) + two=(int)ParseIt.GetField(2); + if(N > 2) + three=(int)ParseIt.GetField(3); + switch(m_Format) + { + case MMDDYY: + m=one;d=two;y=three; + if(y < 100) // ajust two digit year to the range of 1900-1999 + y+=1900; + break; + case DDMMYY: + d=one;m=two;y=three; + if(y < 100) + y+=1900; + break; + case YYMMDD: + y=one;m=two;d=three; + if(y < 100) + y+=1900; + break; + case MMDDYYYY: + m=one;d=two;y=three; + if(y < 100) + y+=1900; + break; + case DDMMYYYY: + d=one;m=two;y=three; + if(y < 100) + y+=1900; + break; + case YYYYMMDD: + y=one;m=two;d=three; + if(y < 100) + y+=1900; + break; + default: + m=y=d=0; + } + + return TRUE; + +} + +//-------------------------------------------------------------------- +// JULIAN DATE CONVERSION BELOW +//-------------------------------------------------------------------- +// Function name : CSimpleDate::ConvertToJulian +// Description : +// Return type : long +//-------------------------------------------------------------------- +long CSimpleDate::ConvertToJulian() +{ + return ConvertToJulian(m_Month,m_Day,m_Year); + +} +//-------------------------------------------------------------------- +// Function name : CSimpleDate::ConvertToJulian +// Description : go to http://www.capecod.net/~pbaum/date/date0.htm for details +// Return type : long +// Argument : int month +// Argument : int day +// Argument : int year +//-------------------------------------------------------------------- +long CSimpleDate::ConvertToJulian( int m,int d,int y) +{ + if(m < 3) + { + m = m + 12; + y=y-1 ; + } + long jd = d + (153 * m - 457) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) + 1721119; + return jd; +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::ConvertFromJulian +// Description : +// Return type : void +//-------------------------------------------------------------------- +void CSimpleDate::ConvertFromJulian() +{ + ConvertFromJulian(m_Month,m_Day,m_Year); +} +//-------------------------------------------------------------------- +// Function name : CSimpleDate::ConvertFromJulian +// Description : goto http://www.capecod.net/~pbaum/date/date0.htm for details +// Return type : void +// Argument : int Month +// Argument : int DAy +// Argument : int Year +//-------------------------------------------------------------------- +void CSimpleDate::ConvertFromJulian(int& Month,int& Day,int& Year) +{ + + long L = m_JulianDate + 68569; + long N = (long) ((4*L)/146097) ; + L = L - ((long)((146097 * N + 3)/4) ); + long I = (long) ((4000 *(L + 1)/1461001)) ; + L = L - (long)((1461*I)/4) + 31; + long J = (long)((80*L)/2447); + Day = L - (long)((2447*J)/80); + L=(long)(J/11) ; + Month = J + 2 - 12*L; + Year = 100*(N-49) + I + L ; +} + +//-------------------------------------------------------------------- +// JULIAN DATE CONVERSION ABOVE +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetDayOfWeek +// Description : goto http://www.capecod.net/~pbaum/date/date0.htm for details +// Return type : int +//-------------------------------------------------------------------- +int CSimpleDate::GetDayOfWeek() +{ + if(!IsValid()) + return 0; + int res= ((int) (m_JulianDate + 1.5)) % 7; + return res; +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetFullDateString +// Description : +// Return type : LPCSTR +//-------------------------------------------------------------------- +LPCSTR CSimpleDate::GetFullDateString() +{ + if(!IsValid()) + return NULL; + m_DateString.Format("%s %s %02d %04d", daysofweek[GetDayOfWeek()],monthsofyear[m_Month],m_Day,m_Year); + return m_DateString; +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetFullDateStringLong +// Description : +// Return type : LPCSTR +//-------------------------------------------------------------------- +LPCSTR CSimpleDate::GetFullDateStringLong() +{ + if(!IsValid()) + return NULL; + m_DateString.Format("%s %s %02d %04d", days_of_week[GetDayOfWeek()],months_of_year[m_Month],m_Day,m_Year); + return m_DateString; +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetJulianDate +// Description : +// Return type : long +//-------------------------------------------------------------------- +long CSimpleDate::GetJulianDate() +{ + if(!IsValid()) + return 0L; + return m_JulianDate; +} + + +//-------------------------------------------------------------------- +// overloaded operators and copy constructors here +//-------------------------------------------------------------------- +// Function name : LPCSTR +// Description : +// Return type : CSimpleDate::operator return LPCSTR +//-------------------------------------------------------------------- +CSimpleDate::operator LPCSTR() +{ + if(!IsValid()) + return (LPCSTR)0; + switch(m_Format) + { + case MMDDYY: + m_DateString.Format("%02d/%02d/%02d",m_Month,m_Day,m_Year > 99 ? m_Year-1900:m_Year); + return (LPCSTR)m_DateString; + case DDMMYY: + m_DateString.Format("%02d/%02d/%02d",m_Day,m_Month,m_Year > 99 ? m_Year-1900:m_Year); + return (LPCSTR)m_DateString; + case YYMMDD: + m_DateString.Format("%02d/%02d/%02d",m_Year > 99 ? m_Year-1900:m_Year,m_Month,m_Day); + return (LPCSTR)m_DateString; + case MMDDYYYY: + m_DateString.Format("%02d/%02d/%04d",m_Month,m_Day,m_Year ); + return (LPCSTR)m_DateString; + case DDMMYYYY: + m_DateString.Format("%02d/%02d/%04d",m_Day,m_Month,m_Year); + return (LPCSTR)m_DateString; + case YYYYMMDD: + m_DateString.Format("%04d/%02d/%02d",m_Year ,m_Month,m_Day); + return (LPCSTR)m_DateString; + default: + return (LPCSTR)NULL; + } +} + + +//-------------------------------------------------------------------- +// OPERATORS +//-------------------------------------------------------------------- +// Function name : long +// Description : +// Return type : CSimpleDate::operator return long +//-------------------------------------------------------------------- +CSimpleDate::operator long() +{ + if(!IsValid()) + return 0L; + return m_JulianDate; +} + +//-------------------------------------------------------------------- +// Function name : = +// Description : +// Return type : CSimpleDate::operator +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::operator =(const CSimpleDate& Date) +{ + if(*this==Date) + return *this; // self assignment + m_Year=Date.m_Year; + m_Month=Date.m_Month; + m_Day=Date.m_Day; + m_JulianDate=Date.m_JulianDate; + m_Format=Date.m_Format; + return *this; +} + +//-------------------------------------------------------------------- +// Function name : = +// Description : +// Return type : CSimpleDate::operator +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::operator =(LPCSTR Date) +{ + ParseDateString(Date); + m_JulianDate=ConvertToJulian(); + return *this; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator > (const CSimpleDate& Date) +{ + if(!IsValid()) + return FALSE; + return m_JulianDate > Date.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator >= (const CSimpleDate& Date) +{ + if(!IsValid()) + return FALSE; + return m_JulianDate >= Date.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator < (const CSimpleDate& Date) +{ + if(!IsValid()) + return FALSE; + return m_JulianDate < Date.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator <= (const CSimpleDate& Date) +{ + if(!IsValid()) + return FALSE; + return m_JulianDate <= Date.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator == (const CSimpleDate& Date) +{ + if(!IsValid()) + return FALSE; + return m_JulianDate == Date.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator != (const CSimpleDate& Date) +{ + if(!IsValid()) + return FALSE; + return m_JulianDate != Date.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator > (LPCSTR Date) +{ + if(!IsValid()) + return FALSE; + CSimpleDate TheDate(Date); + if(!TheDate.IsValid()) + return FALSE; + return m_JulianDate > TheDate.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator < (LPCSTR Date) +{ + if(!IsValid()) + return FALSE; + CSimpleDate TheDate(Date); + if(!TheDate.IsValid()) + return FALSE; + return m_JulianDate < TheDate.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator >= (LPCSTR Date) +{ + if(!IsValid()) + return FALSE; + CSimpleDate TheDate(Date); + if(!TheDate.IsValid()) + return FALSE; + return m_JulianDate >= TheDate.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator <= (LPCSTR Date) +{ + if(!IsValid()) + return FALSE; + CSimpleDate TheDate(Date); + if(!TheDate.IsValid()) + return FALSE; + return m_JulianDate <= TheDate.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator == (LPCSTR Date) +{ + if(!IsValid()) + return FALSE; + CSimpleDate TheDate(Date); + if(!TheDate.IsValid()) + return FALSE; + return m_JulianDate == TheDate.m_JulianDate; +} +//-------------------------------------------------------------------- +BOOL CSimpleDate::operator != (LPCSTR Date) +{ + if(!IsValid()) + return FALSE; + CSimpleDate TheDate(Date); + if(!TheDate.IsValid()) + return FALSE; + return m_JulianDate != TheDate.m_JulianDate; +} + + +//-------------------------------------------------------------------- +// Date Math routines +//-------------------------------------------------------------------- +// Function name : CSimpleDate::YearsOld +// Description : +// Return type : int +//-------------------------------------------------------------------- +int CSimpleDate::YearsOld() +{ + if(!IsValid()) + return 0; + CSimpleDate ToDay; + if(ToDay <= *this) + return 0; + long t=ToDay.GetJulianDate(); + long b=GetJulianDate(); + return (int)((t-b)/365.2425); + +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::AddMonths +// Description : +// Return type : const CSimpleDate& +// Argument : int Mon +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::AddMonths(int Mon) +{ + if(!IsValid()) + return *this; + m_Month+=Mon; + if(m_Month > 12) + { + while(m_Month > 12) + { + m_Month-=12; + ++m_Year; + } + } + AdjustDays(); + m_JulianDate=ConvertToJulian(); + return *this; +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::SubtractMonths +// Description : +// Return type : const CSimpleDate& +// Argument : int Mon +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::SubtractMonths(int Mon) +{ + if(!IsValid()) + return *this; + if(Mon > 12) + { + int t= Mon/12; + m_Year-=t; + Mon=Mon-(t*12); + } + m_Month-=Mon; + if(m_Month < 1) + { + --m_Year; + m_Month+=12; + } + AdjustDays(); + m_JulianDate=ConvertToJulian(); + return *this; +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::AddYears +// Description : +// Return type : const CSimpleDate& +// Argument : int Yrs +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::AddYears(int Yrs) +{ + if(!IsValid()) + return *this; + m_Year+=Yrs; + AdjustDays(); + m_JulianDate=ConvertToJulian(); + return *this; + +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::SubtractYears +// Description : +// Return type : const CSimpleDate& +// Argument : int Yrs +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::SubtractYears(int Yrs) +{ + if(!IsValid()) + return *this; + m_Year-=Yrs; + AdjustDays(); + m_JulianDate=ConvertToJulian(); + return *this; + +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::AddDays +// Description : +// Return type : const CSimpleDate& +// Argument : int Days +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::AddDays(int Days) +{ + if(!IsValid()) + return *this; + m_JulianDate+=Days; + ConvertFromJulian(m_Month,m_Day,m_Year); + return *this; +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::SubtractDays +// Description : +// Return type : const CSimpleDate& +// Argument : int Days +//-------------------------------------------------------------------- +const CSimpleDate& CSimpleDate::SubtractDays(int Days) +{ + if(!IsValid()) + return *this; + m_JulianDate-=Days; + ConvertFromJulian(m_Month,m_Day,m_Year); + return *this; + +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::AdjustDays +// Description : +// Return type : void +//-------------------------------------------------------------------- +void CSimpleDate::AdjustDays() +{ + int is_leap, month_days ; + is_leap = ( m_Year%4 == 0 && m_Year%100 != 0 || m_Year%400 == 0 ) ? 1 : 0 ; + month_days = monthtotals[ m_Month+1 ] - monthtotals[ m_Month] ; + if ( m_Month == 2 ) month_days += is_leap ; + while(m_Day > month_days) + --m_Day; + +} + +//-------------------------------------------------------------------- +// Time functions +//-------------------------------------------------------------------- +// Function name : CSimpleDate::SetTime +// Description : The only time function: Sets the variables for later use +// Return type : void +//-------------------------------------------------------------------- +void CSimpleDate::SetTime() +{ + long time_val ; + struct tm *tm_ptr ; + + time( (time_t *)&time_val) ; + tm_ptr = localtime( (time_t *)&time_val) ; + + m_Hour=tm_ptr->tm_hour; + m_Min=tm_ptr->tm_min; + m_Second=tm_ptr->tm_sec; + if(m_Hour > 12) + { + m_bPM=TRUE; + m_Hour-=12; + } + else + m_bPM=FALSE; + +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetTimeString +// Description : +// Return type : void +// Argument : CString& s +// Argument : BOOL AmPm +//-------------------------------------------------------------------- +void CSimpleDate::GetTimeString(CString& s,BOOL AmPm) +{ + if(!IsValid()) + { + s.Empty(); + return; + } + SetTime(); + int Flag=0; + if(AmPm==TRUE) + { + if(m_bPM) + Flag=1; + else + Flag=2; + } + s.Format("%02d:%02d:%02d %s",m_Hour==0 ? 12:m_Hour,m_Min,m_Second,Flag==0 ? "":Flag==1 ? "PM":"AM"); +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetTimeString +// Description : +// Return type : void +// Argument : LPSTR s +// Argument : int nLen +// Argument : BOOL AmPm +//-------------------------------------------------------------------- +void CSimpleDate::GetTimeString(LPSTR s,int nLen,BOOL AmPm) +{ + CString cs; + GetTimeString(cs,AmPm); + strncpy(s,cs,nLen); +} + + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetTimeStringShort +// Description : +// Return type : void +// Argument : CString& s +// Argument : BOOL AmPm +//-------------------------------------------------------------------- +void CSimpleDate::GetTimeStringShort(CString& s,BOOL AmPm) +{ + if(!IsValid()) + { + s.Empty(); + return; + } + SetTime(); + int Flag=0; + if(AmPm==TRUE) + { + if(m_bPM) + Flag=1; + else + Flag=2; + } + s.Format("%02d:%02d %s",m_Hour==0 ? 12:m_Hour,m_Min,Flag==0 ? "":Flag==1 ? "PM":"AM"); +} + +//-------------------------------------------------------------------- +// Function name : CSimpleDate::GetTimeStringShort +// Description : +// Return type : void +// Argument : LPSTR s +// Argument : int nLen +// Argument : BOOL AmPm +//-------------------------------------------------------------------- +void CSimpleDate::GetTimeStringShort(LPSTR s,int nLen,BOOL AmPm) +{ + CString cs; + GetTimeStringShort(cs,AmPm); + strncpy(s,cs,nLen); +} + + +//-------------------------------------------------------------------- +// Static member functions +//-------------------------------------------------------------------- +// Function name : CSimpleDate::FixDateFormat +// Description : +// Return type : BOOL +// Argument : LPSTR str +//-------------------------------------------------------------------- +BOOL CSimpleDate::FixDateFormat(LPSTR str) +{ + CString s; + s=str; + if(FixDateFormat(s)) + { + strcpy(str,s); + return TRUE; + } + return FALSE; +} +//-------------------------------------------------------------------- +// Function name : CSimpleDate::FixDateFormat +// Description : +// Return type : BOOL +// Argument : CString& str +//-------------------------------------------------------------------- +BOOL CSimpleDate::FixDateFormat(CString& str) +{ + char Buff[20]; + + if(str.IsEmpty()) + return FALSE; + if(str.GetLength() < 6 || str.GetLength() > 11) + return FALSE; + CParseIt ParseIt(str,"/.-"); + ParseIt.Parse(); + int N=ParseIt.GetNumFields(); + if(N > 1) + return FALSE; + strcpy(Buff,str.Left(2)); + strcat(Buff,"/"); + strcat(Buff,str.Mid(2,2)); + strcat(Buff,"/"); + if(str.GetLength()==6) + strcat(Buff,str.Right(2)); + else + strcat(Buff,str.Right(str.GetLength()-4)); + str=Buff; + return TRUE; +} +//-------------------------------------------------------------------- +// Function name : CSimpleDate::VerifyDateFormat +// Description : +// Return type : BOOL +// Argument : LPCSTR date +//-------------------------------------------------------------------- +BOOL CSimpleDate::VerifyDateFormat(LPCSTR date) +{ + BOOL HasSeperators=FALSE; + CString TheDate; + // allow blank dates + if(strlen(date)==0) + return TRUE; + // shortest possible date + if(strlen(date) < 6) + return FALSE; + // look for unacceptable characters + for(int x=0;x < (signed)strlen(date);++x) + { + if( date[x] !='/' && date[x] !='-' && date[x] !='.' && !isdigit(date[x])) + return FALSE; + } + for(x=0;x < (signed)strlen(date);++x) + { + if( date[x] =='/' || date[x] =='-' || date[x] =='.') + HasSeperators=TRUE; + } + TheDate=date; + if(!HasSeperators) + { + if(!FixDateFormat(TheDate)) + return FALSE; + } + CSimpleDate s(TheDate); + return s.IsValid(); +} +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +// NON CLASS MEMBER HELPER FUNCTIONS +//-------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////// +// data input a validation for the CSimpleDate class. These routines will allow +// input of date strings into a C type string or a CString or a long and will verify that +// the data is correct and will supply formatting if none is provided. +/////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +// Function name : DDX_SimpleDate +// Description : This is not real efficient but works. Makes extensive use +// of static class members so speed is not the greatest +// Return type : void +// Argument : CDataExchange *pDX +// Argument : int nID +// Argument : LPSTR str +// Argument : int nLen +//-------------------------------------------------------------------- +void DDX_SimpleDate(CDataExchange *pDX,int nID,LPSTR str,int nLen) +{ + char buff[50]; + pDX->PrepareEditCtrl(nID); + + CEdit *ptr=(CEdit *)pDX->m_pDlgWnd->GetDlgItem(nID); + if(pDX->m_bSaveAndValidate) + { + pDX->m_pDlgWnd->GetDlgItem(nID)->GetWindowText(buff,50); + if(CSimpleDate::FixDateFormat(buff)) + pDX->m_pDlgWnd->GetDlgItem(nID)->SetWindowText(buff); + + if(ptr->LineLength() > nLen) + { + sprintf(buff,"Max Length is %d",nLen); + pDX->m_pDlgWnd->MessageBox(buff,"",MB_OK); + pDX->Fail(); + } + pDX->m_pDlgWnd->GetDlgItem(nID)->GetWindowText(str,nLen+1); + if(CSimpleDate::VerifyDateFormat(str)==FALSE) + { + sprintf(buff,"Invalid Date or Format"); + pDX->m_pDlgWnd->MessageBox(buff,"",MB_OK); + pDX->Fail(); + } + } + else + { + ptr->LimitText(nLen); + pDX->m_pDlgWnd->GetDlgItem(nID)->SetWindowText(str); + } +} + + +//-------------------------------------------------------------------- +// Function name : DDX_SimpleDate +// Description : This is not real efficient but works. Makes extensive use +// of static class members so speed is not the greatest +// Return type : void +// Argument : CDataExchange *pDX +// Argument : int nID +// Argument : CString& str +//-------------------------------------------------------------------- +void DDX_SimpleDate(CDataExchange *pDX,int nID,CString& str) +{ + char buff[50]; + pDX->PrepareEditCtrl(nID); + + if(pDX->m_bSaveAndValidate) + { + pDX->m_pDlgWnd->GetDlgItem(nID)->GetWindowText(str); + if(CSimpleDate::FixDateFormat(str)) + pDX->m_pDlgWnd->GetDlgItem(nID)->SetWindowText(str); + if(CSimpleDate::VerifyDateFormat(str)==FALSE) + { + sprintf(buff,"Invalid Date or Format"); + pDX->m_pDlgWnd->MessageBox(buff,"",MB_OK); + pDX->Fail(); + } + else + pDX->m_pDlgWnd->GetDlgItem(nID)->GetWindowText(str); + } + else + { + pDX->m_pDlgWnd->GetDlgItem(nID)->SetWindowText(str); + } +} + + +//-------------------------------------------------------------------- +// Function name : DDX_SimpleDate +// Description : This is not real efficient but works. Makes extensive use +// of static class members so speed is not the greatest +// Return type : void +// Argument : CDataExchange *pDX +// Argument : int nID +// Argument : long& jdate +//-------------------------------------------------------------------- +void DDX_SimpleDate(CDataExchange *pDX,int nID,long& jdate) +{ + char buff[50]; + pDX->PrepareEditCtrl(nID); + if(jdate < 0) // just a precaution. This way we only check for a 0 value for init + jdate=0; + + if(pDX->m_bSaveAndValidate) + { + pDX->m_pDlgWnd->GetDlgItem(nID)->GetWindowText(buff,50); + if(jdate > 0 && strlen(buff)==0) // program changed value not user input + { + CSimpleDate Date(jdate); + strcpy(buff,(LPCSTR)Date); + pDX->m_pDlgWnd->GetDlgItem(nID)->SetWindowText(buff); + } + if(CSimpleDate::FixDateFormat(buff)) + pDX->m_pDlgWnd->GetDlgItem(nID)->SetWindowText(buff); + + if(CSimpleDate::VerifyDateFormat(buff)==FALSE) + { + sprintf(buff,"Invalid Date or Format"); + pDX->m_pDlgWnd->MessageBox(buff,"",MB_OK); + pDX->Fail(); + } + CSimpleDate Date(buff); + jdate=(long)Date; + } + else + { + if(jdate==0) // had to be init value + strcpy(buff,""); + else + { + CSimpleDate Date(jdate); + strcpy(buff,(LPCSTR)Date); + } + pDX->m_pDlgWnd->GetDlgItem(nID)->SetWindowText(buff); + } +} + +void CSimpleDate::SetDate( int month,int day,int year,int FormatType) +{ +m_Format=FormatType; +m_JulianDate=ConvertToJulian( month, day, year); + +//// Added initialization ///// +m_Year=year; +m_Month=month; +m_Day=day; +////////////////////////////// + +SetTime(); +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.h new file mode 100644 index 0000000..d421096 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleDate.h @@ -0,0 +1,138 @@ +// SimpleDate.h: interface for the CSimpleDate class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_SIMPLEDATE_H__3DD52FF4_4E78_11D3_82D6_00A0CC28BFE2__INCLUDED_) +#define AFX_SIMPLEDATE_H__3DD52FF4_4E78_11D3_82D6_00A0CC28BFE2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +enum{ + MMDDYY, + DDMMYY, + YYMMDD, + MMDDYYYY, + DDMMYYYY, + YYYYMMDD, +}; + +// NOTE:: If you choose any of the two digit year formats you had better be sure all +// dates will be in the range of 1900-1999 else there will be unexpected results + + +#include "Parseit.h" + +class CSimpleDate +{ +public: + // constructors and destructors + CSimpleDate(int FormatType=MMDDYYYY); + CSimpleDate(LPCSTR DateString,int FormatType=MMDDYYYY); + CSimpleDate(long JD,int FormatType=MMDDYYYY); + CSimpleDate(int month,int day,int year,int FormatType=MMDDYYYY); + virtual ~CSimpleDate(); + + // Date math routines + const CSimpleDate& AddDays(int Days); + const CSimpleDate& AddYears(int Yrs); + const CSimpleDate& AddMonths(int Mon); + const CSimpleDate& SubtractYears(int Yrs); + const CSimpleDate& SubtractDays(int Days); + const CSimpleDate& SubtractMonths(int Mon); + virtual int YearsOld(); + + // access routines; + LPCSTR GetFullDateString(); + LPCSTR GetFullDateStringLong(); + virtual int GetDayOfWeek(); + virtual BOOL IsValid(); + long GetJulianDate(); // easier to use (long)CSimpelDate but some prefer this + + virtual int GetDay() + {if(!IsValid()) return 0;return m_Day;}; + virtual int GetMonth() + {if(!IsValid()) return 0;return m_Month;}; + virtual int GetYear() + {if(!IsValid()) return 0;return m_Year;}; + virtual void GetIntegerDate(int& m, int& d,int& y) + {if(!IsValid()) return;m=m_Month;y=m_Year;d=m_Day;}; + virtual int GetHour() + {if(!IsValid()) return 0;return m_Hour+m_bPM*12;}; + virtual int GetMin() + {if(!IsValid()) return 0;return m_Min;}; + virtual int GetSeconds() + {if(!IsValid()) return 0;return m_Second;}; + + virtual void GetTimeString(CString& s,BOOL AmPm=TRUE); + virtual void GetTimeString(LPSTR s,int nLen,BOOL AmPm=TRUE); + virtual void GetTimeStringShort(CString& s,BOOL AmPm=TRUE); + virtual void GetTimeStringShort(LPSTR s,int nLen,BOOL AmPm=TRUE); + + // operator assignments conversions equality etc... + operator LPCSTR(); + operator long(); + const CSimpleDate& operator = (const CSimpleDate& Date); + const CSimpleDate& operator = (LPCSTR Date); + BOOL operator > (const CSimpleDate& Date); + BOOL operator < (const CSimpleDate& Date); + BOOL operator >= (const CSimpleDate& Date); + BOOL operator <= (const CSimpleDate& Date); + BOOL operator == (const CSimpleDate& Date); + BOOL operator != (const CSimpleDate& Date); + BOOL operator > (LPCSTR Date); + BOOL operator < (LPCSTR Date); + BOOL operator >= (LPCSTR Date); + BOOL operator <= (LPCSTR Date); + BOOL operator == (LPCSTR Date); + BOOL operator != (LPCSTR Date); + + + +protected: + // internal class stuff + virtual BOOL SetToday(); + virtual BOOL CSimpleDate::ParseDateString(LPCSTR,int& m,int& d,int& y); + virtual BOOL ParseDateString(LPCSTR); + virtual long ConvertToJulian( int month,int day,int year); + virtual long ConvertToJulian(); + virtual void ConvertFromJulian(int& Month,int& Day,int& Year); + virtual void ConvertFromJulian(); + virtual void AdjustDays(); + virtual void SetTime(); + + // STATIC MEMBER FUNCTIONS +public: + void SetDate(int month,int day,int year,int FormatType=MMDDYYYY); + + // the static functions assume a date format of MMDDYY or MMDDYYYY + // They also do not call this IsValid() function + static BOOL VerifyDateFormat(LPCSTR date); + static BOOL FixDateFormat(CString & date); + static BOOL FixDateFormat(LPSTR date); + + + // class data +protected: + int m_Year; + int m_Month; + int m_Day; + long m_JulianDate; + int m_Format; + CString m_DateString; + + int m_Hour; + int m_Min; + int m_Second; + BOOL m_bPM; + +}; + +// NON Member data exchange functions +void DDX_SimpleDate(CDataExchange *pDX,int nID,LPSTR str,int nLen); +void DDX_SimpleDate(CDataExchange *pDX,int nID,CString& str); +void DDX_SimpleDate(CDataExchange *pDX,int nID,long& jdate); + +#endif // !defined(AFX_SIMPLEDATE_H__3DD52FF4_4E78_11D3_82D6_00A0CC28BFE2__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.cpp new file mode 100644 index 0000000..17d79db --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.cpp @@ -0,0 +1,2534 @@ +// SimpleWODlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "SimpleWODlg.h" +#include "RatesDlg.h" +#include "ContactsViewDlg.h" +#include "probstatdlg.h" +#include +#include ".\simplewodlg.h" +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +//#define _EAF 1 +#define _STARTING_PRINT_COMMAND_ID 32299 +///////////////////////////////////////////////////////////////////////////// +// CSimpleWODlg dialog + + +CSimpleWODlg::CSimpleWODlg(CWnd* pParent /*=NULL*/) +: CDialog(CSimpleWODlg::IDD, pParent) +, m_pSubMenu(NULL) +, m_bShowQueriesOnPrint(false) +, m_bAlertPopup(false) +{ + //{{AFX_DATA_INIT(CSimpleWODlg) + //}}AFX_DATA_INIT + + + m_pApp = (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Quick workorder screen error:"); + rs->SetConnect(m_pApp->strConnectString); + + cbrs=new GZRset("Quick workorder screen contract RS error:"); + cbrs->SetConnect(m_pApp->strConnectString); + + + rsPrint=new GZRset("Quick workorder screen rsPrint error:",true); + rsPrint->SetConnect(m_pApp->strConnectString); + + + //create the extra recordsets to facilitate quick + //saves later on + rsProb=new GZRset("Quick workorder screen Prob table error:"); + rsLabor=new GZRset("Quick workorder screen Labour table error:"); + + rsProb->SetConnect(m_pApp->strConnectString); + rsLabor->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + +rs=m_pApp->rsPool->GetRS("CSimpleWODlg RS"); +cbrs=m_pApp->rsPool->GetRS("CSimpleWODlg CBRS"); +rsProb=m_pApp->rsPool->GetRS("CSimpleWODlg RSPROB"); +rsLabor=m_pApp->rsPool->GetRS("CSimpleWODlg RSLABOR"); +rsPrint=m_pApp->rsPool->GetRSPrint("CSimpleWODlg RSPRINT"); + + + //not editing as far as known + m_bEditing=false; + m_strSelectedRate.Empty(); + m_strSelectedTravelRate.Empty(); + m_strSelectedTech.Empty(); + m_strSelClient.Empty(); + m_strWorkorderID="0"; + +} + + +CSimpleWODlg::~CSimpleWODlg() +{ + + + m_pApp->rsPool->ReleaseRS(&rsLabor->m_nID); + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&cbrs->m_nID); + m_pApp->rsPool->ReleaseRS(&rsPrint->m_nID); + m_pApp->rsPool->ReleaseRS(&rsProb->m_nID); + //_CrtDumpMemoryLeaks(); + +} +void CSimpleWODlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSimpleWODlg) + DDX_Control(pDX, IDC_DATEPICKER2, m_dtEndDate); + DDX_Control(pDX, IDC_LBLTECHNOTES, m_lblTechNotes); + DDX_Control(pDX, IDC_HISTORY, m_lblHistory); + DDX_Control(pDX, IDC_EDOURREFNUMBER2, m_edOurRefNum); + DDX_Control(pDX, IDC_CBSTATUS, m_cbStatus); + DDX_Control(pDX, IDC_lblContactInfo, m_lblContactInfo); + DDX_Control(pDX, IDC_EDCLIENTREFNUM, m_edClientRefNumber); + DDX_Control(pDX, IDC_EDCLIENTCONTACT, m_edClientContact); + DDX_Control(pDX, IDC_LBLCONTRACT, m_lblContract); + DDX_Control(pDX, IDC_TECH_LABEL, m_lblTechList); + DDX_Control(pDX, IDC_TECHLIST, m_cbTechList); + DDX_Control(pDX, IDC_TRAVELRATELABEL, m_lblTravelRate); + DDX_Control(pDX, IDC_TRAVELRATESLIST, m_cbTravelRates); + DDX_Control(pDX, IDC_ONSITE, m_ckOnsite); + DDX_Control(pDX, IDC_DATEPICKER, m_dtDate); + DDX_Control(pDX, IDC_CLIENTLIST_LABEL, m_lblClients); + DDX_Control(pDX, IDC_RATE_LABEL, m_lblRate); + DDX_Control(pDX, IDC_LABEL_CATEGORY, m_lblCategory); + DDX_Control(pDX, IDC_ENDTIMERLABEL, m_lblEnd); + DDX_Control(pDX, IDC_TIMER, m_btnTimer); + DDX_Control(pDX, IDC_GENERALNOTES, m_edDetails); + DDX_Control(pDX, IDC_INVOICENUM, m_edInvoicedOn); + DDX_Control(pDX, IDC_TRAVEL, m_edTravelHours); + DDX_Control(pDX, IDC_NC, m_edNCHours); + DDX_Control(pDX, IDC_BILL, m_edBillHours); + DDX_Control(pDX, IDC_END, m_edEnd); + DDX_Control(pDX, IDC_START, m_edStart); + DDX_Control(pDX, IDC_TYPE, m_cbTypes); + DDX_Control(pDX, IDC_RATESLIST, m_cbRates); + DDX_Control(pDX, IDC_CLIENTLIST, m_cbClients); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_ED_DISTANCE, m_edDistance); + DDX_Control(pDX, IDC_LBLSTATUS, m_lblStatus); +} + +//IDC_LBLSTATUS +BEGIN_MESSAGE_MAP(CSimpleWODlg, CDialog) +//{{AFX_MSG_MAP(CSimpleWODlg) +ON_BN_CLICKED(IDC_TIMER, OnTimer) +ON_BN_CLICKED(IDC_LABEL_CATEGORY, OnLabelCategory) +ON_BN_CLICKED(IDC_RATE_LABEL, OnRateLabel) +ON_BN_CLICKED(IDC_CLIENTLIST_LABEL, OnClientlistLabel) +ON_CBN_CLOSEUP(IDC_TRAVELRATESLIST, OnCloseupTravelrateslist) +ON_CBN_CLOSEUP(IDC_RATESLIST, OnCloseupRateslist) +ON_BN_CLICKED(IDC_TRAVELHOURSLABEL, OnTravelhourslabel) +ON_CBN_CLOSEUP(IDC_TECHLIST, OnCloseupTechlist) +ON_CBN_CLOSEUP(IDC_TYPE, OnCloseupType) +ON_EN_KILLFOCUS(IDC_TRAVEL, OnKillfocusTravel) +ON_EN_KILLFOCUS(IDC_START, OnKillfocusStart) +ON_BN_CLICKED(IDC_ONSITE, OnOnsite) +ON_EN_KILLFOCUS(IDC_NC, OnKillfocusNc) +ON_EN_KILLFOCUS(IDC_INVOICENUM, OnKillfocusInvoicenum) +ON_EN_KILLFOCUS(IDC_GENERALNOTES, OnKillfocusGeneralnotes) +ON_EN_KILLFOCUS(IDC_END, OnKillfocusEnd) +ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DATEPICKER, OnDatetimechangeDatepicker) +ON_CBN_CLOSEUP(IDC_CLIENTLIST, OnCloseupClientlist) +ON_EN_KILLFOCUS(IDC_BILL, OnKillfocusBill) +ON_BN_CLICKED(IDC_LBLCONTRACT, OnLblcontract) +ON_EN_KILLFOCUS(IDC_EDCLIENTCONTACT, OnKillfocusEdclientcontact) +ON_EN_KILLFOCUS(IDC_EDCLIENTREFNUM, OnKillfocusEdclientrefnum) + ON_COMMAND(ID_QUICKWO_DONE, OnQuickwoDone) + ON_COMMAND(ID_QUICKWO_CLIENTNOTES, OnQuickwoClientnotes) + ON_COMMAND(ID_QUICKWO_DELETE, OnQuickwoDelete) + ON_COMMAND(ID_QUICKWO_PRINT, OnQuickwoPrint) + ON_COMMAND(ID_QUICKWO_PRINT_DISPATCH, OnQuickwoPrintDispatch) + ON_EN_KILLFOCUS(IDC_EDOURREFNUMBER2, OnKillfocusEdourrefnumber2) + ON_CBN_CLOSEUP(IDC_CBSTATUS, OnCloseupCbstatus) + ON_BN_CLICKED(IDC_HISTORY, OnHistory) + ON_BN_CLICKED(IDC_LBLTECHNOTES, OnLbltechnotes) + ON_COMMAND(ID_QUICKWO_COSTATUS, OnQuickwoCostatus) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DATEPICKER2, OnDatetimechangeDatepicker2) + ON_BN_CLICKED(IDC_TRAVELRATELABEL, OnTravelratelabel) + //}}AFX_MSG_MAP + ON_EN_KILLFOCUS(IDC_ED_DISTANCE, OnEnKillfocusEdDistance) + ON_COMMAND_RANGE( _STARTING_PRINT_COMMAND_ID, _STARTING_PRINT_COMMAND_ID+100, OnPrintReport ) + ON_BN_CLICKED(IDC_LBLSTATUS, OnStatuslabel) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSimpleWODlg message handlers afx_msg void OnPrintReport( UINT nID ); + + +BOOL CSimpleWODlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + m_resize.Create( this ); + m_resize.Add(IDC_GENERALNOTES,0,0,0,90); + //Use the current width and height as the minimum size + m_resize.SetMinimumTrackingSize(); + Security(); + bool bIsNew=false; + + CMenu* pMenu=this->GetMenu(); + CWaitCursor WAITING; + //if(!m_pApp->m_bTech) + // AfxMessageBox("Not a tech"); + ShowWindow(FALSE); + CString str,q; + long lData=0; + + m_bTiming=false; + + //Contract + m_lblContract.SetTextColor(RGB(255,0,0)); + m_lblContract.SetFontUnderline(TRUE); + m_lblContract.SetFontBold(TRUE); + m_lblContract.SetLink(TRUE); + m_lblContract.SetLinkCursor(m_pApp->hcHand); + m_lblContract.SetLinkURL(""); + + + //Tech notes + m_lblTechNotes.SetTextColor(RGB(255,0,0)); + m_lblTechNotes.SetFontUnderline(TRUE); + m_lblTechNotes.SetFontBold(TRUE); + m_lblTechNotes.SetLink(TRUE); + m_lblTechNotes.SetLinkCursor(m_pApp->hcHand); + m_lblTechNotes.SetLinkURL(""); + + + m_lblHistory.SetTextColor(RGB(0,0,255)); + m_lblHistory.SetFontUnderline(TRUE); + m_lblHistory.SetLink(TRUE); + m_lblHistory.SetLinkCursor(m_pApp->hcHand); + m_lblHistory.SetLinkURL(""); + + //Category hyperlink + m_lblCategory.SetTextColor(RGB(0,0,255)); + m_lblCategory.SetFontUnderline(TRUE); + m_lblCategory.SetLink(TRUE); + m_lblCategory.SetLinkCursor(m_pApp->hcHand); + //empty url means it will not launch explorer + //and can be used as a button instead + m_lblCategory.SetLinkURL(""); + + //Rates dialog hyperlink + m_lblRate.SetTextColor(RGB(0,0,255)); + m_lblRate.SetFontUnderline(TRUE); + m_lblRate.SetLink(TRUE); + m_lblRate.SetLinkCursor(m_pApp->hcHand); + m_lblRate.SetLinkURL(""); + + //Travel Rates dialog hyperlink + m_lblTravelRate.SetTextColor(RGB(0,0,255)); + m_lblTravelRate.SetFontUnderline(TRUE); + m_lblTravelRate.SetLink(TRUE); + m_lblTravelRate.SetLinkCursor(m_pApp->hcHand); + m_lblTravelRate.SetLinkURL(""); + + //Clients dialog hyperlink + m_lblClients.SetTextColor(RGB(0,0,255)); + m_lblClients.SetFontUnderline(TRUE); + m_lblClients.SetLink(TRUE); + m_lblClients.SetLinkCursor(m_pApp->hcHand); + m_lblClients.SetLinkURL(""); + + //v1.9.3.0 Status dialog hyperlink + m_lblStatus.SetTextColor(RGB(0,0,255)); + m_lblStatus.SetFontUnderline(TRUE); + m_lblStatus.SetLink(TRUE); + m_lblStatus.SetLinkCursor(m_pApp->hcHand); + m_lblStatus.SetLinkURL(""); + + //fill combo boxes + FillClientList(); + FillRatesList(); + FillWOTypesList(); + FillTechList(); + FillStatusList(); + FillReportList(); + + //AfxMessageBox(m_cbTechList.GetCurrentRowID()); + //client contact info display + m_lblContactInfo.SetFontBold(TRUE); + m_lblContactInfo.SetFontSize(12); + + //CREATE A NEW WORKORDER IF WERE NOT EDITING AN OLD ONE + if(m_strWorkorderID=="0") + { + //v1.9.4.4 - fix for no techs and trying to make a new work order + if(m_cbTechList.GetCount()==0) + { + //ABORT, no tech + AfxMessageBox("There are no active technicians available!\r\n\r\n" + "A work order can not be created until there is an active technician\r\n" + "entered.\r\n\r\n" + "(Use the: Options->Edit->Users&Rights menu sequence.)\r\n",MB_ICONSTOP); + CDialog::OnCancel(); + return FALSE; + + } + bIsNew=true; + //start a new workorder: + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + q.Format("INSERT INTO wo ( creator, created, modifier, modified ) " + "SELECT %u, #%s#,%u, #%s#;",m_pApp->m_lusrID,dtData.Format(_T("%m/%d/%Y %H:%M:%S")),m_pApp->m_lusrID,dtData.Format(_T("%m/%d/%Y %H:%M:%S"))); + + rs->Ex(q,&lData); + rs->Close(); + m_strWorkorderID.Format("%u",lData); + m_strID.Format("%u",lData); + str.Format("Quick WO#: %s",m_strID); + SetWindowText(str); + // str="Quick Workorder - "+ m_pApp->m_strCurrentUserName; + // SetWindowText(str); + m_dtDate.SetTime(dtData); + m_edNCHours.SetWindowText("0"); + m_edTravelHours.SetWindowText("0"); + m_edDistance.SetWindowText("0"); + m_edBillHours.SetWindowText("0"); + m_edStart.SetWindowText("12:00"); + m_edEnd.SetWindowText("12:00"); + //SET USER DEFAULTS + m_ckOnsite.SetCheck(m_pApp->m_bDefOnsite ? TRUE : FALSE); + m_cbRates.Select(m_pApp->m_lUsersDefRate); + m_cbTravelRates.Select(m_pApp->m_lUsersDefTravelRate); + + // SET THE DEFAULT STATUS of this new workorder + m_cbStatus.Select(m_pApp->m_lDefNewWOStatus); + + pMenu->ModifyMenu(ID_QUICKWO_DELETE,MF_BYCOMMAND,ID_QUICKWO_DELETE,"Cancel add"); + + } + else//yes we are editing, fill in the fields + { + //no timer if editing.!@#$@!#$! + m_btnTimer.ShowWindow(FALSE); + FillFields(); + FillRatesList(); + + } + + if(m_bEditing) + Check4Contract(false); + /////////ShowWindow(SW_SHOWMAXIMIZED); + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + //added 6/24/2001 to avoid mouse wheel accidental cust change when viewing only + if(bIsNew) + m_cbClients.SetFocus(); + else + m_edDetails.SetFocus(); + return FALSE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CSimpleWODlg::FillClientList() +{ + + + CString strData; + CString strIndex; + CString strHead,q; + long lData; + m_cbClients.Clear(); + m_cbClients.AddRow(" ","0"); + lData=0; + + q.Format("SELECT clients.id, clients.company AS compname FROM clients WHERE (((clients.isheadoffice)=False)) " + "ORDER BY clients.company;"); + cbrs->QueryReadOnly(q); + + + + + + if(!cbrs->IsEmpty()) + { + //fill combo box with available clients + VERIFY(cbrs->MoveFirst()); + VERIFY(cbrs->FetchField("compname",&strData)); + VERIFY(cbrs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbClients.AddRow(strData,strIndex); + while(cbrs->MoveForward()) + { + VERIFY(cbrs->FetchField("compname",&strData)); + VERIFY(cbrs->FetchField("id",&lData)); + strIndex.Format("%u",lData); + m_cbClients.AddRow(strData,strIndex); + } + + m_cbClients.SetCurSel(0); + + }//is no records? + + + + + +} + +void CSimpleWODlg::FillRatesList() +{ + //fill travel and regular rates list boxes + CString strData; + CString strIndex; + long lData; + bool bData,bActive; + m_cbTravelRates.Clear(); + m_cbRates.Clear(); + cbrs->QueryReadOnly("SELECT rates.* FROM rates ORDER BY rates.name;"); + if(!cbrs->IsEmpty()) + { + //fill combo box with available RATES + + + do + { + cbrs->FetchField("travelrate",&bData); + cbrs->FetchField("name",&strData); + cbrs->FetchField("id",&lData); + cbrs->FetchField("active",&bActive); + strIndex.Format("%u",lData); + + if(bData==true)//it's a travel rate + { + if(bActive) + m_cbTravelRates.AddRow(strData,strIndex); + else + { + if(m_strSelectedTravelRate==strIndex)//inactive but selected + { + strData=" " + strData; + m_cbTravelRates.AddRow(strData,strIndex); + + } + + + } + } + else//it's a standard rate + { + if(bActive) + m_cbRates.AddRow(strData,strIndex); + else + { + if(m_strSelectedRate==strIndex)//inactive but selected + { + strData=" " + strData; + m_cbRates.AddRow(strData,strIndex); + + } + } + } + }while(cbrs->MoveForward()); + + + + //select default rate + if(m_strSelectedRate.IsEmpty()) + { + m_cbRates.SetCurSel(0); + m_strSelectedRate=m_cbRates.GetCurrentRowID(); + } + else + m_cbRates.Select(m_strSelectedRate); + + //select default travel rate + if(m_strSelectedTravelRate.IsEmpty()) + { + m_cbTravelRates.SetCurSel(0); + m_strSelectedTravelRate=m_cbTravelRates.GetCurrentRowID(); + } + else + m_cbTravelRates.Select(m_strSelectedTravelRate); + + } +} + +void CSimpleWODlg::FillWOTypesList() +{ + CString strData; + CString strIndex; + long lData; + m_cbTypes.Clear(); + m_cbTypes.AddRow("< No category >","0"); + cbrs->QueryReadOnly("SELECT wotypes.* FROM wotypes ORDER BY wotypes.category;"); + if(!cbrs->IsEmpty()) + { + //fill combo box with available categories + cbrs->MoveFirst(); + cbrs->FetchField("category",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTypes.AddRow(strData,strIndex); + while(cbrs->MoveForward()) + { + cbrs->FetchField("category",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTypes.AddRow(strData,strIndex); + } + + m_cbTypes.SetCurSel(0); + } +} + + + + +void CSimpleWODlg::OnTimer() +{ + CString str; + double secs; + COleDateTimeSpan sp; + if(!m_bTiming)//then start the timer + { + //see if there is a start time already + m_edStart.GetWindowText(str); + if(!str.IsEmpty()) + { + if(AfxMessageBox("Reset start time and start timer?\r\nAre you sure?",MB_YESNO)==IDNO) + return; + } + + dt1=COleDateTime::GetCurrentTime(); + str=dt1.Format(VAR_TIMEVALUEONLY); + m_edStart.SetWindowText(str); + m_edEnd.SetWindowText("Timing..."); + m_btnTimer.SetWindowText("Stop timer"); + m_lblEnd.SetFontBold(TRUE); + m_lblEnd.SetTextColor(RGB(255,0,0)); + m_lblEnd.FlashText(TRUE); + m_bTiming=true; + } + else//stop the timer + { + dt2=COleDateTime::GetCurrentTime(); + str=dt2.Format(VAR_TIMEVALUEONLY); + m_edEnd.SetWindowText(str); + m_btnTimer.SetWindowText("Timer"); + m_lblEnd.SetFontBold(FALSE); + m_lblEnd.SetTextColor(RGB(0,0,0)); + m_lblEnd.FlashText(FALSE); + m_bTiming=false; + sp=dt2-dt1; + secs=sp.GetTotalMinutes(); + secs=secs/60; + //strData.Format("%g",fData); + //01/31/2003 localization fix for floats + //convert float to localized string + m_edBillHours.SetWindowText(FtoA(secs)); + } + +} + +void CSimpleWODlg::OnLabelCategory() +{ + CString str; + CWOTypesDlg d; + d.SetReturnString(&str); + if(d.DoModal()==IDOK) + { + //fill category list + FillWOTypesList(); + //select str string; + m_cbTypes.Select(str); + } +} + +void CSimpleWODlg::OnRateLabel() +{ + + CRatesDlg d; + if(d.DoModal()==IDOK) + FillRatesList(); + +} + + +//**************************************** +void CSimpleWODlg::OnClientlistLabel() +{ + CString str; + CClientsDlg d; + d.SetReturnString(&str); + //Added 08/28/2001 to pre-select client on clients screen + d.m_strForceSelection=m_strSelClient; + if(d.DoModal()==IDOK) + { + FillClientList(); + m_cbClients.Select(str); + } + //FillFields(); +} +//---------------------------------------- + +//******************************** +void CSimpleWODlg::OnOK() +{ + + +} + + +//************************************************* +//Pass in ID of workorder we want to edit/display +void CSimpleWODlg::SetWorkorderID(CString *pstrWOID) +{ + + //set the workorder to display + m_strWorkorderID=*pstrWOID; + //flag that were in editing mode + if(m_strWorkorderID!="0") m_bEditing=true; +} + +void CSimpleWODlg::OnCloseupTravelrateslist() +{ + m_strSelectedTravelRate=m_cbTravelRates.GetCurrentRowID(); + + SaveField(&m_cbTravelRates,"travrate",rsLabor); + + +} + +void CSimpleWODlg::OnCloseupRateslist() +{ + m_strSelectedRate=m_cbRates.GetCurrentRowID(); + SaveField(&m_cbRates,"rate",rsLabor); +} + +void CSimpleWODlg::OnTravelhourslabel() +{ + //same deal whichever gets clicked + //FUTURE: make it only show travel rates + //and vice versa depending on what gets clicked + OnRateLabel(); +} + + +//fill the fields if this is an editing workorder// +void CSimpleWODlg::FillFields() +{ + if(!m_bEditing) return; + //m_strWorkorderID + CString q,strData,strProblemID; + bool bData; + float fData; + COleDateTime dtData; + long lData; + + + + + q.Format("SELECT wo.* FROM wo WHERE (((wo.id)=%s));",m_strWorkorderID); + rs->Query(q); + if(rs->IsEmpty()) + { + AfxMessageBox("Can't find workorder record"); + CDialog::OnOK(); + return; + } + + strData.Format("Quick WO#: %s",m_strWorkorderID); + SetWindowText(strData); + + //OUR REFERENCE NUMBER + rs->FetchField("ourref",&strData); + m_edOurRefNum.SetWindowText(strData); + + //STATUS + rs->FetchField("status",&lData); + strData.Format("%u",lData); + m_cbStatus.Select(strData); + + //CLIENT + rs->FetchField("client",&lData); + strData.Format("%u",lData); + m_cbClients.Select(strData); + m_strSelClient=strData; + + //CATEGORY + rs->FetchField("type",&lData); + strData.Format("%u",lData); + m_cbTypes.Select(strData); + + //ONSITE + rs->FetchField("onsite",&bData); + m_ckOnsite.SetCheck(bData ? TRUE:FALSE); + +/* //DATE + rs->FetchField("closed",&dtData); + m_dtDate.SetTime(dtData); + */ + +//CLOSED/OPEN + rs->FetchField("closed",&dtData); + //commented out 10/11/2002 get from labor table instead + //m_dtDate.SetTime(dtData); + m_bIsOpen=false; + if(dtData.GetYear()==1968)//it's open + m_bIsOpen=true; + UpdateClosedOpen(); + + + //**************** + //commented out 10/11/2002, should get from labor table + //not workorder header table + + ////STARTTIME + //rs->FetchField("starttime",&dtData); + //strData=dtData.Format(VAR_TIMEVALUEONLY); + //m_edStart.SetWindowText(strData); + // + ////STOPTIME + //rs->FetchField("stoptime",&dtData); + + //added June 23 2001 to support end date values + //m_dtEndDate.SetTime(dtData); + //*********************** + + strData=dtData.Format(VAR_TIMEVALUEONLY); + m_edEnd.SetWindowText(strData); + + //INVOICE NUMBER + rs->FetchField("invoice",&strData); + m_edInvoicedOn.SetWindowText(strData); + + //CLIENT REFERENCE NUMBER + rs->FetchField("clientrefnum",&strData); + m_edClientRefNumber.SetWindowText(strData); + + //CLIENT CONTACT + rs->FetchField("clientcontact",&strData); + m_edClientContact.SetWindowText(strData); + + //FETCH THE PROBLEM RECORD FIELDS + q.Format("SELECT probs.* FROM probs WHERE (((probs.wolink)=%s));",m_strWorkorderID); + rsProb->Query(q); + if(rsProb->IsEmpty()) + { + AfxMessageBox("Can't find workorder problem record\r\nThis quick workorder is damaged or incomplete."); + CDialog::OnOK(); + return; + } + + + //get id + rsProb->FetchField("id",&lData); + strProblemID.Format("%u",lData); + + + //FETCH THE BILLABLE LABOUR RECORD + q.Format("SELECT labor.* FROM labor " + "LEFT JOIN rates ON labor.rate = rates.id " + "WHERE (((labor.link)=%s));",strProblemID); + + rsLabor->Query(q); + if(rsLabor->IsEmpty()) + return; + + //START + rsLabor->FetchField("start",&dtData); + strData=dtData.Format(VAR_TIMEVALUEONLY); + m_edStart.SetWindowText(strData); + m_dtDate.SetTime(dtData); + + //STOP + rsLabor->FetchField("stop",&dtData); + strData=dtData.Format(VAR_TIMEVALUEONLY); + m_edEnd.SetWindowText(strData); + m_dtEndDate.SetTime(dtData); + + //HOURS + rsLabor->FetchField("hours",&fData); + //strData.Format("%g",fData); + //01/31/2003 localization fix for floats + //convert float to localized string + m_edBillHours.SetWindowText(FtoA(fData)); + + + //NOCHARGE HOURS + rsLabor->FetchField("nchours",&fData); + //01/31/2003 localization fix for floats + //convert float to localized string + m_edNCHours.SetWindowText(FtoA(fData)); + + + //TECHNICIAN + rsLabor->FetchField("tech",&lData); + m_strSelectedTech.Format("%u",lData); + FillTechList(); + + //RATE + rsLabor->FetchField("rate",&lData); + strData.Format("%u",lData); + m_strSelectedRate=strData; + m_cbRates.Select(strData); + + + //DETAILS + rsLabor->FetchField("details",&strData); + m_edDetails.SetWindowText(strData); + + + //TRAVEL HOURS + rsLabor->FetchField("travhours",&fData); + //01/31/2003 localization fix for floats + //convert float to localized string + m_edTravelHours.SetWindowText(FtoA(fData)); + + //TRAVEL RATE + rsLabor->FetchField("travrate",&lData); + strData.Format("%u",lData); + m_strSelectedTravelRate=strData; + m_cbTravelRates.Select(strData); + + //DISTANCE + rsLabor->FetchField("distance",&fData); + //01/31/2003 localization fix for floats + //convert float to localized string + m_edDistance.SetWindowText(FtoA(fData)); + + q.Format("SELECT wo.* FROM wo WHERE (((wo.id)=%s));",m_strWorkorderID); + rs->Query(q); + + DisplayContactInfo(); +} + +void CSimpleWODlg::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_cbTechList.Clear(); + //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->QueryReadOnly(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=" " + strData; + m_cbTechList.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->QueryReadOnly(q); + if(!cbrs->IsEmpty()) + { + cbrs->MoveFirst(); + cbrs->FetchField("fullname",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTechList.AddRow(strData,strIndex); + while(cbrs->MoveForward()) + { + cbrs->FetchField("fullname",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbTechList.AddRow(strData,strIndex); + } + + } + + + if(!m_strSelectedTech.IsEmpty()) + m_cbTechList.Select(m_strSelectedTech); + else + {//attempt to select by current user id + m_strSelectedTech.Format("%u",m_pApp->m_lusrID); + m_cbTechList.Select(m_strSelectedTech); + } + + + + + + +} + +void CSimpleWODlg::OnCloseupTechlist() +{ + + m_strSelectedTech=m_cbTechList.GetCurrentRowID(); + SaveField(&m_cbTechList,"tech",rsLabor); + //added 10/10/2002 to ensure that main workorder list view + //shows the tech assigned to the workorder + SaveField(&m_cbTechList,"assigntech",rs); + //v1.9.4.4 to set rate based on selected tech, not current user id + SetClientRates(); +} + +void CSimpleWODlg::OnCloseupType() +{ + + SaveField(&m_cbTypes,"type",rs); + + + +} + +void CSimpleWODlg::OnKillfocusTravel() +{ + + if(m_edTravelHours.GetModify()==FALSE) return; + + CString strData; + float fData; + + m_edTravelHours.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 + + //v1.9.4.4 added try / catch mechanism to catch dumb-asses entering text in a numeric field + try{ + fData=(float)vtData;//cast variant to float (locale friendly) + } + catch( _com_error &e ) + { + + AfxMessageBox("I could not interpret your entry in the Travel hours 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_edTravelHours.Undo(); + m_edTravelHours.SetModify(FALSE); + m_edTravelHours.SetFocus(); + return; + } + +if(!m_bEditing) return; + rsLabor->UpdateField("travhours",&fData); + rsLabor->SaveRecord(); + m_edTravelHours.SetModify(FALSE); + +} + + +void CSimpleWODlg::OnEnKillfocusEdDistance() +{ + if( m_edDistance.GetModify()==FALSE) return; + + CString strData; + float fData; + + m_edDistance.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 variant to float (locale friendly) + + //v1.9.4.4 added try / catch mechanism to catch dumb-asses entering text in a numeric field + try{ + fData=(float)vtData;//cast variant to float (locale friendly) + } + catch( _com_error &e ) + { + + AfxMessageBox("I could not interpret your entry in the Distance 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_edDistance.Undo(); + m_edDistance.SetModify(FALSE); + m_edDistance.SetFocus(); + return; + } + + //v1.9.4.4 moved down to here so validation occurs even on a new record + if(!m_bEditing) return; + rsLabor->UpdateField("distance",&fData); + rsLabor->SaveRecord(); + m_edDistance.SetModify(FALSE); +} + +void CSimpleWODlg::OnKillfocusStart() +{ + //test 10/11/2002, required for saving properly now + //if(m_edStart.GetModify()==FALSE) return; + + COleDateTime dtDate,dtTime; + m_dtDate.GetTime(dtDate); + CString strData; + m_edStart.GetWindowText(strData); + if(dtTime.ParseDateTime(strData,VAR_TIMEVALUEONLY)==FALSE) + { + AfxMessageBox("Invalid time entered.\r\n" + "You can enter time in many ways\r\n" + "We find it faster to use the period\r\n" + "symbol rather than a colon during entry.\r\n\r\n" + "Here are some examples of valid entry:\r\n" + "22.23 is interpreted as 10:00pm\r\n" + "9.0 = 9:00am\r\n" + "4.3p = 4:03pm\r\n" + "good old fashioned 12:30 still = 12:30pm\r\n" + "Outside north america valid entries\r\n" + "for your locale may be different"); + return; + } + + + strData=dtTime.Format(VAR_TIMEVALUEONLY); + m_edStart.SetWindowText(strData); + + if(!m_bEditing) return ;//dont attempt to update + + + //REMOVED following block 10/11/2002 + //to use labor table for dates exclusively now + //save the time only value in the workorder header + //rs->UpdateField("starttime",&dtTime); + //rs->SaveRecord(); + + //save the complete date/time in the labor record. Guichy! + dtTime.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + rsLabor->UpdateField("start",&dtTime); + rsLabor->SaveRecord(); + + m_edStart.SetModify(FALSE); + +} + +void CSimpleWODlg::OnOnsite() +{ + SaveField(&m_ckOnsite,"onsite",rs); +} + +void CSimpleWODlg::OnKillfocusNc() +{ + if( m_edNCHours.GetModify()==FALSE) return; + CString strData; + float fData; + //NOCHARGE HOURS + m_edNCHours.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 variant to float (locale friendly) + +//v1.9.4.4 added try / catch mechanism to catch dumb-asses entering text in a numeric field + try{ + fData=(float)vtData;//cast variant to float (locale friendly) + } + catch( _com_error &e ) + { + + AfxMessageBox("I could not interpret your entry in the No charge hours 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_edNCHours.Undo(); + m_edNCHours.SetModify(FALSE); + m_edNCHours.SetFocus(); + return; + } +//v1.9.4.4 moved down to here so validation occurs even on a new record + if(!m_bEditing) return; + + rsLabor->UpdateField("nchours",&fData); + rsLabor->SaveRecord(); + m_edNCHours.SetModify(FALSE); +} + +void CSimpleWODlg::OnKillfocusInvoicenum() +{ + SaveField(&m_edInvoicedOn,"invoice",true,rs); + + +} + +void CSimpleWODlg::OnKillfocusGeneralnotes() +{ + //DETAILS + SaveField(&m_edDetails,"details",true,rsLabor); + +} + +void CSimpleWODlg::OnKillfocusEnd() +{ + //wo=stoptime,labor=stop + + + + //no changes then don't bother + //removed 06/23/01 to support end date + //because this is called when the end date is changed to handle both end date + //and end time + //if(m_edEnd.GetModify()!=TRUE) return; + + + + COleDateTime dtDate,dtTime; + m_dtEndDate.GetTime(dtDate); + CString strData; + m_edEnd.GetWindowText(strData); + + if(dtTime.ParseDateTime(strData,VAR_TIMEVALUEONLY)==FALSE) + { + AfxMessageBox("Invalid time entered.\r\n" + "You can enter time in many ways\r\n" + "We find it faster to use the period\r\n" + "symbol rather than a colon during entry.\r\n\r\n" + "Here are some examples of valid entry:\r\n" + "22.23 is interpreted as 10:00pm\r\n" + "9.0 = 9:00am\r\n" + "4.3p = 4:03pm\r\n" + "good old fashioned 12:30 still = 12:30pm\r\n" + "Outside north america valid entries\r\n" + "for your locale may be different"); + return; + } + + strData=dtTime.Format(VAR_TIMEVALUEONLY); + m_edEnd.SetWindowText(strData); + if(!m_bEditing) return ;//dont attempt to update + + //moved up here 06/23/01 to save full date and time info in both woheader and labour + dtTime.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + //save the time (and now date value 6/23/01) in the workorder header + //rs->UpdateField("stoptime",&dtTime); + //rs->SaveRecord(); + //save the complete date/time in the labor record. Guichy! + //dtTime.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + rsLabor->UpdateField("stop",&dtTime); + rsLabor->SaveRecord(); + + m_edEnd.SetModify(FALSE); + +} + +//start date +void CSimpleWODlg::OnDatetimechangeDatepicker(NMHDR* pNMHDR, LRESULT* pResult) +{ + COleDateTime dtData; + m_dtDate.GetTime(dtData); + m_dtEndDate.SetTime(dtData); + + SaveField(&m_dtDate,"closed",rs); + SaveField(&m_dtDate,"created",rs); + + //SaveField(&m_dtDate,"closed",rs); + + //TEST 10/11/2002 + OnKillfocusStart(); + //added July 20 2001 as end date still not being saved + OnKillfocusEnd(); + *pResult = 0; +} + +//end date +void CSimpleWODlg::OnDatetimechangeDatepicker2(NMHDR* pNMHDR, LRESULT* pResult) +{ + + OnKillfocusEnd(); + *pResult = 0; +} + + +void CSimpleWODlg::OnCloseupClientlist() +{ + if(m_cbClients.GetCurrentRowID()=="0") return; +if(m_bAlertPopup) + return; + //Added check to avoid repetition if client not changed + CString strData; + strData=m_cbClients.GetCurrentRowID(); + if(strData==m_strSelClient) return; + + m_strSelClient=m_cbClients.GetCurrentRowID(); + + + + SaveField(&m_cbClients,"client",rs); + Check4Contract(true); + SetClientRates(); + DisplayContactInfo(); + //Added 10/17/2002 to ensure correct client is selected after a popup + //reason being that popping up a dialog box kills focus on the client drop down + //which hasn't fully finished updating yet + //this cased one of our clients to send a tech to Montreal instead of Toronto + //as the previously selected client remained due to the popup causing + //the list box to not update to the new client + m_cbClients.Select(m_strSelClient); +} + +void CSimpleWODlg::OnKillfocusBill() +{ + if(m_edBillHours.GetModify()==FALSE) return; + CString strData; + float fData; + + m_edBillHours.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); + 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 Billable hours 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_edBillHours.Undo(); + m_edBillHours.SetModify(FALSE); + m_edBillHours.SetFocus(); + return; + } + +//v1.9.4.4 moved down to here so validation occurs even on a new record + if(!m_bEditing) return; + + + rsLabor->UpdateField("hours",&fData); + rsLabor->SaveRecord(); + m_edBillHours.SetModify(FALSE); +} + + + + +//************************************************************ +//SAVE EDIT CONTROL FIELD +//************************************************************ +bool CSimpleWODlg::SaveField(CEdit *edControl,CString fldname,bool AllowEmpty,GZRset* rsSet) +{ + + if(!m_bEditing) return true;//dont attempt to update + CString str; + //do nothing if not changed + if(edControl->GetModify()!=TRUE) return true; + + edControl->GetWindowText(str); + //dont save empty fields if not allowed to + if(!AllowEmpty) + { + + if(str.IsEmpty()) + { + edControl->Undo(); + return false; + } + } + + + rsSet->UpdateField(fldname,&str); + rsSet->SaveRecord(); + UpdateModified(); + edControl->SetModify(FALSE); + return true; +} + +//************************************************************ +//SAVE GZCOMBO CONTROL FIELD +//************************************************************ +bool CSimpleWODlg::SaveField(CgzCombo *cbControl,CString fldname,GZRset* rsSet) +{ + + if(!m_bEditing) return true;//dont attempt to update + CString str; + long lData; + str=cbControl->GetCurrentRowID(); + if(str.IsEmpty()) return false;//shouldn't happen but... + lData=atol(str); + rsSet->UpdateField(fldname,&lData); + rsSet->SaveRecord(); + UpdateModified(); + return true; +} + +//************************************************************ +//SAVE CheckBox CONTROL FIELD +//************************************************************ +bool CSimpleWODlg::SaveField(CButton *ckControl,CString fldname,GZRset* rsSet) +{ + if(!m_bEditing) return true;//dont attempt to update + bool bData=false; + BOOL BData; + BData=ckControl->GetCheck(); + if(BData==TRUE) bData=true; + rsSet->UpdateField(fldname,&bData); + rsSet->SaveRecord(); + UpdateModified(); + return true; +} +//************************************************************ +//SAVE DateTimePicker CONTROL FIELD +//************************************************************ +bool CSimpleWODlg::SaveField(CDateTimeCtrl *dtControl,CString fldname,GZRset* rsSet) +{ + if(!m_bEditing) return true;//dont attempt to update + COleDateTime dtData; + dtControl->GetTime(dtData); + rsSet->UpdateField(fldname,&dtData); + rsSet->SaveRecord(); + UpdateModified(); + return true; +} + + +//************************************************ +//UPDATE MODIFIED DATA +//************************************************* +bool CSimpleWODlg::UpdateModified() +{ + + m_pApp->m_bRefreshStatScreen=true; + + + + bool bIndexed=false; + //updates modified by and modified on fields + + rs->UpdateField("modifier",&m_pApp->m_lusrID); + COleDateTime dtData; + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("modified",&dtData); + + //flag as now not indexed any longer + //note: may not be true if the labour + //table parts of this wo were not modified, but + //who cares, this is simpler and wont make much + //difference in the big picture. + rsLabor->UpdateField("indexed",&bIndexed); + rsLabor->SaveRecord(); + rs->SaveRecord(); + + + return true; +} + + + + + +//checks for contract and also checks for tech notes and also popup alert message + +void CSimpleWODlg::Check4Contract(bool bAlert) +{ + CString q,client,strAlert; + client=m_cbClients.GetCurrentRowID(); + long lContract,lHeadOffice; + //check for contract + m_lblContract.ShowWindow(FALSE); + m_strClientContractID.Empty(); + //See if client has a contract + //if so, this will supersede head office so + //get contract number and return + q.Format("SELECT [clients].[contract], [clients].[headoffice], [clients].[technotes], [clients].[alert] " + "FROM clients WHERE ((([clients].[id])=%s) And " + "(([clients].[isheadoffice])=False));",client); + cbrs->QueryReadOnly(q); + ASSERT(!cbrs->IsEmpty()); + cbrs->FetchField("contract",&lContract); + cbrs->FetchField("headoffice",&lHeadOffice); + cbrs->FetchField("technotes",&m_strTechNotes); + cbrs->FetchField("alert",&strAlert); + if(bAlert) + { + if(!strAlert.IsEmpty()) + { + m_bAlertPopup=true; + AfxMessageBox(strAlert); + m_bAlertPopup=false; + } + } + + if(m_strTechNotes.IsEmpty()) + m_lblTechNotes.ShowWindow(FALSE); + else + m_lblTechNotes.ShowWindow(TRUE); + + + if(lContract>0) + { + m_lblContract.ShowWindow(TRUE); + m_strClientContractID.Format("%u",lContract); + return; + } + if(lHeadOffice==0) return;//no head office no point in proceeding + + //Client has no contract, but does have a head + //office which may have a contract... + q.Format("SELECT clients.contract " + "FROM clients WHERE (((clients.id)=%u));",lHeadOffice); + cbrs->QueryReadOnly(q); + ASSERT(!cbrs->IsEmpty()); + cbrs->FetchField("contract",&lContract); + if(lContract>0) + { + m_lblContract.ShowWindow(TRUE); + m_strClientContractID.Format("%u",lContract); + } + +} + +void CSimpleWODlg::OnLblcontract() +{ + CString q,name,terms; + + q.Format("SELECT contracts.name, contracts.terms FROM contracts " + "WHERE (((contracts.id)=%s));",m_strClientContractID); + cbrs->QueryReadOnly(q); + if(cbrs->IsEmpty()) + { + AfxMessageBox("Contract is missing!"); + return; + } + + cbrs->FetchField("name",&name); + cbrs->FetchField("terms",&terms); + q.Format("Contract:\r\n%s\r\n\r\nTerms:\r\n%s",name,terms); + AfxMessageBox(q); + +} + +//Extensively modified for v1.9.4.4 +//now sets rates based on selected tech not current users id +//also now skips changing settings if hours are non-zero +void CSimpleWODlg::SetClientRates() +{ + + + CString q; + //Dont change a thing if hours were entered + m_edBillHours.GetWindowText(q); + if(q!="0") return; + + //long lData; + long lClientDefRate,lClientDefTravelRate; + long lSelectedTechDefRate,lSelectedTechDefTravelRate; + + + //Get clients default rates + q.Format("SELECT clients.defrate, clients.deftravelrate " + "FROM clients " + "WHERE (((clients.id)=%s));",m_cbClients.GetCurrentRowID()); + + cbrs->QueryReadOnly(q); + if(cbrs->IsEmpty()) + { + + lClientDefRate=0; + lClientDefTravelRate=0; + } + else + { + cbrs->FetchField("defrate",&lClientDefRate); + cbrs->FetchField("deftravelrate",&lClientDefTravelRate); + } + cbrs->Close(); + + //Get selected tech's default rates + q.Format("SELECT users.defrate, users.deftravelrate " + "FROM users " + "WHERE (((users.id)=%s));",m_cbTechList.GetCurrentRowID()); + + cbrs->QueryReadOnly(q); + if(cbrs->IsEmpty()) + { + + lSelectedTechDefRate=0; + lSelectedTechDefTravelRate=0; + } + else + { + cbrs->FetchField("defrate",&lSelectedTechDefRate); + cbrs->FetchField("deftravelrate",&lSelectedTechDefTravelRate); + } + cbrs->Close(); + + + +//Set rate to client or selected tech as appropriate + + if(lClientDefRate!=0) + m_cbRates.Select(lClientDefRate); + else + m_cbRates.Select(lSelectedTechDefRate); + + + //Set travel rate + if(lClientDefTravelRate!=0) + m_cbTravelRates.Select(lClientDefTravelRate); + else + m_cbTravelRates.Select(lSelectedTechDefTravelRate);//v1.9.4.4 + + + +} + +bool CSimpleWODlg::SaveNewRecord() +{ + + m_pApp->m_bRefreshStatScreen=true; + + long lData,lLink; + CString strData,q; + COleDateTime dtData,dtTime,dtDate,dtEndDate; + bool bData; + float fData;//single + if(m_cbClients.GetCurrentRowID()=="0") + { + AfxMessageBox("Please choose a client first"); + return false; + + } + + rs->Close(); + q.Format("SELECT wo.* FROM wo WHERE (((wo.id)=%s));",m_strWorkorderID); + rs->Query(q); + + + + //otherwise save new record + + //validate everything + + //Save the workorder fields + + //CLIENT + lData=atol(m_cbClients.GetCurrentRowID()); + ASSERT(lData>0); + rs->UpdateField("client",&lData); + + //CATEGORY + lData=atol(m_cbTypes.GetCurrentRowID()); + rs->UpdateField("type",&lData); + + //CLOSED - time workorder closed + //keep the date for later on processing + //m_dtDate.GetTime(dtDate); + //m_dtEndDate.GetTime(dtEndDate); + dtDate=COleDateTime::GetCurrentTime(); + rs->UpdateField("closed",&dtDate); + rs->UpdateField("created",&dtDate); + + //ONSITE + bData= m_ckOnsite.GetCheck() ? true:false; + rs->UpdateField("onsite",&bData); + + //Following block commented out 10/11/2002 + //fixed to use labor table times instead + ////STARTTIME + //m_edStart.GetWindowText(strData); + //dtData.ParseDateTime(strData,VAR_TIMEVALUEONLY); + //rs->UpdateField("starttime",&dtData); + // + ////STOPTIME + //m_edEnd.GetWindowText(strData); + //dtTime.ParseDateTime(strData,VAR_TIMEVALUEONLY); + //dtData.SetDateTime(dtEndDate.GetYear(),dtEndDate.GetMonth(),dtEndDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + // + //rs->UpdateField("stoptime",&dtData); + + //QUICK - flag this as a quickie workorder + //so that it gets displayed on this screen + //when selected to view + bData=true; + rs->UpdateField("quick",&bData); + + + + //INVOICE # + m_edInvoicedOn.GetWindowText(strData); + rs->UpdateField("invoice",&strData); + + //CLIENT REFERENCE NUMBER + m_edClientRefNumber.GetWindowText(strData); + rs->UpdateField("clientrefnum",&strData); + + //OUR REFERENCE NUMBER + m_edOurRefNum.GetWindowText(strData); + rs->UpdateField("ourref",&strData); + + //CLIENT CONTACT + m_edClientContact.GetWindowText(strData); + rs->UpdateField("clientcontact",&strData); + + //added 10/13/2002 to ensure that main workorder list view + //shows the tech assigned to the workorder + //ASSIGNTECH + //SaveField(&m_cbTechList,"assigntech",rs); + lData=atol(m_cbTechList.GetCurrentRowID()); + rs->UpdateField("assigntech",&lData); + + + rs->SaveRecord(); + rs->Close(); + + + //rs->FetchField("quick",&bData); + //ASSERT(bData==TRUE); + + //Create a problem record + + //open the probs table, return no records + rs->Query("SELECT probs.* FROM probs WHERE (((probs.id)=0));"); + + rs->AddNewRecord(); + + + ASSERT(!m_strID.IsEmpty()); + + //SAVE THE WORKORDER ID NUMBER + rs->UpdateField("wolink",&m_strID); + + //STATUS to zero + lData=0; + rs->UpdateField("status",&lData); + + //CREATOR + rs->UpdateField("creator",&m_pApp->m_lusrID); + + //CREATED + rs->UpdateField("created",&dtDate);//dtdate set earlier + + //CREATOR + rs->UpdateField("modifier",&m_pApp->m_lusrID); + + //CREATED + rs->UpdateField("modified",&dtDate);//dtdate set earlier + + //Save problem record + rs->SaveRecord(); + rs->Close(); + + //get id of problem record + q.Format("SELECT probs.id FROM probs " + "WHERE (((probs.wolink)=%s) AND " + "((probs.status)=0) AND " + "((probs.creator)=%u));",m_strID,m_pApp->m_lusrID); + + + rs->Query(q); + + + lLink=0; + rs->FetchField("id",&lLink); + ASSERT(lLink!=0); + + + //************************************ + //************************************ + //Use id to create a labour table record + //firstly open the labor table in a way that returns no records + rs->Query("SELECT labor.* FROM labor WHERE (((labor.link)=0));"); + rs->AddNewRecord(); + //set labour record fields + + //LINK TO PROBLEM RECORD + rs->UpdateField("link",&lLink); + + //TECH + strData=m_cbTechList.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("tech",&lData); + + + //HOURS + m_edBillHours.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 variant to float (locale friendly) + //fData=(float)atof(strData); + rs->UpdateField("hours",&fData); + + //NOCHARGE HOURS + m_edNCHours.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 vtData1(strData); + fData=(float)vtData1;//cast variant to float (locale friendly) + //fData=(float)atof(strData); + rs->UpdateField("nchours",&fData); + + //TRAVEL HOURS + m_edTravelHours.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 vtDatax1(strData); + fData=(float)vtDatax1;//cast variant to float (locale friendly) + //fData=(float)atof(strData); + rs->UpdateField("travhours",&fData); + + //DISTANCE + m_edDistance.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 vtData2(strData); + fData=(float)vtData2;//cast variant to float (locale friendly) + //fData=(float)atof(strData); + rs->UpdateField("distance",&fData); + + //RATE + strData=m_cbRates.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("rate",&lData); + + //TRAVEL RATE + strData=m_cbTravelRates.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("travrate",&lData); + + + + + //START + + //this field expects time and also date + //so we need to get the time and add back in the date + //date is set earlier in this function + + //moved down to here 10/11/2002 + m_dtDate.GetTime(dtDate); + m_dtEndDate.GetTime(dtEndDate); + + m_edStart.GetWindowText(strData); + dtTime.ParseDateTime(strData,VAR_TIMEVALUEONLY); + dtData.SetDateTime(dtDate.GetYear(),dtDate.GetMonth(),dtDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + rs->UpdateField("start",&dtData); + + //STOP + //TODO:validation of conversion + m_edEnd.GetWindowText(strData); + dtTime.ParseDateTime(strData,VAR_TIMEVALUEONLY); + dtData.SetDateTime(dtEndDate.GetYear(),dtEndDate.GetMonth(),dtEndDate.GetDay(),dtTime.GetHour(),dtTime.GetMinute(),dtTime.GetSecond()); + rs->UpdateField("stop",&dtData); + + //DETAILS + m_edDetails.GetWindowText(strData); + rs->UpdateField("details",&strData); + + + rs->SaveRecord(); + + + m_bEditing=true;//we are now editing because of save + + //01/11/2001 changed to: + rs->Close(); + + //changes 08/22/00 added the following + //to refresh recordset + FillFields(); + + //and same date as above added this bit + return true; + + + +} + + + + +void CSimpleWODlg::OnKillfocusEdclientcontact() +{ + SaveField(&m_edClientContact,"clientcontact",true,rs); + +} + +void CSimpleWODlg::OnKillfocusEdclientrefnum() +{ + SaveField(&m_edClientRefNumber,"clientrefnum",true,rs); + +} + + +//added nov 10th 2000, to ensure +//all data is saved before printing +void CSimpleWODlg::Flush(bool bClose) +{ + + if(bClose) + { + //Added Nov 10th, deletes rs recordset object + //to flush it then calls fillfields at the bottom + //to reopen it. + + rs->Close(); + rsLabor->Close(); + rsProb->Close(); + //m_pApp->Delay(5); + + } + else + { + + //fill the recordsets again + FillFields(); + } + +} + +void CSimpleWODlg::OnQuickwoDone() +{ + CString strData,q; + COleDateTime dtData,dtTime,dtDate; + //added because clicking a menu item doesn't kill + //focus on a control to allow it to update + m_ckOnsite.SetFocus(); + + + if(m_cbClients.GetCurrentRowID()=="0") + { + AfxMessageBox("Please choose a client"); + return; + + } + + //bail if user is only editing + if(m_bEditing) + { + CDialog::OnOK(); + return; + } + + + + //otherwise save new record + SaveNewRecord(); + + + + + + CDialog::OnOK(); +} + +void CSimpleWODlg::OnQuickwoClientnotes() +{ + CContactsViewDlg d; + d.Setup(m_cbClients.GetCurrentRowID()); + d.DoModal(); +} + + + + + + + +void CSimpleWODlg::OnQuickwoDelete() +{ + CString q; + CString msg; + + //added because clicking a menu item doesn't kill + //focus on a control to allow it to update + m_ckOnsite.SetFocus(); + + if(!m_bEditing) + { + msg="Abandon workorder?\r\nAre you sure?"; + + if(AfxMessageBox(msg,MB_YESNO)==IDYES) + { + q.Format("DELETE wo.*, wo.id FROM wo WHERE (((wo.id)=%s));",m_strID); + rs->Ex(q); + rs->QueryReadOnly("SELECT defaults.* FROM defaults");//just to flush + m_pApp->m_bRefreshStatScreen=true; + CDialog::OnOK(); + } + } + else + { + + msg="Delete workorder?\r\nAre you sure?"; + if(AfxMessageBox(msg,MB_YESNO)==IDYES) + { + q.Format("DELETE labor.*, probs.wolink " + "FROM labor INNER JOIN probs ON labor.link = probs.id " + "WHERE (((probs.wolink)=%s));",m_strWorkorderID); + rs->Ex(q); + + q.Format("DELETE probs.wolink, probs.* " + "FROM probs " + "WHERE (((probs.wolink)=%s));",m_strWorkorderID); + rs->Ex(q); + + + + q.Format("DELETE wo.*, wo.id FROM wo WHERE (((wo.id)=%s));",m_strWorkorderID); + rs->Ex(q); + rs->QueryReadOnly("SELECT defaults.* FROM defaults");//just to flush + m_pApp->m_bRefreshStatScreen=true; + CDialog::OnOK(); + } + + } + + + +} + + + + + +void CSimpleWODlg::OnQuickwoPrint() +{ + + CString q; + CString parameters; + //added because clicking a menu item doesn't kill + //focus on a control to allow it to update + m_ckOnsite.SetFocus(); + + //Save first if new record + if(!m_bEditing) + { + if(!SaveNewRecord()) return; + //kill time here + //AfxMessageBox("Record Saved...proceeding to print"); + + } + + //close the recordsets + Flush(true); + + parameters.Format("\"%s\" AS zCompName, ",m_pApp->m_strRegCompany); + + /* + q.Format("SELECT %s wo.*, probs.*, labor.*, users.first, users.last, users.initials, clients.* " + "FROM (users INNER JOIN (labor INNER JOIN (wo INNER JOIN probs ON wo.id = probs.wolink) ON labor.link = probs.id) ON users.id = labor.tech) LEFT JOIN clients ON wo.client = clients.id " + "WHERE (((wo.id)=%s));",parameters,m_strWorkorderID); + */ + + q.Format("SELECT %s wo.id, wo.clientrefnum, wo.clientcontact, clients.company AS clientcompany, Format(wo.closed,\"Short Date\") AS wodate, " + "[users]![first] & \" \" & [users]![last] AS wotech, labor.hours, " + "labor.travhours, labor.nchours, rates_1.name AS workrate, rates.name " + "AS travrate, labor.start AS starttime, " + "labor.stop AS stoptime, wo.invoice, labor.details, wo.onsite " + "FROM (((users RIGHT JOIN (labor RIGHT JOIN (wo LEFT JOIN probs ON " + "wo.id = probs.wolink) ON labor.link = probs.id) ON users.id = " + "labor.tech) LEFT JOIN clients ON wo.client = clients.id) LEFT " + "JOIN rates ON labor.travrate = rates.id) LEFT JOIN rates AS " + "rates_1 ON labor.rate = rates_1.id WHERE (((wo.id)=%s));",parameters,m_strWorkorderID); +#ifdef _DEBUG + m_pApp->ShowStuff(q); +#endif + rsPrint->QueryReadOnly(q); + rsPrint->QueryReadOnly(q); +/* + CString strTEST; + strTEST=rsPrint->SetFieldToMemo("details"); + //m_pApp->ShowStuff(strTEST); +*/ + + if(!rsPrint->IsEmpty()) + { + m_pApp->PrintCMReportRDC("Quick workorder",rsPrint->RecordSetPointer()); +#ifdef _DEBUG + m_pApp->CreateTTX("QuickWO.ttx",rsPrint->RecordSetPointer()); +#endif + } + + //reopen the recordsets + Flush(false); +} + +void CSimpleWODlg::OnQuickwoPrintDispatch() +{ + //added because clicking a menu item doesn't kill + //focus on a control to allow it to update + m_ckOnsite.SetFocus(); + + CString q; + + //Save first if new record + if(!m_bEditing) + { + if(!SaveNewRecord()) return; + + } + + + //print the dispatch format workorder + + //close all the extra recordsets - Nov 10th 2000 + //(U.S. presidential election uncertainty day 3) + Flush(true); + + + q.Format("SELECT IIf(IsNull([clients].[company]),[clients].[last] & \", \" & [clients].[first],[clients].[company]) AS clientname, " + "IIf(IsNull([clients].[streetaddress]),[clients].[mailaddress],[clients].[streetaddress]) & IIf(IsNull([clients].[city]),\"\"," + "[clients].[city]) & IIf(IsNull([clients].[stateprov]),\"\",\", \" & [clients].[stateprov] & " + "IIf(IsNull([clients].[postal]),\"\",\" \" & [clients].[postal])) AS address, " + "\"Work required: \" & [probs].[brief] & IIf([probs].[unit]<>0,Chr(13) & \"Unit: \" & [nonclients].[company_person] & " + "\" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] & \") SN: \" & [units].[sn],\"\") AS probheader, " + "\"%s\" AS compname, wo.id AS wonumber, wo.created, labor.details, probs.notes, IIf(IsNull(contracts_1.name)," + "[contracts].[name],contracts_1.name) AS contractinfo, IIf([probs].[unit]<>0,\"Unit: \" & " + "[nonclients].[company_person] & \" \" & [unitmodels].[description] & \" (\" & [unitmodels].[model] & \") SN: \" & " + "[units].[sn],\"\") AS Equipment, wo.starttime AS [Booked for], probs.brief, clients.mailaddress, clients.streetaddress, " + "clients.city, clients.stateprov, clients.postal, clients.country, clients.bizphone, clients.extension, clients.technotes, clients.first, clients.last, wo.clientrefnum, wo.ourref, wo.clientcontact " + "FROM (((labor RIGHT JOIN (((units RIGHT JOIN probs ON units.id = probs.unit) LEFT JOIN unitmodels ON " + "units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id) ON labor.link = " + "probs.id) RIGHT JOIN ((wo LEFT JOIN clients ON wo.client = clients.id) LEFT JOIN clients AS headoffices ON " + "clients.headoffice = headoffices.id) ON probs.wolink = wo.id) LEFT JOIN contracts ON clients.contract = " + "contracts.id) LEFT JOIN contracts AS contracts_1 ON headoffices.contract = contracts_1.id " + "WHERE (((wo.id)=%s));",m_pApp->m_strRegCompany,m_strWorkorderID); + + rsPrint->QueryReadOnly(q); + rsPrint->QueryReadOnly(q); + + if(!rsPrint->IsEmpty()) + { + +#ifdef _DEBUG + m_pApp->ShowStuff(q); + m_pApp->CreateTTX("wodispqu.ttx",rsPrint->RecordSetPointer()); +#endif + m_pApp->PrintCMReportRDC("Workorder dispatch (Quick)",rsPrint->RecordSetPointer()); + + } + + else + { + AfxMessageBox("There is no data to print!"); + + } + + + + //reopen the closed recordsets + Flush(false); +} + +void CSimpleWODlg::DisplayContactInfo() +{ + CString q, strData, strDisplay; +//retrieve contact info based on workorder + + q.Format( + "SELECT clients.first, clients.last, clients.company, " + "clients.mailaddress, clients.streetaddress, clients.city, " + "clients.stateprov, clients.postal, clients.country, clients.bizphone, " + "clients.extension, clients.fax, clients.email " + "FROM clients " + "WHERE (((clients.id)=%s));",m_strSelClient); + + cbrs->QueryReadOnly(q); + if(cbrs->IsEmpty()) + { + m_lblContactInfo.SetWindowText(""); + return; + } + + + strDisplay="[Contact: "; + cbrs->FetchField("first",&strData); + if(!strData.IsEmpty()) + strDisplay+=strData + " "; + + cbrs->FetchField("last",&strData); + strDisplay+=strData+"]"; + + cbrs->FetchField("bizphone",&strData); + if(!strData.IsEmpty()) + strDisplay+= "[Phone: " + strData; + + cbrs->FetchField("extension",&strData); + if(!strData.IsEmpty()) + strDisplay+=" ext:" + strData; + + strDisplay+="]"; + + + + cbrs->FetchField("fax",&strData); + if(!strData.IsEmpty()) + strDisplay+="[Fax: " + strData + "]"; + + cbrs->FetchField("email",&strData); + if(!strData.IsEmpty()) + strDisplay+="[Email: " + strData + "]"; + + //Physical address for Lenny and the lock people + strDisplay+="[Addr: "; + cbrs->FetchField("streetaddress",&strData); + if(!strData.IsEmpty()) + strDisplay+= strData + ", "; + cbrs->FetchField("city",&strData); + if(!strData.IsEmpty()) + strDisplay+= strData; + strDisplay+="]"; + + m_lblContactInfo.SetWindowText(strDisplay); + + +} + +void CSimpleWODlg::FillStatusList() +{ +//========================================== + //WORKORDER STATUS LIST + + CString strData; + CString strIndex; + long lData; + + //FILL STATUS LIST + m_cbStatus.Clear(); + //first enter default item + strData="< N/A >"; + strIndex="0"; + m_cbStatus.AddRow(strData,strIndex); + + cbrs->QueryReadOnly("SELECT probstat.id, probstat.notes FROM probstat ORDER BY probstat.id;"); + + if(!cbrs->IsEmpty()) + { + do + { + cbrs->FetchField("notes",&strData); + cbrs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbStatus.AddRow(strData,strIndex); + }while(cbrs->MoveForward()); + } + m_cbStatus.Select("0"); + //============================================ +} + +void CSimpleWODlg::OnKillfocusEdourrefnumber2() +{ + SaveField(&m_edOurRefNum,"ourref",true,rs); +} + +void CSimpleWODlg::OnCloseupCbstatus() +{ + SaveField(&m_cbStatus,"status",rs); + + +} + +void CSimpleWODlg::OnHistory() +{ + CString q; + q.Format("SELECT wo.created, wo.modified, wo.creator, wo.modifier FROM wo " + "WHERE (((wo.id)=%s));",m_strWorkorderID); + + cbrs->QueryReadOnly(q); + + + COleDateTime dtCreated,dtModified; + CString modifier,creator; + long m,c; + //GET RECORD STATUS FIELDS + cbrs->FetchField("created",&dtCreated); + cbrs->FetchField("modified",&dtModified); + + cbrs->FetchField("creator",&c); + + cbrs->FetchField("modifier",&m); + creator.Format("%u",c); + modifier.Format("%u",m); + + + CStatusDlg d; + d.SetValues(&creator,&modifier,&dtCreated,&dtModified); + d.DoModal(); + +} + +//Show tech notes +void CSimpleWODlg::OnLbltechnotes() +{ + m_pApp->ShowStuff(m_strTechNotes); + +} + +void CSimpleWODlg::UpdateClosedOpen() +{ + CString strData; + strData=m_bIsOpen ? " ":" "; + CMenu* pMenu=this->GetMenu(); + pMenu->ModifyMenu(ID_QUICKWO_COSTATUS,MF_BYCOMMAND,ID_QUICKWO_COSTATUS,strData); +//v1.9.4.2 + if(m_bReadOnly) + pMenu->EnableMenuItem(ID_QUICKWO_COSTATUS, MF_DISABLED | MF_GRAYED); + + this->DrawMenuBar(); +} + +void CSimpleWODlg::OnQuickwoCostatus() +{ + CString q, strStatusQ; + + strStatusQ.Empty(); + if(m_bIsOpen) + { + m_bIsOpen=false; + if(m_pApp->m_lDefClosedWOStatus!=0) + { + m_strSelectedStatus.Format("%u",m_pApp->m_lDefClosedWOStatus); + strStatusQ.Format(", wo.status=%s",m_strSelectedStatus); + m_cbStatus.Select(m_strSelectedStatus); + } + } + else + { + m_bIsOpen=true; + if(m_pApp->m_lDefReOpenWOStatus!=0) + { + m_strSelectedStatus.Format("%u",m_pApp->m_lDefReOpenWOStatus); + strStatusQ.Format(", wo.status=%s",m_strSelectedStatus); + m_cbStatus.Select(m_strSelectedStatus); + } + } + + + //----- + COleDateTime dtData=COleDateTime::GetCurrentTime(); + if(m_bIsOpen) + dtData.SetDate(1968,03,12); + + q.Format("UPDATE wo SET wo.closed = #%s# %s WHERE (((wo.id)=%s));",dtData.Format(_T("%m/%d/%Y %H:%M:%S")),strStatusQ,m_strWorkorderID); + cbrs->Ex(q); + cbrs->Close(); + + //removed because of some strange voodoo when it says another user is modifying + // UpdateModified(); + m_pApp->m_bRefreshStatScreen=true; + //----- + + UpdateClosedOpen(); +} + + + +//added 07/25/01, somehow got missed all along :( +void CSimpleWODlg::OnTravelratelabel() +{ +OnRateLabel(); +} + +void CSimpleWODlg::Security() +{ +m_bReadOnly=false; + int x=m_pApp->Allowed(RWORKORDER,true); + if(x==0)//no access allowed + { + m_pApp->SecurityWarning(); + CDialog::OnCancel(); + } + if(x==2)//read only + { + + m_bReadOnly=true; + m_dtEndDate.EnableWindow(FALSE); + m_edOurRefNum.EnableWindow(FALSE); + m_cbStatus.EnableWindow(FALSE); + m_edClientRefNumber.EnableWindow(FALSE); + m_edClientContact.EnableWindow(FALSE); + m_cbTechList.EnableWindow(FALSE); + m_cbTravelRates.EnableWindow(FALSE); + m_ckOnsite.EnableWindow(FALSE); + m_dtDate.EnableWindow(FALSE); + m_btnTimer.EnableWindow(FALSE); + m_edDetails.SetReadOnly(TRUE);//.EnableWindow(FALSE); + m_edInvoicedOn.EnableWindow(FALSE); + m_edTravelHours.EnableWindow(FALSE); + m_edDistance.EnableWindow(FALSE); + m_edNCHours.EnableWindow(FALSE); + m_edBillHours.EnableWindow(FALSE); + m_edEnd.EnableWindow(FALSE); + m_edStart.EnableWindow(FALSE); + m_cbTypes.EnableWindow(FALSE); + m_cbRates.EnableWindow(FALSE); + m_cbClients.EnableWindow(FALSE); + CMenu* pMenu=this->GetMenu(); + pMenu->EnableMenuItem(ID_QUICKWO_DELETE, MF_DISABLED | MF_GRAYED); + //v1.9.4.2 + pMenu->EnableMenuItem(ID_QUICKWO_COSTATUS, MF_DISABLED | MF_GRAYED); + + + + //v1.9.4.4 + m_lblCategory.EnableWindow(FALSE); + //m_lblProjects.EnableWindow(FALSE); + m_lblStatus.EnableWindow(FALSE); + //m_lblFind.EnableWindow(FALSE); + } + + //v1.9.4.4 delete option disabled unless a member of managers + if(m_pApp->m_lGroupID!=1) + { + CMenu* pMenu=this->GetMenu(); + pMenu->EnableMenuItem(ID_QUICKWO_DELETE, MF_DISABLED | MF_GRAYED); + } +} + + + +void CSimpleWODlg::FillReportList(void) +{ + + CString q,strData; + UINT uiResourceID=_STARTING_PRINT_COMMAND_ID;/*id's 32289 to 33388 are set aside for what have u, in this case workorder report menu commands*/ + + q="SELECT rptsmaster.virtualname,rptsmaster.id, rptsmaster.wodisplayorder FROM rptsmaster WHERE " +"(((rptsmaster.recordset)=\"woquick\")) ORDER BY rptsmaster.wodisplayorder;"; + if(!rs->QueryReadOnly(q)) return; + + //get the corrent menu location + CMenu* pMainMenu = GetMenu(); + //CMenu* m_pSubMenu=NULL; + for (int i=0;i<(int)pMainMenu->GetMenuItemCount();i++) + { + m_pSubMenu=pMainMenu->GetSubMenu(i); + if(m_pSubMenu && m_pSubMenu->GetMenuItemID(0)== ID_PRINT_PLACEHOLDER) + break; + } + ASSERT(m_pSubMenu); + + //remove the placeholder + m_pSubMenu->RemoveMenu(0,MF_BYPOSITION); + //remove old report commands (lazy..I know) + m_pSubMenu->RemoveMenu(0,MF_BYPOSITION); + m_pSubMenu->RemoveMenu(0,MF_BYPOSITION); + + //Show query option for manager account only + if(m_pApp->m_lusrID==1) + { + m_pSubMenu->AppendMenu(0,uiResourceID,"SHOW QUERIES ON PRINT"); + m_pSubMenu->CheckMenuItem(uiResourceID,MF_UNCHECKED|MF_BYCOMMAND); + m_pSubMenu->AppendMenu(MF_SEPARATOR); + m_bShowQueriesOnPrint=false; + + } + + do{ + uiResourceID++; + //Add menu item: report name, uiResourceID command + rs->FetchField("virtualname",&strData); + m_pSubMenu->AppendMenu(0,uiResourceID,strData); + + + }while(rs->MoveForward()); +} + + + +void CSimpleWODlg::OnPrintReport( UINT nID ) +{ + CString strVirtualReportName,strTTXPath; + CString strError; + CString q,strQuery; + CString strWOID,strRegTo,strSchedTech; + CString strShowQuery,strTemp; + + //see if it's a checkmark that needs to be done + if(nID==_STARTING_PRINT_COMMAND_ID)//it's a click on show queries + { + m_bShowQueriesOnPrint=!m_bShowQueriesOnPrint; + if(m_bShowQueriesOnPrint) + m_pSubMenu->CheckMenuItem(_STARTING_PRINT_COMMAND_ID,MF_CHECKED|MF_BYCOMMAND); + else + m_pSubMenu->CheckMenuItem(_STARTING_PRINT_COMMAND_ID,MF_UNCHECKED|MF_BYCOMMAND); + + return; + } + + + + m_pSubMenu->GetMenuString(nID,strVirtualReportName,MF_BYCOMMAND); + + //added because clicking a menu item doesn't kill + //focus on a control to allow it to update + m_ckOnsite.SetFocus(); + + //Save first if new record + if(!m_bEditing) + if(!SaveNewRecord()) + return; + + //close the recordsets + Flush(true); + + + q.Format("SELECT rptsmaster.* FROM rptsmaster WHERE (((rptsmaster.virtualname)=\"%s\"));",strVirtualReportName); + //Fetch query + if(!cbrs->QueryReadOnly(q)) + { + strError.Format( + "Unable to print:\r\n" + "%s\r\n" + "Can't open rptsmaster table due to the error previously reported\r\n" + "by the database driver.",strVirtualReportName); + AfxMessageBox(strError); + return; + + } + + + if(!cbrs->FetchField("filename",&strTTXPath)) + { + strError.Format( + "Unable to print:\r\n" + "%s\r\n" + "can't retrieve report file name due to the error previously reported\r\n" + "by the database driver.",strVirtualReportName); + AfxMessageBox(strError); + return; + + } + strTTXPath.Replace(".rpt",".ttx"); + + if(!cbrs->FetchField("query",&strQuery)) + { + strError.Format( + "Unable to print:\r\n" + "%s\r\n" + "Can't retrieve report query due to the error previously reported\r\n" + "by the database driver.",strVirtualReportName); + AfxMessageBox(strError); + return; + + } + + if(m_bShowQueriesOnPrint) + { + strShowQuery.Format("---==< Database queries to aid in report customization >==---\r\n\r\n" + "Raw query for:%s\r\n" + "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r\n" + "%s\r\n" + "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r\n\r\n\r\n",strVirtualReportName,strQuery); + + + } + //make token substitutions + strQuery.Replace("~REGTO",m_pApp->m_strRegCompany); + strQuery.Replace("Evaluation",m_pApp->m_strRegCompany); + strQuery.Replace("~WOID",m_strWorkorderID); + + if(m_bShowQueriesOnPrint) + { + strTemp.Format("Query after tokens replaced for:%s\r\n" + "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r\n" + "%s\r\n" + "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r\n",strVirtualReportName,strQuery); + strShowQuery+=strTemp; + + m_pApp->ShowStuff(strShowQuery); + + } + + //run query + if(!rsPrint->QueryReadOnly(strQuery)) + { + strError.Format( + "Unable to print:\r\n" + "%s\r\n" + "due to the error previously reported\r\n" + "by the database driver.",strVirtualReportName); + AfxMessageBox(strError); + return; + } + + //run query again, because it seems to be needed + //and was done that way before. + //probably some sort of timing issue + //but it works and this is the last + //maint. release for this tired old code + if(!rsPrint->QueryReadOnly(strQuery)) + { + strError.Format( + "Unable to print:\r\n" + "%s\r\n" + "due to the error previously reported\r\n" + "by the database driver.",strVirtualReportName); + AfxMessageBox(strError); + return; + } + +//call report +if(!rsPrint->IsEmpty()) + { + m_pApp->PrintCMReportRDC(strVirtualReportName,rsPrint->RecordSetPointer()); + if(m_pApp->m_lusrID==1)//manager account? + m_pApp->CreateTTX(strTTXPath,rsPrint->RecordSetPointer(),true); + } + + //reopen the recordsets + Flush(false); + + + + +} +// Convert a float to ascii preserving locale format +CString CSimpleWODlg::FtoA(float fData) +{ + _variant_t vItem(fData); + _bstr_t bs; + VarFormatNumber(&vItem,-1,-2,-2,-2,0,bs.GetAddress()); + return CString((BSTR)bs); +} + +void CSimpleWODlg::OnStatuslabel() +{ + CProbStatDlg d; + d.DoModal(); + FillStatusList(); + if(m_strSelectedStatus.IsEmpty()) + m_strSelectedStatus="0"; + m_cbStatus.Select(m_strSelectedStatus); +} + +// Sets the selected labor rates for a selected tech that isn't the current logged in user (if there isn't a client default) +void CSimpleWODlg::SetForeignTechLaborRateDefaults(void) +{ +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.h new file mode 100644 index 0000000..a111f62 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SimpleWODlg.h @@ -0,0 +1,179 @@ +#if !defined(AFX_SIMPLEWODLG_H__6A1BC701_19B4_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_SIMPLEWODLG_H__6A1BC701_19B4_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SimpleWODlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSimpleWODlg dialog +#include "gzcombo.h" +#include "gzrset.h" +// +#include "label.h" +#include "wotypesdlg.h" +#include "clientsdlg.h" +#include "ResizeCtrl.h" +#include "afxwin.h" +class CSimpleWODlg : public CDialog +{ +// Construction +public: + CString m_strSelClient; + CString m_strSelectedStatus; + bool m_bIsOpen; + void UpdateClosedOpen(); + CString m_strTechNotes; + void FillStatusList(); + void DisplayContactInfo(); + void Flush(bool bClose); + bool SaveNewRecord(); + void SetClientRates(); + void Check4Contract(bool bAlert); + CString m_strClientContractID; + ~CSimpleWODlg(); + + void FillTechList(); + void FillFields(); + CString m_strWorkorderID; + bool m_bEditing; + void SetWorkorderID(CString* pstrWOID); + COleDateTime dt1; + COleDateTime dt2; + bool m_bTiming; + void FillWOTypesList(); + void FillRatesList(); + void FillClientList(); + CString m_strID; + CString m_strSelectedTech; + CString m_strSelectedRate; + CString m_strSelectedTravelRate; + CSimpleWODlg(CWnd* pParent = NULL); // standard constructor + GZRset* rs; + GZRset* cbrs; + GZRset* rsPrint; + GZRset* rsProb; + GZRset* rsLabor; + + + CSpApp* m_pApp; + //Save fields + bool SaveField(CEdit* edControl,CString fldname,bool AllowEmpty,GZRset* rsSet); + bool SaveField(CgzCombo* cbControl,CString fldname,GZRset* rsSet); + bool SaveField(CButton* ckControl,CString fldname,GZRset* rsSet); + bool SaveField(CDateTimeCtrl* dtControl,CString fldname,GZRset* rsSet); + bool UpdateModified(); + //------------------------------- +// Dialog Data + //{{AFX_DATA(CSimpleWODlg) + enum { IDD = IDD_SIMPLEWO }; + CDateTimeCtrl m_dtEndDate; + CLabel m_lblTechNotes; + CLabel m_lblHistory; + CEdit m_edOurRefNum; + CgzCombo m_cbStatus; + CLabel m_lblContactInfo; + CEdit m_edClientRefNumber; + CEdit m_edClientContact; + CLabel m_lblContract; + CLabel m_lblTechList; + CgzCombo m_cbTechList; + CLabel m_lblTravelRate; + CgzCombo m_cbTravelRates; + CButton m_ckOnsite; + CDateTimeCtrl m_dtDate; + CLabel m_lblClients; + CLabel m_lblRate; + CLabel m_lblCategory; + CLabel m_lblEnd; + CButton m_btnTimer; + CEdit m_edDetails; + CEdit m_edInvoicedOn; + CEdit m_edTravelHours; + CEdit m_edNCHours; + CEdit m_edBillHours; + CEdit m_edEnd; + CEdit m_edStart; + CgzCombo m_cbTypes; + CgzCombo m_cbRates; + CgzCombo m_cbClients; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSimpleWODlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSimpleWODlg) + virtual BOOL OnInitDialog(); + afx_msg void OnTimer(); + afx_msg void OnLabelCategory(); + afx_msg void OnRateLabel(); + afx_msg void OnClientlistLabel(); + virtual void OnOK(); + afx_msg void OnCloseupTravelrateslist(); + afx_msg void OnCloseupRateslist(); + afx_msg void OnTravelhourslabel(); + afx_msg void OnCloseupTechlist(); + afx_msg void OnCloseupType(); + afx_msg void OnKillfocusTravel(); + afx_msg void OnKillfocusStart(); + afx_msg void OnOnsite(); + afx_msg void OnKillfocusNc(); + afx_msg void OnKillfocusInvoicenum(); + afx_msg void OnKillfocusGeneralnotes(); + afx_msg void OnKillfocusEnd(); + afx_msg void OnDatetimechangeDatepicker(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnCloseupClientlist(); + afx_msg void OnKillfocusBill(); + afx_msg void OnLblcontract(); + afx_msg void OnKillfocusEdclientcontact(); + afx_msg void OnKillfocusEdclientrefnum(); + afx_msg void OnQuickwoDone(); + afx_msg void OnQuickwoClientnotes(); + afx_msg void OnQuickwoDelete(); + afx_msg void OnQuickwoPrint(); + afx_msg void OnQuickwoPrintDispatch(); + afx_msg void OnKillfocusEdourrefnumber2(); + afx_msg void OnCloseupCbstatus(); + afx_msg void OnHistory(); + afx_msg void OnLbltechnotes(); + afx_msg void OnQuickwoCostatus(); + afx_msg void OnDatetimechangeDatepicker2(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnTravelratelabel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + bool m_bReadOnly; + void Security(); + CResizeCtrl m_resize; + +public: + CEdit m_edDistance; + afx_msg void OnEnKillfocusEdDistance(); + afx_msg void OnPrintReport( UINT nID ); + void FillReportList(void); + CMenu* m_pSubMenu; + bool m_bShowQueriesOnPrint; + bool m_bAlertPopup; + // Convert a float to ascii preserving locale format + CString FtoA(float fData); + CLabel m_lblStatus; + afx_msg void OnStatuslabel(); + // Sets the selected labor rates for a selected tech that isn't the current logged in user (if there isn't a client default) + void SetForeignTechLaborRateDefaults(void); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SIMPLEWODLG_H__6A1BC701_19B4_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.cpp new file mode 100644 index 0000000..f246d14 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.cpp @@ -0,0 +1,465 @@ +// SnR.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "SnR.h" +#include "SnREdit.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +//memory leak debugging help +#define _CRTDBG_MAP_ALLOC +#include +#include +///////////////////////////////////////////////////////////////////////////// +// CSnR + +IMPLEMENT_DYNCREATE(CSnR, CFormView) + +CSnR::CSnR() +: CFormView(CSnR::IDD) +, m_nCX(0) +{ + //{{AFX_DATA_INIT(CSnR) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + +} + +CSnR::~CSnR() +{ +} + +void CSnR::DoDataExchange(CDataExchange* pDX) +{ + CFormView::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSnR) + // NOTE: the ClassWizard will add DDX and DDV calls here + DDX_Control(pDX, IDC_REPORT, m_rc); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_CKSHOWCOMPLETED, m_ckShowCompleted); +} + + +BEGIN_MESSAGE_MAP(CSnR, CFormView) +//{{AFX_MSG_MAP(CSnR) +ON_NOTIFY(RVN_ITEMDBCLICK, IDC_REPORT, OnRvnItemDbClick) +//}}AFX_MSG_MAP +ON_WM_SIZE() +ON_BN_CLICKED(IDC_CKSHOWCOMPLETED, OnBnClickedCkshowcompleted) +ON_WM_HELPINFO() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSnR diagnostics + +#ifdef _DEBUG +void CSnR::AssertValid() const +{ + CFormView::AssertValid(); +} + +void CSnR::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CSnR message handlers + +void CSnR::Activate() +{ + #ifdef _WTF_ + AfxMessageBox("SNR activate"); + #endif + +/* + if(rs==NULL) + { + rs=new GZRset("Shipping and receiving rs error:"); + rs->SetConnect(m_pApp->strConnectString); + } +*/ + //Initialize recordset pointer + + + rs=m_pApp->rsPool->GetRS("CSnR"); + + CString profile,q; + q.Format("SELECT users.srprofile " + "FROM users WHERE (((users.id)=%u));",m_pApp->m_lusrID); + rs->Query(q); + rs->FetchField("srprofile",&profile); + if(!profile.IsEmpty()) + { + for(int x=0;x<7;x++) + m_rc.DeactivateColumn(x); + m_rc.GetProfile(&profile); + } + FillView(); + +} + +void CSnR::DeActivate() +{ + #ifdef _WTF_ + AfxMessageBox("dbutils De-activate"); + #endif + + CString profile,q; + //save to user prefs. + m_rc.WriteProfile(&profile); + q.Format("UPDATE users SET users.srprofile = \"%s\" " + "WHERE (((users.id)=%u));",profile,m_pApp->m_lusrID); + rs->Ex(q); + +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + + + +void CSnR::OnInitialUpdate() +{ + CFormView::OnInitialUpdate(); + + + m_strCrit.Empty(); + + //removed Jan 8th 2001 as unecessary + //Initialize recordset pointer + //rs=m_pApp->rsPool->GetRS("CSnR"); + + + + m_ilReport.Create(IDB_BM2, 16, 1, RGB(255,0,255)); + m_rc.SetImageList(&m_ilReport); + + + + m_rc.InsertColor(0, 0x00C0D8C0); + m_rc.InsertColor(1, ::GetSysColor(COLOR_GRAYTEXT)); + m_rc.InsertColor(2, 0x00D0C0C0); + m_rc.InsertColor(3, 0x00804000); + + + RVCOLUMN rvc; + + rvc.nFormat = RVCF_TEXT|RVCF_EX_AUTOWIDTH|RVCF_EX_FIXEDWIDTH|RVCF_SUBITEM_IMAGE; + rvc.iImage = 1; + rvc.lpszText = _T("Status"); + rvc.iWidth = 60; + m_rc.DefineColumn(0, &rvc); + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Item"; + rvc.iWidth = 60; + m_rc.DefineColumn(1, &rvc); + + rvc.lpszText = "Client"; + rvc.iWidth = 60; + m_rc.DefineColumn(2, &rvc); + + + rvc.nFormat = RVCF_TEXT; + rvc.lpszText = "Sent on"; + rvc.iWidth = 60; + m_rc.DefineColumn(3, &rvc); + + rvc.lpszText = "Due"; + rvc.iWidth = 60; + m_rc.DefineColumn(4, &rvc); + + //Checkmark + rvc.nFormat = RVCF_TEXT|RVCF_SUBITEM_IMAGE|RVCF_CENTER; + rvc.lpszText = "Rcvd."; + rvc.iWidth = 60; + m_rc.DefineColumn(5, &rvc); + + rvc.nFormat = RVCF_TEXT | RVCF_EX_FIXEDWIDTH; + rvc.lpszText = "ID"; + rvc.iWidth = 0; + m_rc.DefineColumn(6, &rvc); + + + + + + + m_rc.ModifyStyle(0, RVS_SINGLESELECT); + //m_rc.ModifyStyle(0, RVS_SHOWCOLORALTERNATE); + + + //turn off the grids + m_rc.ModifyStyle(RVS_SHOWVGRID, 0); + m_rc.ModifyStyle(RVS_SHOWHGRID, 0); + + + //removed Jan 8th 2001 as unecessary + //retrieve the items and display them + //FillView(); + //m_pApp->rsPool->ReleaseRS(&rs->m_nID); + + + +} + + +void CSnR::FillView() +{ + COleDateTime dtDefault; + dtDefault.SetDate(1968,03,12); + CString q; + int x=0; + m_strCrit.Empty(); + if(m_ckShowCompleted.GetCheck()==FALSE) + m_strCrit=" WHERE (((subrepair.isback)=False)) "; + +//1.9.3.0 added AS WOID to wo.id column for changes below + q.Format("SELECT subrepair.id AS subid, wo.closed, wo.id AS WOID, IIf(IsNull([clients]![company]), " + "[clients]![first] & \" \" & [clients]![last],[clients]![company]) AS compname, " + "nonclients_2!company_person & \" \" & IIf(IsNull([unitmodels]![description]), " + "[unitmodels]![model],[unitmodels]![description]) & \" \" & IIf(IsNull([sn]),\"\",\"sn:\" & [sn]) AS item, " + "nonclients.company_person AS sentto, nonclients_1.company_person AS sentby, " + "users.initials, IIf(subrepair.sent=#%s#,\"---\",Format(subrepair.sent,\"Short Date\")) AS strsent, subrepair.isback, " + "IIf(subrepair.eta=#%s#,\"---\",Format(subrepair.eta,\"Short Date\")) AS streta, subrepair.received, DateDiff(\"d\",Now(),[subrepair].[eta]) AS duedays " +"FROM (nonclients RIGHT JOIN (unitmodels RIGHT JOIN (units RIGHT JOIN (clients RIGHT JOIN (users RIGHT JOIN " +"((subrepair LEFT JOIN (probs LEFT JOIN wo ON probs.wolink = wo.id) ON subrepair.link = probs.id) LEFT JOIN " +"nonclients AS nonclients_1 ON subrepair.sentvia = nonclients_1.id) ON users.id = subrepair.creator) ON " +"clients.id = wo.client) ON units.id = probs.unit) ON unitmodels.id = units.model) ON nonclients.id = " +"subrepair.where) LEFT JOIN nonclients AS nonclients_2 ON unitmodels.manufacturer = nonclients_2.id " +"%s ORDER BY subrepair.id DESC;",dtDefault.Format(_T("%m/%d/%Y")),dtDefault.Format(_T("%m/%d/%Y")),m_strCrit); + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //m_pApp->ShowStuff(q); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +rs->Query(q); + m_rc.DeleteAllItems(); + + + if(rs->IsEmpty()) + return; + + + + + CString strData,strItem,strClient,strOutdate,strDueDays,strDuedate,strIsBack,strID; + CString strWOID; + COleDateTime dtDate; + long lData; + long lDueDays; + bool bReturned; + int nDueDays; + rs->MoveFirst(); + + + do + { + //Added 1.9.3.0 + rs->FetchField("WOID",&lData); + strWOID.Format(" [WO: %u]",lData); + + rs->FetchField("item",&strItem); + //avoid the underline in the report control + //for a single & + strItem.Replace("&","&&"); + + + rs->FetchField("compname",&strClient); + strClient.Replace("&","&&"); + + //Added v1.9.3.0 + strClient+=strWOID; + + + rs->FetchField("strsent",&strOutdate); + + rs->FetchField("streta",&strDuedate); + + + rs->FetchField("duedays",&lDueDays); + nDueDays=lDueDays;//atoi(strDueDays); + + rs->FetchField("subid",&lData); + strID.Format("%u",lData); + + rs->FetchField("isback",&bReturned); + + + + + //Set the look of the row and insert it + + //LATE! + RVITEM rvi; + rvi.iItem = x; + rvi.iSubItem = 0; + rvi.nMask = RVIM_IMAGE|RVIM_PREVIEW|RVIM_STATE|RVIM_LPARAM; + rvi.nState = 0; + rvi.nPreview = 0;//no preview necessary + if(bReturned) + rvi.iImage=3;//blank + else + { + rvi.iImage=0;//green light - default + + if(nDueDays<0)//overdue + rvi.iImage=2;//redlight + + if(nDueDays==0)//due today + rvi.iImage=1;//orange light + + } + + rvi.lParam = x; + m_rc.InsertItem(&rvi); + + + //ITEM + rvi.iSubItem = 1; + rvi.nMask = RVIM_TEXT; + rvi.lpszText = strItem.GetBuffer(strItem.GetLength()); + m_rc.SetItem(&rvi); + + //CLIENT + rvi.iSubItem = 2; + rvi.lpszText = strClient.GetBuffer(strClient.GetLength()); + m_rc.SetItem(&rvi); + + //SENT OUT + rvi.iSubItem = 3; + rvi.lpszText = strOutdate.GetBuffer(strOutdate.GetLength()); + m_rc.SetItem(&rvi); + + //DUE + rvi.iSubItem = 4; + rvi.lpszText = strDuedate.GetBuffer(strDuedate.GetLength()); + m_rc.SetItem(&rvi); + + //ISBACK + rvi.nMask = RVIM_IMAGE |RVIM_CHECK; + rvi.nState=0;//who knows what this is for? + rvi.iSubItem = 5; + rvi.iImage=-1; + if(bReturned==false) + rvi.iCheck = FALSE; + else + rvi.iCheck = TRUE; + rvi.lpszText = "Check"; + m_rc.SetItem(&rvi); + + + + + //ID + rvi.nMask = RVIM_TEXT; + rvi.iSubItem = 6; + rvi.lpszText = strID.GetBuffer(strID.GetLength()); + m_rc.SetItem(&rvi); + + + x++; + + }while(rs->MoveForward()); + + + + +} + +void CSnR::OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult) +{ + + LPNMREPORTVIEW lpnmrv = (LPNMREPORTVIEW)pNMHDR; + + + + if(lpnmrv->iItem >=0)//-1 if clicked on invalid + { + + //CLoanersEditDlg d; + //CString item=m_rc.GetItemText(lpnmrv->iItem,6); + //d.SetRentalID(&item); + //d.DoModal(); + + CSnREdit d; + CString item=m_rc.GetItemText(lpnmrv->iItem,6); + d.m_strSubRepairID=item; + + if(d.DoModal()==IDOK) + FillView(); + + + + } + + *pResult = FALSE; +} + +void CSnR::LayoutControls(void) +{ + CRect rectCtl,rectStat; + GetWindowRect(rectStat); + + + int nOffset=rectStat.top; + int nLastBottom,nRight,nHeight; + //int nHeight,nWidth,nLeft; + + + m_rc.GetWindowRect(rectCtl); + + rectCtl.right=rectStat.right-73; + rectCtl.top-=nOffset; + rectCtl.left=13; + rectCtl.bottom=rectStat.bottom-70-nOffset; + m_rc.MoveWindow(rectCtl,TRUE); + nLastBottom=rectCtl.bottom; + nRight=rectCtl.right; + + + m_ckShowCompleted.GetWindowRect(rectCtl); + nHeight=rectCtl.Height(); + //rectCtl.right=rectStat.right-73; + rectCtl.top=nLastBottom+10; + //rectCtl.left=13; + rectCtl.bottom=nLastBottom+nHeight+10; + m_ckShowCompleted.MoveWindow(rectCtl,TRUE); + + + +} + + + +void CSnR::OnSize(UINT nType, int cx, int cy) +{ + + + CFormView::OnSize(nType, cx, cy); + if(cx>m_nCX)//to cut down on number of times called + { + m_nCX=cx; + if(m_rc.m_hWnd) + { + LayoutControls(); + } + } +} + +void CSnR::OnBnClickedCkshowcompleted() +{ + FillView(); +} + +BOOL CSnR::OnHelpInfo(HELPINFO* pHelpInfo) +{ +WinHelp (0x00020000 + IDD_SNR_FORM,HELP_CONTEXT); + return TRUE; +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.h new file mode 100644 index 0000000..579d766 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnR.h @@ -0,0 +1,86 @@ +#if !defined(AFX_SNR_H__640A17A1_4127_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_SNR_H__640A17A1_4127_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SnR.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSnR form view + +#ifndef __AFXEXT_H__ +#include +#endif + +#include "ReportCtrl.h" +#include "gzrset.h" +#include "gzk.h" +#include "afxwin.h" + +class CSnR : public CFormView +{ +public: + CSnR(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(CSnR) +GZRset* rs; + CSpApp* m_pApp; + void OnRvnItemDbClick(NMHDR* pNMHDR, LRESULT* pResult); +// Form Data +public: + //{{AFX_DATA(CSnR) + enum { IDD = IDD_SNR_FORM }; + CReportCtrl m_rc; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + +// Attributes +public: + +// Operations +public: + CString m_strCrit; + void FillView(); + void DeActivate(); + void Activate(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSnR) + public: + virtual void OnInitialUpdate(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + CImageList m_ilReport; + virtual ~CSnR(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(CSnR) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + void LayoutControls(void); + + int m_nCX; + afx_msg void OnSize(UINT nType, int cx, int cy); + CButton m_ckShowCompleted; + afx_msg void OnBnClickedCkshowcompleted(); + afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SNR_H__640A17A1_4127_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.cpp new file mode 100644 index 0000000..41ca7b2 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.cpp @@ -0,0 +1,585 @@ +// SnREdit.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "SnREdit.h" +#include "NonClientsDlg.h" +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSnREdit dialog + + +CSnREdit::CSnREdit(CWnd* pParent /*=NULL*/) + : CDialog(CSnREdit::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSnREdit) + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + + /* + rs = new GZRset("Error: Ship/Receive rs."); + rs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CSnREdit"); + + cfm = new CgzCurrencyFormatter; + m_strSelectedSentTo="0"; + m_strSelectedSentVia="0"; + bModified=false; + k=new GZK; + k->GZSetUniqueKey(40); +} +CSnREdit::~CSnREdit() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + delete cfm; + delete k; +} + +void CSnREdit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSnREdit) + DDX_Control(pDX, IDC_LBLWO, m_lblInfo); + DDX_Control(pDX, IDC_LBLREPAIRCTRS, m_lblRepairCenters); + DDX_Control(pDX, IDC_LBLMANUFACTURERS, m_lblManufacturers); + DDX_Control(pDX, IDC_LBLSENTVIA, m_lblSentVia); + DDX_Control(pDX, IDC_LBLETARECEIVED, m_lblEtaReceived); + DDX_Control(pDX, IDC_EDWAYBILL, m_edWaybill); + DDX_Control(pDX, IDC_EDRMA, m_edRMA); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_EDCOST, m_edCost); + DDX_Control(pDX, IDC_EDCHARGE, m_edCharge); + DDX_Control(pDX, IDC_DTSENT, m_dtSent); + DDX_Control(pDX, IDC_DTRECETA, m_dtRecEta); + DDX_Control(pDX, IDC_CKRECEIVED, m_ckReceived); + DDX_Control(pDX, IDC_CBSENTVIA, m_cbSentVia); + DDX_Control(pDX, IDC_CBSENTTO, m_cbSentTo); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSnREdit, CDialog) + //{{AFX_MSG_MAP(CSnREdit) +ON_EN_KILLFOCUS(IDC_EDCHARGE, OnKillfocusEdcharge) +ON_EN_KILLFOCUS(IDC_EDCOST, OnKillfocusEdcost) +ON_BN_CLICKED(IDC_CKRECEIVED, OnCkreceived) + ON_BN_CLICKED(IDC_LBLMANUFACTURERS, OnLblmanufacturers) + ON_BN_CLICKED(IDC_LBLREPAIRCTRS, OnLblrepairctrs) + ON_BN_CLICKED(IDC_LBLSENTVIA, OnLblsentvia) + ON_CBN_CLOSEUP(IDC_CBSENTTO, OnCloseupCbsentto) + ON_CBN_CLOSEUP(IDC_CBSENTVIA, OnCloseupCbsentvia) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTRECETA, OnDatetimechangeDtreceta) + ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTSENT, OnDatetimechangeDtsent) + ON_EN_KILLFOCUS(IDC_EDNOTES, OnKillfocusEdnotes) + ON_EN_KILLFOCUS(IDC_EDRMA, OnKillfocusEdrma) + ON_EN_KILLFOCUS(IDC_EDWAYBILL, OnKillfocusEdwaybill) + ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSnREdit message handlers +BOOL CSnREdit::OnInitDialog() +{ + CString q,strData; + long lData; + bool bData; + COleCurrency crData; + COleDateTime dtData; + CDialog::OnInitDialog(); + + + //"Hyperlink-o-size" labels + m_lblManufacturers.SetTextColor(RGB(0,0,255)); + m_lblManufacturers.SetFontUnderline(TRUE); + m_lblManufacturers.SetLink(TRUE); + m_lblManufacturers.SetLinkCursor(m_pApp->hcHand); + m_lblManufacturers.SetLinkURL(""); + + m_lblRepairCenters.SetTextColor(RGB(0,0,255)); + m_lblRepairCenters.SetFontUnderline(TRUE); + m_lblRepairCenters.SetLink(TRUE); + m_lblRepairCenters.SetLinkCursor(m_pApp->hcHand); + m_lblRepairCenters.SetLinkURL(""); + + m_lblSentVia.SetTextColor(RGB(0,0,255)); + m_lblSentVia.SetFontUnderline(TRUE); + m_lblSentVia.SetLink(TRUE); + m_lblSentVia.SetLinkCursor(m_pApp->hcHand); + m_lblSentVia.SetLinkURL(""); + + + + //FILL PICKLISTS + FillLists(); + + //ATTEMPT TO FILL FIELDS +/* + q.Format("SELECT subrepair.*, probs.wolink, users.first, users.last " + "FROM (subrepair LEFT JOIN probs ON subrepair.link = probs.id) LEFT JOIN users ON subrepair.creator = users.id " + "WHERE (((subrepair.id)=%s));",m_strSubRepairID); +*/ + +q.Format("SELECT subrepair.*, probs.wolink, users.first, users.last, [nonclients]![company_person] & \" \" & IIf(IsNull([unitmodels]![description]),[unitmodels]![model],[unitmodels]![description]) & \" \" & IIf(IsNull([sn]),\"\",\"sn:\" & [sn]) AS item " +"FROM ((((subrepair LEFT JOIN probs ON subrepair.link = probs.id) LEFT JOIN users ON subrepair.creator = users.id) LEFT JOIN units ON probs.unit = units.id) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " +"WHERE (((subrepair.id)=%s));",m_strSubRepairID); + +#ifdef _DEBUG +m_pApp->ShowStuff(q); +#endif + + + rs->Query(q); + + m_lblEtaReceived.SetWindowText("Return E.T.A."); + m_ckReceived.SetCheck(FALSE); + + if(rs->IsEmpty())//No record + {//set to defaults + m_cbSentTo.Select(m_strSelectedSentTo); + m_cbSentVia.Select(m_strSelectedSentVia); + m_dtSent.SetTime(COleDateTime::GetCurrentTime()); + m_dtRecEta.SetTime(COleDateTime::GetCurrentTime()); + + m_edCharge.SetWindowText("$0.00"); + m_edCost.SetWindowText("$0.00"); + + } + else //there is a record + { + //fill the fields + rs->FetchField("isback",&bData); + if(bData) + { + m_lblEtaReceived.SetWindowText("Received back:"); + m_ckReceived.SetCheck(TRUE); + m_bInitiallyReceived=true; + rs->FetchField("received",&dtData); + m_dtRecEta.SetTime(dtData); + } + else + { + m_bInitiallyReceived=false; + rs->FetchField("eta",&dtData); + m_dtRecEta.SetTime(dtData); + + } + + + rs->FetchField("where",&lData); + m_cbSentTo.Select(lData); + + rs->FetchField("sentvia",&lData); + m_cbSentVia.Select(lData); + + rs->FetchField("sent",&dtData); + m_dtSent.SetTime(dtData); + + + rs->FetchField("waybill",&strData); + m_edWaybill.SetWindowText(strData); + + rs->FetchField("rma",&strData); + m_edRMA.SetWindowText(strData); + + rs->FetchField("cost",&crData); + m_edCost.SetWindowText(cfm->Format(crData)); + + rs->FetchField("charge",&crData); + m_edCharge.SetWindowText(cfm->Format(crData)); + + rs->FetchField("notes",&strData); + m_edNotes.SetWindowText(strData); + + rs->FetchField("wolink",&lData); + strData.Format("Subrepair item from Workorder # %u",lData); + m_strWorkorderID.Format("%u",lData); + SetWindowText(strData); + + rs->FetchField("first",&strData); + m_strOrderer=strData; + + rs->FetchField("last",&strData); + m_strOrderer+=" " + strData; + + //for send mail function if required + rs->FetchField("creator",&lData); + m_strOrdererID.Format("%u",lData); + + rs->FetchField("item",&strData); + m_lblInfo.SetWindowText(strData); + + + + } + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +//********************************* +void CSnREdit::FillLists() +{ + + CString q,strData,strIndex; + long lData; + m_cbSentVia.Clear(); + m_cbSentVia.AddRow(" < na/unknown >","0"); + rs->Query("SELECT nonclients.company_person, nonclients.id " + "FROM nonclients WHERE (((nonclients.type)=2));");//type 2 = couriers/shippers + if(!rs->IsEmpty()) + { + rs->MoveFirst(); + + do + { + rs->FetchField("company_person",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbSentVia.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + + m_cbSentTo.Clear(); + m_cbSentTo.AddRow(" < Not sent out >","0"); + rs->Query("SELECT nonclients.company_person, nonclients.id " + "FROM nonclients WHERE (((nonclients.type)=1)) OR (((nonclients.type)=3));");//type 1 = subcontractors repair centers 3=manufact + if(!rs->IsEmpty()) + { + rs->MoveFirst(); + + do + { + rs->FetchField("company_person",&strData); + rs->FetchField("id",&lData); + strIndex.Format("%u",lData); + m_cbSentTo.AddRow(strData,strIndex); + }while(rs->MoveForward()); + + } + + m_cbSentTo.Select(m_strSelectedSentTo); + m_cbSentVia.Select(m_strSelectedSentVia); +} + +void CSnREdit::OnKillfocusEdcharge() +{ + COleCurrency crData; + CString str; + if(m_edCharge.GetModify()) bModified=true; + m_edCharge.GetWindowText(str); + if(crData.ParseCurrency(str)!=TRUE) + { + AfxMessageBox("I could not interpret your entry in the charge field\r\n" + "I can't save this field until a valid currency entry is made.\r\n" + "If you want to leave it blank put a zero in it."); + m_edCharge.SetFocus(); + return; + } + + m_edCharge.SetWindowText(cfm->Format(crData)); + + +} + +void CSnREdit::OnKillfocusEdcost() +{ + COleCurrency crData; + CString str; + if(m_edCost.GetModify()) bModified=true; + m_edCost.GetWindowText(str); + if(crData.ParseCurrency(str)!=TRUE) + { + AfxMessageBox("I could not interpret your entry in the cost field\r\n" + "I can't save this field until a valid currency entry is made.\r\n" + "If you want to leave it blank, put a zero in it."); + m_edCost.SetFocus(); + return; + } + + m_edCost.SetWindowText(cfm->Format(crData)); + + +} + +void CSnREdit::OnCkreceived() +{ + + if(m_ckReceived.GetCheck()==TRUE)//user has indicated receipt + { + m_lblEtaReceived.SetWindowText("Received back:"); + m_dtRecEta.SetTime(COleDateTime::GetCurrentTime()); + } + else//user has indicated not received for some unknown reason + { //probably just to try the patience of the programmer + //and the resourcefulness of his error checking + m_lblEtaReceived.SetWindowText("Return E.T.A."); + m_dtRecEta.SetTime(COleDateTime::GetCurrentTime()); + //bug avoidance:make sure when header saves this page + //the dates are set correctly depending on user selection + + } + bModified=true; +} + +void CSnREdit::OnLblmanufacturers() +{ + m_strSelectedSentTo=m_cbSentTo.GetCurrentRowID(); + m_strSelectedSentVia=m_cbSentVia.GetCurrentRowID(); + PopupNonClients(3); + FillLists(); + + +} + +void CSnREdit::OnLblrepairctrs() +{ + m_strSelectedSentTo=m_cbSentTo.GetCurrentRowID(); + m_strSelectedSentVia=m_cbSentVia.GetCurrentRowID(); + PopupNonClients(1); + FillLists(); + +} + +void CSnREdit::OnLblsentvia() +{ + m_strSelectedSentVia=m_cbSentVia.GetCurrentRowID(); + m_strSelectedSentTo=m_cbSentTo.GetCurrentRowID(); + PopupNonClients(2); + FillLists(); + +} + +void CSnREdit::PopupNonClients(long type) +{ + CNonClientsDlg d; + long ltype; + ltype=type; + d.SetType(<ype); + d.DoModal(); +} + +void CSnREdit::OnCloseupCbsentto() +{ + bModified=true; + +} + +void CSnREdit::OnCloseupCbsentvia() +{ + bModified=true; +} + +void CSnREdit::OnDatetimechangeDtreceta(NMHDR* pNMHDR, LRESULT* pResult) +{ +bModified=true; + *pResult = 0; +} + +void CSnREdit::OnDatetimechangeDtsent(NMHDR* pNMHDR, LRESULT* pResult) +{ +bModified=true; +COleDateTime dtData; +m_dtSent.GetTime(dtData); +m_dtRecEta.SetTime(dtData); + *pResult = 0; +} + +void CSnREdit::OnKillfocusEdnotes() +{ + if(m_edNotes.GetModify()) bModified=true; + +} + +void CSnREdit::OnKillfocusEdrma() +{ +if(m_edRMA.GetModify()) bModified=true; +} + +void CSnREdit::OnKillfocusEdwaybill() +{ +if(m_edWaybill.GetModify()) bModified=true; +} + +void CSnREdit::OnBtndone() +{ +CString profile,q,strData,msg,subj,unitdesc; + COleDateTime dtData; + COleCurrency crData; + bool bReceived=false; + long lData; + + if(bModified) + { + q.Format("SELECT subrepair.*, probs.wolink, users.first, users.last, [nonclients]![company_person] & \" \" & IIf(IsNull([unitmodels]![description]),[unitmodels]![model],[unitmodels]![description]) & \" \" & IIf(IsNull([sn]),\"\",\"sn:\" & [sn]) AS item " +"FROM ((((subrepair LEFT JOIN probs ON subrepair.link = probs.id) LEFT JOIN users ON subrepair.creator = users.id) LEFT JOIN units ON probs.unit = units.id) LEFT JOIN unitmodels ON units.model = unitmodels.id) LEFT JOIN nonclients ON unitmodels.manufacturer = nonclients.id " +"WHERE (((subrepair.id)=%s));",m_strSubRepairID); + + + + rs->Query(q); + + //save changes if modified +strData= m_cbSentTo.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("where",&lData); + + m_dtSent.GetTime(dtData); + rs->UpdateField("sent",&dtData); + + bReceived=( m_ckReceived.GetCheck() ? true : false); + rs->UpdateField("isback",&bReceived); + + m_dtRecEta.GetTime(dtData); + if(bReceived) + rs->UpdateField("received",&dtData); + else + rs->UpdateField("eta",&dtData); + + strData= m_cbSentVia.GetCurrentRowID(); + lData=atol(strData); + rs->UpdateField("sentvia",&lData); + + m_edWaybill.GetWindowText(strData); + rs->UpdateField("waybill",&strData); + + m_edRMA.GetWindowText(strData); + rs->UpdateField("rma",&strData); + + m_edNotes.GetWindowText(strData); + rs->UpdateField("notes",&strData); + + m_edCost.GetWindowText(strData); + crData.ParseCurrency(strData); + rs->UpdateField("cost",&crData); + + m_edCharge.GetWindowText(strData); + crData.ParseCurrency(strData); + rs->UpdateField("charge",&crData); + + dtData=COleDateTime::GetCurrentTime(); + + rs->UpdateField("modifier",&m_pApp->m_lusrID); + + rs->UpdateField("modified",&dtData); + rs->SaveRecord(); + + rs->SaveRecord(); + } + +//bugbug breceived being used without initialization + if(m_bInitiallyReceived==false && bReceived==true) + { + strData.Format("Should I notify the person who created \r\n" + "this sub repair record:%s \r\n" + "that this item is in?",m_strOrderer); + if(AfxMessageBox(strData,MB_YESNO)==IDYES) + { + m_lblInfo.GetWindowText(unitdesc); + subj.Format("WO#%s unit shipped out has returned",m_strWorkorderID); + msg.Format("%s \r\nsent away for repair has been received back.",unitdesc); + SendMail(msg,subj); + + + } + + } + + + //flush rs + rs->Close(); + //rs->Query("SELECT subrepair.* FROM subrepair WHERE (((subrepair.id)=0));"); + CDialog::OnOK(); +} + +void CSnREdit::SendMail(CString strMsg, CString strSubject) +{ + CString q; + long lData; +COleDateTime dtData,dtData2,dtData3; +bool bData; +//encrypt the subject and message + // + + k->GZEncrypt(&strMsg,false); + k->GZEncrypt(&strSubject,false); + + //save the message + //open the recordset without returning a record (no id=0) + rs->Query("SELECT mail.* FROM mail;"); + rs->AddNewRecord(); + + + //******************************** + // START SAVING FIELDS + //******************************** + //FROM + rs->UpdateField("from",&m_pApp->m_lusrID); + + //DATE: + dtData=COleDateTime::GetCurrentTime(); + rs->UpdateField("date",&dtData); + + //POPUP - wont do anything now + //but in future should cause instant message + bData = true; + rs->UpdateField("popup",&bData); + + //SUBJECT + rs->UpdateField("subject",&strSubject); + + //MESSAGE + rs->UpdateField("message",&strMsg); + + //DELIVERY DATE + //get the date, remove on the date portion which + //sets the time to 0:0:0 (midnight) + dtData3=COleDateTime::GetCurrentTime(); + dtData2.SetDate(dtData3.GetYear(),dtData3.GetMonth(),dtData3.GetDay()); + + rs->UpdateField("deliverydate",&dtData2); + rs->SaveRecord(); + + +//****************** DONE SAVING FIELDS ************* +//*************************************************** + + //retrieve the id number + q.Format("SELECT mail.* FROM mail " + "WHERE (((mail.from)=%u) AND ((mail.date)=#%s#));" + ,m_pApp->m_lusrID,dtData.Format(_T("%m/%d/%Y %H:%M:%S"))); + + rs->Query(q); + + + //should work but.... + ASSERT(!rs->IsEmpty()); + + rs->FetchField("id",&lData); + + + //save the recipient record + + q.Format("INSERT INTO mailroute ( maillink, recipient, remind ) " + "SELECT %u , %s , True;",lData,m_strOrdererID); + + rs->Ex(q); + rs->Close(); + + + + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.h new file mode 100644 index 0000000..a53bce2 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SnREdit.h @@ -0,0 +1,93 @@ +#if !defined(AFX_SNREDIT_H__3EA9F622_453B_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_SNREDIT_H__3EA9F622_453B_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SnREdit.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSnREdit dialog +#include "gzcombo.h" +#include "gzrset.h" +#include "label.h" +#include "gzCurrencyFormatter.h" +class CSnREdit : public CDialog +{ +// Construction +public: + + void SendMail(CString strMsg, CString strSubject); + CString m_strOrderer; + CString m_strOrdererID; + bool m_bInitiallyReceived; + CSnREdit(CWnd* pParent = NULL); // standard constructor + ~CSnREdit(); + bool bModified; + CString m_strSelectedSentTo; + CString m_strSelectedSentVia; + void PopupNonClients(long type); + void FillLists(); + CString m_strWorkorderID; + CString m_strSubRepairID; + GZRset* rs; + GZK* k; + CSpApp* m_pApp; + CgzCurrencyFormatter* cfm; +// Dialog Data + //{{AFX_DATA(CSnREdit) + enum { IDD = IDD_SNREDIT }; + CStatic m_lblInfo; + CLabel m_lblRepairCenters; + CLabel m_lblManufacturers; + CLabel m_lblSentVia; + CStatic m_lblEtaReceived; + CEdit m_edWaybill; + CEdit m_edRMA; + CEdit m_edNotes; + CEdit m_edCost; + CEdit m_edCharge; + CDateTimeCtrl m_dtSent; + CDateTimeCtrl m_dtRecEta; + CButton m_ckReceived; + CgzCombo m_cbSentVia; + CgzCombo m_cbSentTo; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSnREdit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSnREdit) + virtual BOOL OnInitDialog(); + afx_msg void OnKillfocusEdcharge(); + afx_msg void OnKillfocusEdcost(); + afx_msg void OnCkreceived(); + afx_msg void OnLblmanufacturers(); + afx_msg void OnLblrepairctrs(); + afx_msg void OnLblsentvia(); + afx_msg void OnCloseupCbsentto(); + afx_msg void OnCloseupCbsentvia(); + afx_msg void OnDatetimechangeDtreceta(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnDatetimechangeDtsent(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKillfocusEdnotes(); + afx_msg void OnKillfocusEdrma(); + afx_msg void OnKillfocusEdwaybill(); + afx_msg void OnBtndone(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SNREDIT_H__3EA9F622_453B_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.cpp new file mode 100644 index 0000000..d10c803 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.cpp @@ -0,0 +1,214 @@ +// SrchView.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "SrchView.h" +#include "WOHeaderDlg.h" +#include "SimpleWODlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSrchView dialog + + +CSrchView::CSrchView(CWnd* pParent /*=NULL*/) +: CDialog(CSrchView::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSrchView) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp = (CSpApp*)AfxGetApp(); + rsPrint=m_pApp->rsPool->GetRSPrint("CSrchView RSPRINT"); +} + +CSrchView::~CSrchView() +{ + m_pApp->rsPool->ReleaseRS(&rsPrint->m_nID); +} + +void CSrchView::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSrchView) + DDX_Control(pDX, IDC_RED, m_red); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSrchView, CDialog) +//{{AFX_MSG_MAP(CSrchView) +ON_BN_CLICKED(IDC_BTNDONE, OnBtndone) + ON_BN_CLICKED(IDC_BTNCOPY, OnBtncopy) + ON_BN_CLICKED(IDC_BTNEDIT, OnBtnedit) + ON_BN_CLICKED(IDC_BTNCOPYALL, OnBtncopyall) + ON_BN_CLICKED(IDC_BTNPRINT, OnBtnprint) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSrchView message handlers + +BOOL CSrchView::OnInitDialog() +{ + CDialog::OnInitDialog(); + ShowWindow(SW_MAXIMIZE); + m_red.SetWindowText(*m_pstrText); + m_pstrText->MakeLower();//for ease of highlighting + HiLite(); + m_red.SetFocus(); + return FALSE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +//highlight the search words +void CSrchView::HiLite() +{ + //FLAG HEADINGS: + //lowercase because matching to passed string + //which was converted to lowercase for ease of + //searching + FlagWord("workorder:",false,true,false); + FlagWord("invoice#:",false,true,false); + + FlagWord("client reference#:",false,true,false); + FlagWord("client contact:",false,true,false); + FlagWord("our reference#:",false,true,false); + + FlagWord("client:",false,true,false); + FlagWord("tech:",false,true,false); + FlagWord("problem:",false,true,false); + FlagWord("service details:",false,true,false); + + for(int x=0;xGetAt(m_pslHiWords->FindIndex(x)),true,true,true); + + } + + + +} + +void CSrchView::OnBtndone() +{ + CDialog::OnOK(); +} + +void CSrchView::FlagWord(CString strWord, bool bUnderline, bool bBold,bool bColour) +{ + + + CHARFORMAT cf; + + strWord.TrimLeft(" "); + strWord.TrimRight(" "); + strWord.Remove('*'); + strWord.Remove('%'); + + + + int n = m_pstrText->Find(strWord,0); + while (n != -1) + { + m_red.SetSel((long)n, (long)(n+strWord.GetLength())); + cf.dwMask = CFM_COLOR | CFM_BOLD | CFM_UNDERLINE; + if(bColour) + cf.crTextColor=RGB(255,0,0); + else + cf.crTextColor=RGB(0,0,0); + if(bBold) + cf.dwEffects = CFE_BOLD; + if(bUnderline) + cf.dwEffects = cf.dwEffects | CFE_UNDERLINE; + m_red.SetSelectionCharFormat(cf); + + n = m_pstrText->Find(strWord,n+1); + } + m_red.SetSel(0,0); + + + +} + +void CSrchView::OnBtncopy() +{ +long start,end; +m_red.GetSel(start,end); +if(end==0)//nothing selected +{ + //select all + m_red.SetSel(0,-1); +} + +m_red.Copy(); +} + +void CSrchView::OnBtnedit() +{ + if(m_bQuickWO) + { + + CSimpleWODlg qwo; + qwo.SetWorkorderID(&m_strWOID); + qwo.DoModal(); + + } + else + { + CWOHeaderDlg wo; + wo.SetWorkorderID(m_strWOID); + wo.DoModal(); + + } + +} + +void CSrchView::OnBtncopyall() +{ + + //select all + m_red.SetSel(0,-1); + m_red.Copy(); +} + +void CSrchView::OnBtnprint() +{ + CString q; + CString strData; + m_red.GetWindowText(strData); + strData.Replace("\"","''"); + + //set the report text to the memo field in the user record + //this is a workaround to ensure that reports see this as a memo field + q.Format("UPDATE users SET users.rpttext1 = \"%s\" WHERE (((users.id)=%u));",strData,m_pApp->m_lusrID); + rsPrint->Ex(q); + + + //fetch the record + q.Format("SELECT users.rpttext1 AS srchresults, \"%s\" AS srchuser FROM users " + "WHERE (((users.id)= %u));", m_pApp->m_strCurrentUserName, m_pApp->m_lusrID); + + rsPrint->Query(q); + + + + if(!rsPrint->IsEmpty()) + { + m_pApp->PrintCMReportRDC("Search results",rsPrint->RecordSetPointer()); +#ifdef _DEBUG + m_pApp->CreateTTX("srch.ttx",rsPrint->RecordSetPointer()); +#endif + } + else + AfxMessageBox("There is no data to print"); + + +} + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.h new file mode 100644 index 0000000..dc75c37 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/SrchView.h @@ -0,0 +1,62 @@ +#if !defined(AFX_SRCHVIEW_H__B72D0981_5043_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_SRCHVIEW_H__B72D0981_5043_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SrchView.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSrchView dialog +#include "gzrset.h" +class CSrchView : public CDialog +{ +// Construction +public: + ~CSrchView(); + GZRset* rsPrint; + CSpApp* m_pApp; + + bool m_bQuickWO; + CString m_strWOID; + void FlagWord(CString strWord, bool bUnderline, bool bBold, bool bColour); + int m_nKeywords; + void HiLite(); + CString* m_pstrText; + CStringList* m_pslHiWords; + CSrchView(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CSrchView) + enum { IDD = IDD_SRCHVIEW }; + CRichEditCtrl m_red; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSrchView) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSrchView) + virtual BOOL OnInitDialog(); + afx_msg void OnBtndone(); + afx_msg void OnBtncopy(); + afx_msg void OnBtnedit(); + afx_msg void OnBtncopyall(); + afx_msg void OnBtnprint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SRCHVIEW_H__B72D0981_5043_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.cpp new file mode 100644 index 0000000..dcaadc5 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.cpp @@ -0,0 +1,143 @@ +// StatusDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "StatusDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CStatusDlg dialog + + +CStatusDlg::CStatusDlg(CWnd* pParent /*=NULL*/) + : CDialog(CStatusDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CStatusDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_pApp= (CSpApp*)AfxGetApp(); + /* + rs=new GZRset("Error: Record status screen"); + rs->SetConnect(m_pApp->strConnectString); + */ +//Initialize recordset pointer + +rs=m_pApp->rsPool->GetRS("CStatusDlg"); +} + + + +CStatusDlg::~CStatusDlg() +{ +m_pApp->rsPool->ReleaseRS(&rs->m_nID); +} + +void CStatusDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CStatusDlg) + DDX_Control(pDX, IDC_STATUSMSG, m_Status); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CStatusDlg, CDialog) + //{{AFX_MSG_MAP(CStatusDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CStatusDlg message handlers + +BOOL CStatusDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + //Security(); + + m_Status.SetFontName("Tahoma"); + m_Status.SetFontSize(12); + m_Status.SetFontBold(FALSE); + m_Status.SetTextColor(RGB(0,0,0)); + Display(); + + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +//****************************************************8 +void CStatusDlg::SetValues(CString *creator, CString *modifier, COleDateTime *created, COleDateTime *modified) +{ + m_pCreator=creator; + m_pModifier=modifier; + m_pCreated=created; + m_pModified=modified; + +} + +void CStatusDlg::Display() +{ + CString q,strData,strRecStatus; + + + + q.Format("SELECT [first] & \" \" & [last] AS fullname " + "FROM users WHERE (((users.id)=%s));",*m_pCreator); + + rs->Query(q); + if(rs->IsEmpty()) + strData="unknown"; + else + rs->FetchField("fullname",&strData); + + strRecStatus="This record was originally created by " + strData; + + strRecStatus=strRecStatus+" on:\r\n" + m_pCreated->Format(); + + + q.Format("SELECT [first] & \" \" & [last] AS fullname " + "FROM users WHERE (((users.id)=%s));",*m_pModifier); + + rs->Query(q); + if(rs->IsEmpty()) + strData="unknown"; + else + rs->FetchField("fullname",&strData); + strRecStatus= strRecStatus + "\r\n\r\nand last modified by " + strData; + strRecStatus=strRecStatus+" on:\r\n" + m_pModified->Format(); + + strRecStatus=strRecStatus + "."; + m_Status.SetWindowText(strRecStatus); + +} + + +////Added v1.9.4.4 follows wo security since there is no separate one for status +//void CStatusDlg::Security() +//{ +// m_bReadOnly=false; +// int x=m_pApp->Allowed(RWORKORDER,true); +// if(x==0)//no access allowed +// { +// m_pApp->SecurityWarning(); +// CDialog::OnCancel(); +// } +// if(x==2)//read only +// { +// m_bReadOnly=true; +// m_btnAdd.ShowWindow(FALSE); +// m_btnDelete.ShowWindow(FALSE); +// m_ckActive.EnableWindow(FALSE); +// m_edDescription.SetReadOnly(TRUE); +// m_edName.SetReadOnly(TRUE); +// +// +// } +//} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.h new file mode 100644 index 0000000..a6bfd06 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StatusDlg.h @@ -0,0 +1,61 @@ +#if !defined(AFX_STATUSDLG_H__C7047C82_19FC_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_STATUSDLG_H__C7047C82_19FC_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// StatusDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CStatusDlg dialog +#include "gzrset.h" +#include "label.h" + +class CStatusDlg : public CDialog +{ +// Construction +public: + ~CStatusDlg(); + void Display(); + void SetValues(CString * creator,CString* modifier, COleDateTime* created, COleDateTime* modified); + CStatusDlg(CWnd* pParent = NULL); // standard constructor + CString * m_pCreator; + COleDateTime * m_pCreated; + CString * m_pModifier; + COleDateTime * m_pModified; + CSpApp* m_pApp; + GZRset* rs; + + + //void Security(); +// Dialog Data + //{{AFX_DATA(CStatusDlg) + enum { IDD = IDD_RECSTATUS }; + CLabel m_Status; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CStatusDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CStatusDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STATUSDLG_H__C7047C82_19FC_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.cpp new file mode 100644 index 0000000..cdfc71a --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// sp.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.h new file mode 100644 index 0000000..ca7a472 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StdAfx.h @@ -0,0 +1,42 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A74C37E7_FC36_11D3_964F_00C0F02C4B69__INCLUDED_) +#define AFX_STDAFX_H__A74C37E7_FC36_11D3_964F_00C0F02C4B69__INCLUDED_ + + +//#define AYQB 1 //meaning Build as AyaNovaQBI version + +#define WINVER 0x0410 + +#ifdef AYQB +#define SCDATAFILE "QBTRIAL.AYA" +#else +#define SCDATAFILE "scdata.sc" +#endif + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A74C37E7_FC36_11D3_964F_00C0F02C4B69__INCLUDED_) +#include + +#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF") +#import "C:\PROGRAM FILES\COMMON FILES\System\ado\MSJRO.DLL" no_namespace \ No newline at end of file diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.cpp new file mode 100644 index 0000000..495b144 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.cpp @@ -0,0 +1,488 @@ +//------------------------------------------------------------------------------ +// FILE NAME: StringParser.cpp +// HEADER: StringParser.h +// +// PURPOSE: Implementation of the CStringParser class. +// +// DESCRIPTION: This class acepts a string and immediately parses it into +// separate fields based on the delimiter character specified by +// the programmer. The separated fields are stored in a +// CStringArray, and the 0th element in the array contains the +// original string. Access to the separated fields is 1-based +// (the first field is in index 1, and so on). +// +// If you are parsing quoted strings, it is IMPARATIVE that the +// quoted strings be formatted correctly. Otherwise you will get +// what appears to be bizarre results. +// +// DISCLAIMER: At first glance, it may seem like the code is somewhat verbose +// and I might have taken the long way around to perform some +// tasks, but I think it makes it easier for someone else to follow +// when I do that. Maintainability is probably the most important +// aspect of coding (after reliability of course). +// +// CHANGE HISTORY: +// DATE INIT CHANGE DESCRIPTION +// -------- ---- -------------------------------------------------------- +// 07/20/2000 jms Initial code completed. +// 08/09/2000 jms Added a way to submit a new string to facilitate the use +// of the same object instance when a subsewquent string +// needs to be parsed. +// 01/12/2001 jms Added a way to find strings withion the parsed results. +// 01/20/2001 jms Added support for quoted strings. +//------------------------------------------------------------------------------ + +#include "stdafx.h" + +#include "StringParser.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::CStringParser() +// +// PURPOSE: Constructor - initializes the array of strings and calls the +// ParseString() function. +// +// PARMETERS: CString sString The string to be parsed +// char cDelimiter The delimiter character used to parse the +// string +// +// RETURNS: N/A +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 07/20/2000 jms Initial development. +//------------------------------------------------------------------------------ +CStringParser::CStringParser(CString sString, char cDelimiter) +{ + m_aStrings.SetSize(0,10); + ResetOriginalString(sString, cDelimiter); +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::CStringParser() +// +// PURPOSE: Constructor - initializes the array of strings and calls the +// ParseString() function. +// +// PARMETERS: CString sString The string to be parsed. +// char cDelimiter The delimiter character used to parse the +// string. +// char cQuoter The quote character we should be looking +// for. +// +// RETURNS: N/A +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- -------------------------------------------------------- +// 01/20/2001 jms Added overloaded version of constructor to support +// quoted strings. +//------------------------------------------------------------------------------ +CStringParser::CStringParser(CString sString, char cDelimiter, char cQuoter) +{ + m_aStrings.SetSize(0,10); + ResetOriginalString(sString, cDelimiter, cQuoter); +} + +//------------------------------------------------------------------------------ +// NAME: CStringParser::CStringParser() +// +// PURPOSE: Constructor - does nothing +// +// PARMETERS: CString sString The string to be parsed. +// +// RETURNS: N/A +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- -------------------------------------------------------- +// 04/25/2001 jc Added overloaded version of constructor to support +// initialization without other data +//------------------------------------------------------------------------------ +CStringParser::CStringParser() +{ + m_aStrings.SetSize(0,10); + +} + +//------------------------------------------------------------------------------ +// NAME: CStringParser::~CStringParser() +// +// PURPOSE: Destructor - removes all of the array elements from the +// CStringArray. +// +// PARMETERS: None +// +// RETURNS: None +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 07/20/2000 jms Initial development. +// 08/09/2000 jms Added call to new Clear() function. +//------------------------------------------------------------------------------ +CStringParser::~CStringParser() +{ + Clear(); +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::Clear() +// +// PURPOSE: Clears the string table. +// +// PARMETERS: None +// +// RETURNS: None +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 08/09/2000 jms Added function. +//------------------------------------------------------------------------------ +void CStringParser::Clear() +{ + if (m_nCount > 0) + { + m_aStrings.RemoveAll(); + } +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::ResetOriginalString() +// +// PURPOSE: Clears the string table. +// +// PARMETERS: None +// +// RETURNS: None +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 08/09/2000 jms Added function. +//------------------------------------------------------------------------------ +void CStringParser::ResetOriginalString(CString sString, char cDelimiter) +{ + Clear(); + m_aStrings.Add(sString); + m_cDelimiter = cDelimiter; + m_cQuoter = '\0'; + m_nCount = 0; + ParseString(); +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::ResetOriginalString() +// +// PURPOSE: Clears the string table. +// +// PARMETERS: None +// +// RETURNS: None +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 08/09/2000 jms Added function. +//------------------------------------------------------------------------------ +void CStringParser::ResetOriginalString(CString sString, char cDelimiter, char cQuoter) +{ + Clear(); + m_aStrings.Add(sString); + m_cDelimiter = cDelimiter; + m_cQuoter = cQuoter; + m_nCount = 0; + ParseStringWithQuoter(); +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::GetField() +// +// PURPOSE: Returns the CString stored in the array element specified by +// the nIndex parameter. If the specified index is greater than +// the number of elements, it is an error. +// +// PARMETERS: int nIndex The index of the desired array item. +// +// RETURNS: CString sBuffer the string retrieved from the array. +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 07/20/2000 jms Initial development. +//------------------------------------------------------------------------------ +CString CStringParser::GetField(int nIndex) +{ + CString sBuffer; + sBuffer.Empty(); + if (m_nCount >= nIndex) + { + sBuffer = m_aStrings.GetAt(nIndex); + } + else + { + sBuffer = "ERROR: Array index out of range."; + } + return sBuffer; +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::ParseString() +// +// PURPOSE: Separates the fields out of a copy of the original string by +// searching for the specified delimiter character. As the string +// is searched, it becomes shorter by deleting the most recently +// found field (and the next delimiter, if one exists) from the +// beginning of itself. +// +// PARMETERS: None +// +// RETURNS: int The number of fields found in the original string. +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 07/20/2000 jms Initial development. +//------------------------------------------------------------------------------ +int CStringParser::ParseString() +{ + // get a copy of the string + CString sWorkString = GetOriginalString(); + CString sBuffer; + int pos = 0; + + m_nCount = 0; + + // while the string is not empty... + while (!sWorkString.IsEmpty()) + { + // find the position of the next delimiter + pos = sWorkString.Find(m_cDelimiter); + // if a delimiter is found + if (pos >= 0) + { + // store the field + sBuffer = sWorkString.Left(pos); + // delete the field and the found delimiter + sWorkString = sWorkString.Mid(pos + 1); + } + // otherwise, if a delimiter isn't found + else + { + // the rest of the string is a field + sBuffer = sWorkString; + // and make the string empty + sWorkString.Empty(); + } + // add the field to the CStringArray + m_aStrings.Add(sBuffer); + // increment the counter + m_nCount++; + } + return m_nCount; +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::ParseStringWithQuoter() +// +// PURPOSE: Separates the fields out of a copy of the original string by +// searching for the specified delimiter character. As the string +// is searched, it becomes shorter by deleting the most recently +// found field (and the next delimiter, if one exists) from the +// beginning of itself. +// +// This version of ParseString handles a quoted string. A quoted +// string may have the specified delimiter in an embedded between +// quote characters, and this instance of the delimiter must be +// ignored. +// +// PARMETERS: None +// +// RETURNS: int The number of fields found in the original string. +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 01/20/2001 jms Added this function. +//------------------------------------------------------------------------------ +int CStringParser::ParseStringWithQuoter() +{ + // get a copy of the string + CString sWorkString = GetOriginalString(); + CString sBuffer; + int pos = 0; + + m_nCount = 0; + + // while the string is not empty... + while (!sWorkString.IsEmpty()) + { + // find the position of the next delimiter + pos = sWorkString.Find(m_cDelimiter); + // if a delimiter is found + if (pos >= 0) + { + // if the first character is the specified quoter + if (sWorkString.GetAt(0) == m_cQuoter) + { + // we have work to do + sBuffer.Empty(); + int nLength = 0; + BOOL bDone = FALSE; + + do + { + //add the next character + sBuffer += CString(sWorkString.GetAt(nLength)); + nLength++; + + // if string is longer than one char and both ends are the quote char + if (nLength > 1 && sBuffer.GetAt(nLength - 1) == m_cQuoter) + { + // we are done + bDone = TRUE; + } + } while (!bDone); + + // adjust our work string + sWorkString = sWorkString.Mid(nLength + 1); + } + else + { + sBuffer = sWorkString.Left(pos); + sWorkString = sWorkString.Mid(pos + 1); + } + } + // otherwise, if a delimiter isn't found + else + { + // the rest of the string is a field + sBuffer = sWorkString; + // and make the string empty + sWorkString.Empty(); + } + // add the field to the CStringArray + m_aStrings.Add(sBuffer); + // increment the counter + m_nCount++; + } + + return m_nCount; +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::FindExact() +// +// PURPOSE: Searches the entire array (excluding item 0) for an exact match +// of the specified string. +// +// PARMETERS: CString sText The string we're looking for +// int& nElement The element number of the found string +// or SP_NOTFOUND if not found. +// BOOL bCaseSensitive Case sensitivity matters +// +// RETURNS: CString The matching string if any. +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// ---------- ---- ----------------------------------------------------------- +// 01/12/2001 jms Added function. +//------------------------------------------------------------------------------ +CString CStringParser::FindExact(CString sText, int* nElement, BOOL bCaseSensitive/*=FALSE*/) +{ + if (!bCaseSensitive) + { + sText.MakeUpper(); + } + *nElement = SP_NOTFOUND; + + CString sResult = ""; + BOOL bFound = FALSE; + + for (int i = 1; i <= m_nCount; i++) + { + sResult = m_aStrings.GetAt(i); + if (!bCaseSensitive) + { + sResult.MakeUpper(); + } + if (sResult == sText) + { + *nElement = i; + sResult = m_aStrings.GetAt(i); + bFound = TRUE; + break; + } + sResult.Empty(); + } + return sResult; +} + + +//------------------------------------------------------------------------------ +// NAME: CStringParser::Find() +// +// PURPOSE: Searches the entire array (excluding item 0) for any string that +// contains the specified string. +// +// PARMETERS: CString sText The string we're looking for +// int& nElement The element number of the found string +// or SP_NOTFOUND if not found. +// BOOL bCaseSensitive Case sensitivity matters +// +// RETURNS: CString The matching string if any. +// +// CHANGE LOG: +// DATE INIT DESCRIPTION +// -------- ---- ------------------------------------------------------------- +// 01/12/01 jms Added function. +//------------------------------------------------------------------------------ +CString CStringParser::Find(CString sText, int* nElement, BOOL bCaseSensitive/*=FALSE*/) +{ + if (!bCaseSensitive) + { + sText.MakeUpper(); + } + *nElement = SP_NOTFOUND; + + CString sResult = ""; + BOOL bFound = FALSE; + for (int i = 1; i <= m_nCount; i++) + { + sResult = m_aStrings.GetAt(i); + if (!bCaseSensitive) + { + sResult.MakeUpper(); + } + if (sResult.Find(sText) >= 0) + { + //save the position at which we found the string + *nElement = i; + // get it again (so we can get it in it's native form) + sResult = m_aStrings.GetAt(i); + bFound = TRUE; + break; + } + sResult.Empty(); + } + return sResult; +} + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.h new file mode 100644 index 0000000..d6bb5d2 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/StringParser.h @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +// FILE NAME: StringParser.h +// +// PURPOSE: Definition of the CStringParser class. +// +// DESCRIPTION: This class acepts a string and immediately parses it into +// separate fields based on the delimiter character specified by +// the programmer. The separated fields are stored in a +// CStringArray, and the 0th element in the array contains the +// original string. Access to the separated fields is 1-based +// (the first field is in index 1, and so on). +// +// REVISION LOG: +// DATE INIT REVISION COMMENT +// -------- ---- -------- --------------------------------------------------- +// +// CHANGE HISTORY: +// DATE INIT CHANGE DESCRIPTION +// -------- ---- ------------------------------------------------------------- +// 07/15/00 jms New file +//------------------------------------------------------------------------------ + +#ifndef __STRINGPARSER_H +#define __STRINGPARSER_H + +#include + +const int SP_NOTFOUND = -1; + +class CStringParser: public CObject +{ +private: + // data members + CStringArray m_aStrings; + int m_nCount; + char m_cDelimiter; + char m_cQuoter; + + // methods + int ParseString(); + int ParseStringWithQuoter(); + +public: + // data members + + // ctor/dtor + CStringParser(); + CStringParser(CString sString, char cDelimiter); + CStringParser(CString sString, char cDelimiter, char cQuoter); + ~CStringParser(); + + // methods + void Clear (); + CString GetField (int nIndex); + int GetCount () { return m_nCount; }; + CString GetOriginalString () { return m_aStrings.GetAt(0); }; + void ResetOriginalString(CString sString, char cDelimiter); + void ResetOriginalString(CString sString, char cDelimiter, char cQuoter); + CString FindExact (CString sText, int* nElement, BOOL bCaseSensitive=FALSE); + CString Find (CString sText, int* nElement, BOOL bCaseSensitive=FALSE); +}; + + +#endif + + + diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.cpp new file mode 100644 index 0000000..416cc95 --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.cpp @@ -0,0 +1,66 @@ +// TED.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "TED.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTED dialog + + +CTED::CTED(CWnd* pParent /*=NULL*/) + : CDialog(CTED::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTED) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CTED::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTED) + DDX_Control(pDX, IDC_EDTEXT, m_edText); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTED, CDialog) + //{{AFX_MSG_MAP(CTED) + ON_BN_CLICKED(IDC_BTNCOPYALL, OnBtncopyall) + ON_BN_CLICKED(IDC_BTNCOPYSELECTION, OnBtncopyselection) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTED message handlers + +BOOL CTED::OnInitDialog() +{ + CDialog::OnInitDialog(); + +m_edText.SetWindowText(m_strText); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CTED::OnBtncopyall() +{ + m_edText.SetSel(0,-1); + m_edText.Copy(); + +} + +void CTED::OnBtncopyselection() +{ + m_edText.Copy(); + +} diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.h b/archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.h new file mode 100644 index 0000000..f0cb4fd --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/TED.h @@ -0,0 +1,49 @@ +#if !defined(AFX_TED_H__4C3C43E1_500A_11D4_964F_00C0F02C4B69__INCLUDED_) +#define AFX_TED_H__4C3C43E1_500A_11D4_964F_00C0F02C4B69__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TED.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CTED dialog + +class CTED : public CDialog +{ +// Construction +public: + CString m_strText; + CTED(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CTED) + enum { IDD = IDD_DISPLAYTEXT }; + CEdit m_edText; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTED) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTED) + virtual BOOL OnInitDialog(); + afx_msg void OnBtncopyall(); + afx_msg void OnBtncopyselection(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TED_H__4C3C43E1_500A_11D4_964F_00C0F02C4B69__INCLUDED_) diff --git a/archive/ayanova 1.9.4 CE final release db schema 171/sp/UnitsDlg.cpp b/archive/ayanova 1.9.4 CE final release db schema 171/sp/UnitsDlg.cpp new file mode 100644 index 0000000..db1f58d --- /dev/null +++ b/archive/ayanova 1.9.4 CE final release db schema 171/sp/UnitsDlg.cpp @@ -0,0 +1,1678 @@ +// UnitsDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "sp.h" +#include "UnitsDlg.h" +#include "NonClientsDlg.h" +#include "ModelsDlg.h" +#include "ClientsDlg.h" +#include "PM.h" +#include "SimpleDate.h" +#include "GenericPopupList.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CUnitsDlg dialog + + +CUnitsDlg::CUnitsDlg(CWnd* pParent /*=NULL*/) +: CDialog(CUnitsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CUnitsDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + m_bAddMode=false; + m_pApp= (CSpApp*)AfxGetApp(); + + /* + rs=new GZRset("Error: Units dialog"); + rs->SetConnect(m_pApp->strConnectString); + + cbrs=new GZRset("Error: Units dialog combo box recordset\r\n"); + cbrs->SetConnect(m_pApp->strConnectString); + */ + //Initialize recordset pointer + + +rs=m_pApp->rsPool->GetRS("CUnitsDlg (RS)"); +cbrs=m_pApp->rsPool->GetRS("CUnitsDlg (CBRS)"); + + m_pstrReturnUnit=NULL; + m_pstrReturnClient=NULL; + m_strSelectedUnit.Empty(); + m_strSelectedClient.Empty(); + m_strSelectedModel.Empty(); + + m_bListByDescription=true; + m_bIniting=true; + m_bSubUnitSelected=false; + m_bAddIsDuplicate=false; + + +} + + + + +//***************************** +CUnitsDlg::~CUnitsDlg() +{ + m_pApp->rsPool->ReleaseRS(&rs->m_nID); + m_pApp->rsPool->ReleaseRS(&cbrs->m_nID); +} + + + + +//************************************* +void CUnitsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CUnitsDlg) + DDX_Control(pDX, IDC_LBL_SUB_UNITS, m_lblSubUnits); + DDX_Control(pDX, IDC_CBSN2, m_cbSubSn); + DDX_Control(pDX, IDC_BTNADDDUPLICATE, m_btnAddDuplicate); + DDX_Control(pDX, IDC_EDLASTMETERREADING, m_edLastMeterReading); + DDX_Control(pDX, IDC_BTNPM, m_btnPM); + DDX_Control(pDX, IDC_LBLBYMODEL, m_lblByModel); + DDX_Control(pDX, IDC_LBLBYDESC, m_lblByDesc); + DDX_Control(pDX, IDC_CKRENTAL, m_ckRental); + DDX_Control(pDX, IDC_EDID3, m_edID3); + DDX_Control(pDX, IDC_EDID2, m_edID2); + DDX_Control(pDX, IDC_EDID1, m_edID1); + DDX_Control(pDX, IDC_CKPM, m_ckPM); + DDX_Control(pDX, IDC_LBLSNLIST, m_lblSNList); + DDX_Control(pDX, IDC_LBLRESELLERS, m_lblResellers); + DDX_Control(pDX, IDC_LBLMODEL, m_lblModel); + DDX_Control(pDX, IDC_LBLCLIENT, m_lblClient); + DDX_Control(pDX, IDC_EDWARRANTYTERMS, m_edWarrantyTerms); + DDX_Control(pDX, IDC_EDSN, m_edSN); + DDX_Control(pDX, IDC_EDRECEIPT, m_edReceipt); + DDX_Control(pDX, IDC_EDNOTES, m_edNotes); + DDX_Control(pDX, IDC_EDDESCRIPTION, m_edDescription); + DDX_Control(pDX, IDC_DTPURCHASED, m_dtPurchased); + DDX_Control(pDX, IDC_DONE, m_btnDone); + DDX_Control(pDX, IDC_CKBOUGHTHERE, m_ckBoughtHere); + DDX_Control(pDX, IDC_CBSN, m_cbSN); + DDX_Control(pDX, IDC_CBRESELLERS, m_cbResellers); + DDX_Control(pDX, IDC_CBMODELS, m_cbModels); + DDX_Control(pDX, IDC_CBCLIENTS, m_cbClients); + DDX_Control(pDX, IDC_BTNADD, m_btnAdd); + DDX_Control(pDX, IDC_BTNDELETE, m_btnDelete); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CUnitsDlg, CDialog) +//{{AFX_MSG_MAP(CUnitsDlg) +ON_CBN_CLOSEUP(IDC_CBSN, OnCloseupCbsn) +ON_CBN_CLOSEUP(IDC_CBMODELS, OnCloseupCbmodels) +ON_CBN_CLOSEUP(IDC_CBCLIENTS, OnCloseupCbclients) +ON_BN_CLICKED(IDC_DONE, OnDone) +ON_BN_CLICKED(IDC_LBLRESELLERS, OnLblresellers) +ON_BN_CLICKED(IDC_LBLMODEL, OnLblmodel) +ON_BN_CLICKED(IDC_LBLCLIENT, OnLblclient) +ON_EN_KILLFOCUS(IDC_EDWARRANTYTERMS, OnKillfocusEdwarrantyterms) +ON_EN_KILLFOCUS(IDC_EDSN, OnKillfocusEdsn) +ON_EN_KILLFOCUS(IDC_EDRECEIPT, OnKillfocusEdreceipt) +ON_EN_KILLFOCUS(IDC_EDNOTES, OnKillfocusEdnotes) +ON_EN_KILLFOCUS(IDC_EDDESCRIPTION, OnKillfocusEddescription) +ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTPURCHASED, OnDatetimechangeDtpurchased) +ON_BN_CLICKED(IDC_CKPM, OnCkpm) +ON_BN_CLICKED(IDC_CKBOUGHTHERE, OnCkboughthere) +ON_CBN_CLOSEUP(IDC_CBRESELLERS, OnCloseupCbresellers) +ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete) +ON_BN_CLICKED(IDC_BTNADD, OnBtnadd) + ON_BN_CLICKED(IDC_CKRENTAL, OnCkrental) + ON_BN_CLICKED(IDC_LBLBYDESC, OnLblbydesc) + ON_BN_CLICKED(IDC_LBLBYMODEL, OnLblbymodel) + ON_EN_KILLFOCUS(IDC_EDID1, OnKillfocusEdid1) + ON_EN_KILLFOCUS(IDC_EDID2, OnKillfocusEdid2) + ON_EN_KILLFOCUS(IDC_EDID3, OnKillfocusEdid3) + ON_BN_CLICKED(IDC_BTNPM, OnBtnpm) + ON_EN_KILLFOCUS(IDC_EDLASTMETERREADING, OnKillfocusEdlastmeterreading) + ON_BN_CLICKED(IDC_BTNADDDUPLICATE, OnBtnaddduplicate) + ON_CBN_CLOSEUP(IDC_CBSN2, OnCloseupCbsn2) + ON_BN_CLICKED(IDC_LBL_SUB_UNITS, OnLblSubUnits) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CUnitsDlg message handlers +void CUnitsDlg::SetReturnStrings(CString *sn,CString *client) +{ + m_pstrReturnUnit=sn; + m_pstrReturnClient=client; + + //specific sn requested? + if(!m_pstrReturnUnit->IsEmpty()) + m_strSelectedUnit=*m_pstrReturnUnit; + + //specific client requested? + if(!m_pstrReturnClient->IsEmpty()) + m_strSelectedClient=*m_pstrReturnClient; +} + + +//*********************************** +BOOL CUnitsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + CWaitCursor wait; + ShowWindow(SW_HIDE); + Security(); + //make "hyperlinks" + m_lblClient.SetTextColor(RGB(0,0,255)); + m_lblClient.SetFontUnderline(TRUE); + m_lblClient.SetLink(TRUE); + m_lblClient.SetLinkCursor(m_pApp->hcHand); + m_lblClient.SetLinkURL(""); + + m_lblModel.SetTextColor(RGB(0,0,255)); + m_lblModel.SetFontUnderline(TRUE); + m_lblModel.SetLink(TRUE); + m_lblModel.SetLinkCursor(m_pApp->hcHand); + m_lblModel.SetLinkURL(""); + + m_lblResellers.SetTextColor(RGB(0,0,255)); + m_lblResellers.SetFontUnderline(TRUE); + m_lblResellers.SetLink(TRUE); + m_lblResellers.SetLinkCursor(m_pApp->hcHand); + m_lblResellers.SetLinkURL(""); + + m_lblByDesc.SetTextColor(RGB(0,0,255)); + m_lblByDesc.SetFontUnderline(TRUE); + m_lblByDesc.SetLink(TRUE); + m_lblByDesc.SetLinkCursor(m_pApp->hcHand); + m_lblByDesc.SetLinkURL(""); + + m_lblByModel.SetTextColor(RGB(0,0,255)); + m_lblByModel.SetFontUnderline(TRUE); + m_lblByModel.SetLink(TRUE); + m_lblByModel.SetLinkCursor(m_pApp->hcHand); + m_lblByModel.SetLinkURL(""); + + m_lblSubUnits.SetTextColor(RGB(0,0,255)); + m_lblSubUnits.SetFontUnderline(TRUE); + m_lblSubUnits.SetLink(TRUE); + m_lblSubUnits.SetLinkCursor(m_pApp->hcHand); + m_lblSubUnits.SetLinkURL(""); + + //SETUP FOR MODE + + //display clients name at top and + //filter by passed sn/client + + FillModelList(); + FillClientList(); + FillResellerList(); + //EnableFields(false); + //must be called last, as is dependant on other list values + FillSNList(); + + ShowWindow(SW_MAXIMIZE); + m_cbSN.SetFocus(); + m_bIniting=false; + //=================================================== + // SET WINDOW SIZE TO MATCH WORK AREA + ShowWindow(SW_SHOWMAXIMIZED); + CRect workarea; + SystemParametersInfo(SPI_GETWORKAREA,0,&workarea,0); + SetWindowPos(NULL,workarea.left,workarea.top,workarea.Width(),workarea.Height(),SWP_NOZORDER); + //=================================================== + return FALSE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +//***************************************** +//====================================== +void CUnitsDlg::FillSNList() +{ + + CString q,client,model,strData,strIndex; + long lData; + m_cbSN.Clear(); + m_cbSubSn.Clear(); + //client=m_cbClients.GetCurrentRowID(); + //model=m_cbModels.GetCurrentRowID(); + + //No filter + //if(client=="0" && model == "0") + q="SELECT units.sn, units.id FROM units ORDER BY units.sn;"; + /* + //Filter by client + if(client!="0" && model == "0") + q.Format("SELECT units.sn, units.id FROM units " + "WHERE (((units.client)=%s)) ORDER BY units.sn;",client); + + //Filter by model number + if(client=="0" && model != "0") + q.Format(" SELECT units.sn, units.id FROM units " + "WHERE (((units.model)=%s)) ORDER BY units.sn;",model); + + //Filter by client and model number + if(client!="0" && model != "0") + q.Format("SELECT units.sn, units.id FROM units " + "WHERE (((units.client)=%s) AND ((units.model)=%s));",client,model); + */ + + //Set the default + strData="