Notes for week 6

For this week's links click here .

Dynamic Scenarios

Introduction

You are used to creating scenarios for static situations such as creating functions for menu handlers. The program you started in week 4 started out as this type of problem, but if you look at the rental window you developed last week, the sequence of events when the user is processing a rental is not clear from the interface. To clearify the sequence of events for each of the processes, you will create a dynamic scenario. Before creating the standard scenario, write a script of what will occur during renting. Make sure to indicate things that should not be possible. This will not only give you an idea of how to write your functions, it will help find weaknesses in your interface.

Script for the Rental Form

Here is a first attempt at a script for processing a rental. Notes in red indicate restrictions on the interface discovered from the script.

When you begin a new rental, the confirm rental button should not be enabled
  1. Ask for the user id.
    1. if the user has an id enter it
    2. if not leave the id blank
  2. In either case press the check customer button
  3. After returning from the customer window you should have a legal number and the customer data should be legal.
    This will not be enough to activate the confirm rental button, but you must send a message from the customer window that confirms that the information is correct.
  4. The next order of business is to obtain the type of rental.
    To control the order, you can enable items only when prerequisites have been met. You could disable all features other than the Customer Id, Check Customer and Cancel until the Customer Id is confirmed. Then enable only the rental type.
  5. Once the rental type is chosen, active length of stay and either condo number or slip length.
    You should provide a list of available condos, if the this is a condo rental.

Some New Ideas

At this point you should have noticed that if the rental window is on the screen, you add a rental without calling the add rental menu item. You may be able to delete the Rental menu entirely. This may lead to a redesign of the main window. Maybe a small window with two buttons (one for the rental window and the other for the customer window) might be inorder.

Did you miss anything in this script? It is hard to tell by just looking at the script if anything is missing. One thing that is not obvious here is does the customer have a choice of prices? Prices should be included in the list of available condos. What if the same person wants to rent more than one item. You might want to freeze (disable) the id once it has been confirmed and add a Order Complete button that is pressed when the customer is done. This button would return both windows to their original state. While you're at it you might want to add a clear button to both windows to return them to their original state. The handler for this button can be called whenever you need to reset a window. You may also want to add a timer that pops up a dialog if the user fails to hit the Order Complete button after a given length of time.

Check Your Script

Before committing too much energy to the final user interface and scenarios, you should check your script with the client. If there is more than one user, you may want to talk to each to see if the scripts are realistic. It might be even better if before you write your script you observe the current system in action.

First Scenario

In this section you will use an abbreviated version of the scenario to trace the actions sketched above.

Script for the Customer Form

Write a script that you think would be the sequence of events when filling out the customer form. Next create a scenario like the one above for the customer form. Notice that some of the items already appear in the scenario for the rental, but others are new since they involve checking new customers and double checking information. Some discussion of this and SQL is given in the page you get by clicking here . The rest is put off until week 7.

One thing the might come up when reviewing a script for taking customer information is the need to double check the information. While there is no way to ensure that the user will double check each piece of information, you can remind the user and make it difficult not to double check by putting checkboxes in front of each item. Then require all be checked before adding the user. This is important even when the user is a repeat customer since vital information may have changed since the last time the customer rented. If you have decided to use the zip code and last name for seaching, you will want both of these items at the top of the form. This is the new version of the customer form. Note that the hint for for the find button indicates that the user must have the last name and zip code entered. The hint for add customer is that you must have check boxes filled.

Communicating Between The Windows

How will you communicate the confirmation of customer information in the rental window? One thing you can do is create a bool variable in the Rental window and set it to false when a new rental begins. You will need to create a function to set the variable and then the customer window confirm button handler can set the confirmation. You need only have a function, confirmed, since the only setting you would allow from outside is true (the customer information is confirmed. Both forms were created as subforms of the MainForm, so comunications are direct. The call to the customer window from the rental window illustrates the proper calls in this case.

  //This call is from the CustomerForm to the RentalForm
   void __fastcall  TCustomerForm1::ConfirmBtnClick(TObject *Sender)
{
     MainForm->RentalForm()->confirmed();
}
 //---------------------------------------------------------------------------
//This call is from the RentalForm to the CustomerForm
  

 void __fastcall  TRentalForm::CheckCustomerClick(TObject *Sender)
{
   MainForm->CustomerForm()->CustomerId->Text = CustomerId->Text;
   MainForm->ShowCustomer1Click(Sender);
}
 //---------------------------------------------------------------------------
  

In the RentalForm the Confirm Rental button cannot be pressed unless all of the appropriate entries are filled in and the customer is confirmed. When the function confirmed is called from the customer form, this might be the last thing that is needed to enable the Confirm Rental button, so the button enabler is called from confirmed. These functions are given below.

 
  
void  confirmed() {_custConfirmed =  true ; enableComplete();}

 //---------------------------------------------------------------------------
  
 void __fastcall  TRentalForm::enableComplete()
{
   Confirm->Enabled = _custConfirmed && CustomerId->Text != "" 
                     && StayLength->Text != "" 
                     &&( (CondoRental->Checked && CondoNumber->Text != "" )
                        || (BoatSlip->Checked && BoatLength->Text !=  "" ));
}
 //---------------------------------------------------------------------------
  

One function is used to check to see if any of the components has been changed. This function is created for one of the fields (say CustomerId) and then chosen as the OnChange handler for the rest of the components. Numerical components have the usual filter put on the OnKeyClicked event.

Most of the OnChange handlers for TEdit and TEditMask components simply set the corresponding checkboxes Enable property true if there is something in the box. The state change must also check to see if this is a legal state abbreviation by searching the list of abbreviations. If the typed text is not in the abbreviation list, a messagebox indicate this. The checkbox is not enabled until a legal abbreviation is entered or selected.

void __fastcall  TCustomerForm1::StateChange(TObject *Sender)
{
   State->Text = State->Text.UpperCase();  // All abreviations upper case
  
   StateCheckBox->Checked =  false ; // change causes check to disappear  
   if  (State->Text.Length() == 2)
   {
       int index = State->Items->IndexOf(State->Text);  //See if the current text is a state  
       if  (index >=0)  //if it is set the ItemIndex  
         State->ItemIndex = index;
       else
         State->Text = String(State->Text[1]);   // Otherwise delete last letter  
   }
   else if  (State->Text.Length() > 2)  //too many letters  
   {
     State->Text = State->Text.SubString(0,2);  //delete the last one and see if you have a state  
     int index = State->Items->IndexOf(State->Text);
     if  (index >=0)
         State->ItemIndex = index;
     else          
         State->ItemIndex = -1; // otherwise not ok
   }
   StateCheckBox->Enabled = State->ItemIndex >=0;  // Have you got a state  
   State->SelStart = State->Text.Length();  // Make sure cusor is at the end of the line.  
   _modified =  true ;
}