home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / IOC / LANCELOT / LTIMEC.CPP < prev    next >
C/C++ Source or Header  |  1995-04-07  |  23KB  |  597 lines

  1. /*******************************************************************************
  2. * FILE NAME: ltimec.cpp                                                        *
  3. *                                                                              *
  4. * DESCRIPTION:                                                                 *
  5. *                                                                              *
  6. * Class                                                                        *
  7. *   TimeCard                                                                   *
  8. *   TimeCardPage                                                               *
  9. *                                                                              *
  10. * COPYRIGHT:                                                                   *
  11. *   Licensed Materials - Property of IBM                                       *
  12. *   (C) Copyright IBM Corporation 1992, 1995                                   *
  13. *   All Rights Reserved                                                        *
  14. *   US Government Users Restricted Rights - Use, duplication, or disclosure    *
  15. *   restricted by GSA ADP Schedule Contract with IBM Corp.                     *
  16. *                                                                              *
  17. * CHANGE HISTORY:                                                              *
  18. *******************************************************************************/
  19.  
  20. #ifndef _IBASE_                         //Make sure ibase.hpp is included
  21.   #include <ibase.hpp>                  //  since that is where IC_<environ>
  22. #endif                                  //  is defined.
  23. #include <stdio.h>
  24. #include <iexcbase.hpp>
  25. #include <ireslib.hpp>
  26. #include <ihelp.hpp>
  27. #include <iscroll.hpp>
  28. #include "lancelot.h"
  29. #include "ltimec.hpp"
  30.  
  31.  
  32. /*************************************************************/
  33. /* CLASS TimeCardPage - constructor                          */
  34. /*************************************************************/
  35.  
  36. TimeCardPage :: TimeCardPage( IWindow*        pParent,
  37.                         ProjectPage*   pProjPage,
  38.                         TasksPage*     pTasksPage,
  39.                         const IString&  aKey)
  40.               : IMultiCellCanvas( ID_TIMECARD_PAGE, pParent, pParent),
  41.                 pageButtons(ID_TIMECARD_PAGE_BUTTONS, this, this, false),
  42.                 pageScrollButtons( ID_TIMECARD_PAGE_SCROLL_BUTTONS,
  43.                         this, this ),
  44.                 tcVp(ID_TIMECARD_VP, this, this,
  45.                         IRectangle(),
  46.                         (IViewPort::defaultStyle() &
  47.                         ~IViewPort::asNeededVerticalScrollBar ) |
  48.                         IViewPort::alwaysVerticalScrollBar),
  49.                 totalHoursText(ID_NO_ITEM, this , this ),
  50.                 totalBillableHoursText (ID_NO_ITEM, this, this ),
  51.                 pProjectPage(pProjPage),
  52.                 pTasksPage(pTasksPage),
  53.                 weekEndingDate(IDate()),
  54.                 pTimeCardData( new
  55.                         LTimeCardData( aKey, weekEndingDate.date() ) ),
  56.                 timeCard(&tcVp,
  57.                         pProjPage,
  58.                         pTasksPage,
  59.                         pTimeCardData),
  60. #ifdef IC_PM
  61.                 pieChart( ID_TIMECARD_PIECHART,
  62.                         this, this, IRectangle(), pTimeCardData ),
  63. #endif
  64.                 Key(aKey),
  65.                 thePageSettings( IApplication::current().userResourceLibrary().loadString(
  66.                         STR_TCD_TIMECARD_TAB), NULL,
  67.                         INotebook::PageSettings::autoPageSize
  68.                         | INotebook::PageSettings::majorTab )
  69. {
  70.   pageScrollButtons.setDisplayText(pTimeCardData->theWeek.asString());
  71.  
  72.   totalHoursText.setAlignment(IStaticText::topCenter);
  73.   totalBillableHoursText.setAlignment(  IStaticText::topCenter);
  74.  
  75.   setDisplayText(IString(timeCard.getTotalHours()),
  76.                  IString(timeCard.getTotalBillable()));
  77.  
  78.   setCells();
  79.   handleIt();
  80. };
  81.  
  82. /*************************************************************/
  83. /* CLASS TimeCardPage - ~TimeCardPage - destructor           */
  84. /*************************************************************/
  85.  
  86. TimeCardPage :: ~TimeCardPage()
  87. {
  88.    ICommandHandler::stopHandlingEventsFor( &pageButtons );
  89.    ICommandHandler::stopHandlingEventsFor( &pageScrollButtons );
  90.    ISelectHandler::stopHandlingEventsFor( &pageButtons );
  91.    delete( pTimeCardData );
  92. };
  93.  
  94.  
  95. /****************************************************************************
  96. * CLASS TimeCardPage :: handleIt()                                          *
  97. ****************************************************************************/
  98. TimeCardPage&  TimeCardPage :: handleIt()
  99. {
  100.    ICommandHandler::handleEventsFor( &pageButtons );
  101.    ICommandHandler::handleEventsFor( &pageScrollButtons );
  102.    ISelectHandler::handleEventsFor( &pageButtons );
  103.    return *this;
  104. }
  105.  
  106. /****************************************************************************
  107. * CLASS TimeCardPage :: setCells() - set up the multi-cell canvas cells     *
  108. ****************************************************************************/
  109. TimeCardPage& TimeCardPage :: setCells()
  110. {
  111.    addToCell(&pageScrollButtons,       2,  1);
  112.  
  113.    addToCell(&tcVp,                    1,  4,  3,  1);
  114.  
  115. #ifdef IC_PM
  116.    addToCell(&pieChart,                4,  4);
  117.    setColumnWidth( 4, 0, true );
  118.    setRowHeight( 4, 0, true );
  119. #endif
  120.  
  121.    addToCell(&totalHoursText,          2,  6);
  122.    addToCell(&totalBillableHoursText,  2,  7);
  123.  
  124.    addToCell(&pageButtons,             2,  8);
  125.  
  126. /*---------------------------------------------------------------------------
  127. | Get the minimum size for the view-window portion of the viewport.         |
  128. | Since the viewport will have a vertical scrollbar, we need to add it's    |
  129. |  width to the view-window's width.                                        |
  130. | Since the timecard's height is too much to fit on the notebook page,      |
  131. |  reduce the height by 1/4.                                                |
  132. | Set the minimum size of the viewport.                                     |
  133. ---------------------------------------------------------------------------*/
  134.    ISize tcVpMinSize( windowWithHandle( tcVp.viewWindow() )->minimumSize() );
  135.    tcVpMinSize += ISize( tcVp.verticalScrollBar()->size().width(), 0 );
  136.    tcVpMinSize.setHeight( tcVpMinSize.height()/4 );
  137.    tcVp.setMinimumSize( tcVpMinSize );
  138.  
  139.    return *this;
  140. };
  141.  
  142. /**************************************************************************/
  143. /* CLASS TimeCardPage :: setDisplayText()                                 */
  144. /**************************************************************************/
  145.  
  146. TimeCardPage& TimeCardPage :: setDisplayText(const char* totHrs,
  147.                                              const char* totBillHrs)
  148. {
  149.    totalHoursText.setText(         STR_TCD_TOTAL_HOURS_TEXT );
  150.    totalBillableHoursText.setText( STR_TCD_TOTAL_BILLABLE_HOURS_TEXT);
  151.  
  152.    totalHoursText.setText( totalHoursText.text() + totHrs);
  153.    totalBillableHoursText.setText( totalBillableHoursText.text() + totBillHrs);
  154.  
  155.    return *this;
  156. };
  157.  
  158.  
  159.  
  160.  
  161. TimeCard :: TimeCard(IWindow* pParent
  162.                    , ProjectPage* pProjPage
  163.                    , TasksPage  * pTasksPage
  164.                    , LTimeCardData  * rLTimeCardData)
  165.           : IMultiCellCanvas(ID_TIMECARD_PAGE,
  166.                                pParent, pParent,
  167.                                IRectangle() )
  168.             ,dateHeader(ID_TIMECARD_DATE_HEADER, this, this)
  169.             ,projectHeader(ID_TIMECARD_PROJECT_HEADER, this, this)
  170.             ,taskHeader(ID_TIMECARD_TASK_HEADER, this, this)
  171.             ,hourHeader(ID_TIMECARD_HOUR_HEADER, this, this)
  172. #ifdef IC_MOTIF
  173.             ,dateHandler( TEST_DATE )
  174. #endif
  175.             ,pProjectPage(pProjPage)
  176.             ,pTasksPage(pTasksPage)
  177.             ,totalHours(0)
  178.             ,totalBillable(0)
  179. {
  180.   dateHeader.setText(IApplication::current().userResourceLibrary()
  181.                      .loadString(STR_TCD_DATE_HEADER));
  182.   projectHeader.setText(IApplication::current().userResourceLibrary()
  183.                      .loadString(STR_TCD_PROJECT_HEADER));
  184.   taskHeader.setText(IApplication::current().userResourceLibrary()
  185.                      .loadString(STR_TCD_TASK_HEADER));
  186.   hourHeader.setText(IApplication::current().userResourceLibrary()
  187.                      .loadString(STR_TCD_HOUR_HEADER));
  188.  
  189.   for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  190.   {
  191. /*---------------------------------------------------------------------------
  192. | Create an entryfield for entering the date.                               |
  193. | Set the character limit.                                                  |
  194. | Since the default minimumSize is too wide,                                |
  195. | - get the minimumSize                                                     |
  196. | - get the current font's average character width                          |
  197. | - multiply the font width by the limit of the entryfield and add a buffer |
  198. |   to avoid the entryfield from scrolling                                  |
  199. | Set the new minimum size.                                                 |
  200. | Auto delete the object when no longer available.                          |
  201. | Create a de the object when no longer available.                          |
  202. ---------------------------------------------------------------------------*/
  203.     date[index] = new IEntryField(ID_TCD_DATE0_EF, this, this,
  204.                                   IRectangle(),
  205.                                   IEntryField::classDefaultStyle |
  206.                                   IControl::tabStop);
  207.     date[index]->setLimit(  DISPLAY_LIMIT_DATE  );
  208.     ISize dateMinSize( date[index]->minimumSize() );
  209.     dateMinSize.setWidth( font().avgCharWidth() * ( DISPLAY_LIMIT_DATE + 2 ) );
  210.     date[index]->setMinimumSize( dateMinSize );
  211.     date[index]->setAutoDeleteObject();
  212.  
  213. /*---------------------------------------------------------------------------
  214. | Create a downdownlist combobox for the project.                           |
  215. | Set the character limit.                                                  |
  216. | Auto delete the object when no longer available.                          |
  217. ---------------------------------------------------------------------------*/
  218.     proj[index] = new IComboBox(ID_TCD_PROJ0_CBX, this, this,
  219.                                IRectangle(),
  220.                                IComboBox::defaultStyle() &
  221.                                ~IComboBox::simpleType     |
  222.                                IComboBox::dropDownListType |
  223.                                IControl::tabStop);
  224.     proj[index]->setLimit(  DISPLAY_LIMIT       );
  225.     proj[index]->setAutoDeleteObject();
  226.  
  227. /*---------------------------------------------------------------------------
  228. | Create a downdownlist combobox for the task.                              |
  229. | Set the character limit.                                                  |
  230. | Auto delete the object when no longer available.                          |
  231. ---------------------------------------------------------------------------*/
  232.     task[index] = new IComboBox(ID_TCD_TASK0_CBX, this, this,
  233.                                IRectangle(),
  234.                                IComboBox::defaultStyle() &
  235.                                ~IComboBox::simpleType     |
  236.                                IComboBox::dropDownListType |
  237.                                IControl::tabStop);
  238.     task[index]->setLimit(  DISPLAY_LIMIT       );
  239.     task[index]->setAutoDeleteObject();
  240.  
  241. /*---------------------------------------------------------------------------
  242. | Create a spinbutton for entering the hours.                               |
  243. | Set the character limit.                                                  |
  244. | Since the default minimumSize is too wide,                                |
  245. | - get the minimumSize                                                     |
  246. | - get the current font's average character width                          |
  247. | - multiply the font width by the limit of the entryfield and add a buffer |
  248. |   to avoid the entryfield from scrolling and for the spinbutton's arrows  |
  249. | Set the new minimum size                                                  |
  250. | Auto delete the object when no longer available.                          |
  251. ---------------------------------------------------------------------------*/
  252.     hours[index] = new INumericSpinButton(ID_TCD_HOURS0_EF, this, this,
  253.                                IRectangle(),
  254.                                INumericSpinButton::defaultStyle() |
  255.                                IControl::tabStop);
  256.     hours[index]->setLimit( DISPLAY_LIMIT_HOURS );
  257.     ISize hoursMinSize( hours[index]->minimumSize() );
  258.     hoursMinSize.setWidth( font().avgCharWidth() * ( DISPLAY_LIMIT_HOURS + 2 + 3 ) );
  259.     hours[index]->setMinimumSize( hoursMinSize );
  260.     hours[index]->setAutoDeleteObject();
  261.   }
  262.  
  263.   fillComboBox();
  264.   fillVp(rLTimeCardData);
  265.   fillHours(rLTimeCardData->employeeNumber());
  266.   handleIt();
  267.   setCells();
  268. };
  269.  
  270.  
  271. /*************************************************************/
  272. /* CLASS TimeCard - ~TimeCardPage - destructor           */
  273. /*************************************************************/
  274.  
  275. TimeCard :: ~TimeCard()
  276. {
  277. };
  278.  
  279. /*************************************************************/
  280. /* CLASS TimeCard - handleIt()                               */
  281. /*************************************************************/
  282.  
  283. TimeCard& TimeCard :: handleIt()
  284. {
  285.  
  286. #ifdef IC_MOTIF
  287.   for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  288.   {
  289.     dateHandler.handleEventsFor( date[index] );
  290.   }
  291. #endif
  292.  
  293.   return *this;
  294. };
  295.  
  296.  
  297. TimeCard& TimeCard :: fillHours(const IString& key)
  298. {
  299.   LTaskData taskD(key);
  300.   int billable = 0;
  301.   int hrs=0;
  302.  
  303.   for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  304.   {
  305.     if (hours[index]->isValid())
  306.       hrs += hours[index]->value();
  307.     if (taskD.isInAndBillable(key, task[index]->text()))
  308.       billable += hours[index]->value();
  309.   }
  310.  
  311.   totalHours = hrs;
  312.   totalBillable = billable;
  313.   return *this;
  314. };
  315.  
  316. /*************************************************************/
  317. /* CLASS TimeCard - fillVp                                   */
  318. /*************************************************************/
  319.  
  320. TimeCard& TimeCard :: fillVp(LTimeCardData * tcp)
  321. {
  322.   for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  323.   {
  324.     date[index]->setText(   tcp->tcard[index].date()          );
  325.     proj[index]->setText(   tcp->tcard[index].projectName()   );
  326.     task[index]->setText(   tcp->tcard[index].taskName()      );
  327.     hours[index]->setValue( tcp->tcard[index].hours().asInt() );
  328.   }
  329.  
  330.   return *this;
  331. };
  332.  
  333.  
  334. /**************************************************************************/
  335. /* CLASS TimeCard :: setCells() - set up the multi-cell canvas cells   */
  336. /**************************************************************************/
  337.  
  338. TimeCard& TimeCard :: setCells()
  339. {
  340.   unsigned short theRow;
  341.  
  342.   addToCell(&dateHeader,     1,  1);
  343.   addToCell(&projectHeader,  3,  1);
  344.   addToCell(&taskHeader,     5,  1);
  345.   addToCell(&hourHeader,     7,  1);
  346.  
  347.   for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  348.   {
  349.      theRow = (index+1) * 2 + 1;
  350.      addToCell(date[index],  1, theRow);
  351.      addToCell(proj[index],  3, theRow);
  352.      addToCell(task[index],  5, theRow);
  353.      addToCell(hours[index], 7, theRow);
  354.   }
  355.  
  356.    return *this;
  357. };
  358.  
  359.  
  360. /**************************************************************************/
  361. /* CLASS TimeCard :: fillListBox() - set up the drop down list boxes  */
  362. /**************************************************************************/
  363.  
  364. TimeCard& TimeCard :: fillComboBox()
  365. {
  366.   // make sure pointers are ok
  367.   IString
  368.     theProj,
  369.     theDesc,
  370.     theMgr,
  371.     theAct,
  372.     theTask,
  373.     theBill;
  374.  
  375.   LProjectData::Rule theRule=LProjectData::na;
  376.   LTaskData::Rule theRuleT=LTaskData::na;
  377.  
  378.   mtComboBoxes();
  379.  
  380.   pProjectPage->setProjectData();
  381.   // get project data and fill up drop down
  382.   if (pProjectPage->projData().setFirst())
  383.  
  384.      while (pProjectPage->projData().getItem(theProj,
  385.                                               theDesc,
  386.                                               theMgr,
  387.                                               theAct,
  388.                                               theRule)) {
  389.        for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  390.        {
  391.          proj[index]->addAsLast(theProj);
  392.        }
  393.          pProjectPage->projData().getNext();
  394.      }
  395.  
  396.  
  397.  
  398.   pTasksPage->setTasksData();
  399.   // get task data and fill up drop down
  400.   if (pTasksPage->getTaskData().setFirst()) {
  401.  
  402.      while (pTasksPage->getTaskData().getItem(theTask,
  403.                                          theDesc,
  404.                                          theBill,
  405.                                          theRuleT))
  406.      {
  407.        for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  408.        {
  409.          task[index]->addAsLast(theTask);
  410.        }
  411.  
  412.          pTasksPage->getTaskData().getNext();
  413.      }
  414.   }
  415.  
  416.    for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  417.    {
  418.      hours[index]->setRange(IRange(0, 24));
  419.    }
  420.  
  421.   return *this;
  422. };
  423.  
  424.  
  425. TimeCard& TimeCard :: mtComboBoxes() {
  426.   for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  427.   {
  428.     proj[index]->removeAll();
  429.     task[index]->removeAll();
  430.   }
  431.   return *this;
  432. };
  433.  
  434. // need to check date is in range
  435.  
  436. IBase :: Boolean TimeCardPage :: verifyAndSave( IString& theString
  437.                                                ,IString& theEntry
  438.                                                ,const IString theName )
  439. {
  440.     int ix;
  441.     long hrs;
  442.  
  443.   // verify the data
  444.  
  445.      if ((theName.length() == 0) && (Key.length() == 0 ))
  446.         return true ;
  447.  
  448.      // take what is in the bag and write it to the database
  449.      // data is ok, now save it.
  450.  
  451.      IString a,b,c,d ;
  452.      int totalHours=0;
  453.  
  454.      // get the data from the ui fields and save in the data area
  455.  
  456.      Boolean incompleteMsg( false );
  457.      unsigned short saveIndex( 0 );
  458.  
  459.      for ( unsigned short index=0; index < ID_TIMECARD_ENTRIES; index++ )
  460.      {
  461.        a = timeCard.date[index]->text();
  462.        b = timeCard.proj[index]->text();
  463.        c = timeCard.task[index]->text();
  464.        hrs = timeCard.hours[index]->value();
  465.  
  466.        pTimeCardData->tcard[index].setDate( "" );
  467.        pTimeCardData->tcard[index].setProjectName( "" );
  468.        pTimeCardData->tcard[index].setTaskName( "" );
  469.        pTimeCardData->tcard[index].setHours( 0 );
  470.  
  471.        if ((0 != a.length() ) &&
  472.            (0 != b.length() ) &&
  473.            (0 != c.length() ))
  474.        {
  475.           d = IString(hrs) ;
  476.           totalHours += hrs ;
  477.  
  478.           pTimeCardData->tcard[saveIndex].setDate(        a);
  479.           pTimeCardData->tcard[saveIndex].setProjectName( b);
  480.           pTimeCardData->tcard[saveIndex].setTaskName(    c);
  481.           pTimeCardData->tcard[saveIndex].setHours(       d);
  482.           saveIndex++;
  483.        }
  484.        else if ( ( !incompleteMsg ) &&
  485.                  ( 0 != a.length() ) ||
  486.                  ( 0 != b.length() ) ||
  487.                  ( 0 != c.length() ) )
  488.        {
  489.          IMessageBox msgBox( this );
  490.          msgBox.show( STR_TIMECARD_NOSAVE
  491.                       ,IMessageBox::warningIcon |
  492.                       IMessageBox::okButton );
  493.          incompleteMsg = true;
  494.          continue;
  495.        }
  496.      } /* endfor */
  497.  
  498.      IString k;
  499.  
  500.     if (theName.length()>0)
  501.        k = theName;
  502.     else
  503.        k = Key ;
  504.  
  505.      // concat the date
  506.      k+= pTimeCardData->theWeek.asString();
  507.  
  508.      pTimeCardData->save(k);
  509.  
  510.      return (true);
  511. };
  512.  
  513.  
  514. IBase::Boolean TimeCardPage :: command(ICommandEvent &cmdEvent)
  515. {
  516.   Boolean rc = false;
  517.   LTimeCardData *pTCD;
  518.   IString badString, badControl;
  519.  
  520.   switch (cmdEvent.commandId()) {       //Get command id
  521.  
  522.     case ID_BUTTON_UNDO:             //Get the original data back
  523.       delete(pTimeCardData);
  524.       pTimeCardData =  new LTimeCardData( Key, weekEndingDate.date() );
  525.       timeCard.fillVp(pTimeCardData);
  526.       timeCard.fillHours(pTimeCardData->employeeNumber());
  527.       pageScrollButtons.setDisplayText(pTimeCardData->theWeek.asString());
  528.       rc = true;
  529.       break;
  530.  
  531.    case   ID_BUTTON_NEXT:
  532.       verifyAndSave( badString, badControl, Key);
  533.       delete(pTimeCardData);
  534.       pTimeCardData =  new LTimeCardData( Key,
  535.                        weekEndingDate.nextDate(WeekEndingDate::next) );
  536.       timeCard.fillVp(pTimeCardData);
  537.       timeCard.fillHours(pTimeCardData->employeeNumber());
  538. #ifdef IC_PM
  539.       pieChart.refreshData( pTimeCardData );
  540.       pieChart.drawPie();
  541. #endif
  542.       pageScrollButtons.setDisplayText(pTimeCardData->theWeek.asString());
  543.       setDisplayText(IString(timeCard.getTotalHours()),
  544.                      IString(timeCard.getTotalBillable()));
  545.       rc = true;
  546.       break;
  547.  
  548.    case   ID_BUTTON_PREV:
  549.       verifyAndSave( badString, badControl, Key);
  550.       delete(pTimeCardData);
  551.       pTimeCardData =  new LTimeCardData( Key,
  552.                        weekEndingDate.nextDate(WeekEndingDate::previous) );
  553.  
  554.       timeCard.fillVp(pTimeCardData);
  555.       timeCard.fillHours(pTimeCardData->employeeNumber());
  556. #ifdef IC_PM
  557.       pieChart.refreshData( pTimeCardData );
  558.       pieChart.drawPie();
  559. #endif
  560.       pageScrollButtons.setDisplayText(pTimeCardData->theWeek.asString());
  561.       setDisplayText(IString(timeCard.getTotalHours()),
  562.                      IString(timeCard.getTotalBillable()));
  563.       rc = true;
  564.       break;
  565.  
  566.     case ID_BUTTON_HELP:
  567.       // Product Information processing
  568.       IHelpWindow::helpWindow( this )->show(
  569.            IResourceId( ID_TIMECARD_PAGE ) );
  570.       rc = true;
  571.  
  572.   } /* end switch */
  573.  
  574.   return rc;
  575. };
  576.  
  577.  
  578. WeekEndingDate :: WeekEndingDate(IDate aDate)
  579. {
  580.    // given a date, set it to friday (it should be so easy!)
  581.    while (aDate.dayOfWeek() != IDate::Friday) {
  582.       aDate+=1;
  583.    }
  584.  
  585.    theDate = aDate;
  586. };
  587.  
  588. WeekEndingDate :: ~WeekEndingDate()
  589. {};
  590.  
  591. const IDate WeekEndingDate :: nextDate(WeekScroll scroll)
  592. {
  593.     (scroll == WeekEndingDate::next) ? theDate += 7 : theDate -= 7;
  594.     return theDate;
  595. };
  596.  
  597.