Section 7.6. A Case Study: A Sophisticated Cash Register


[Page 392]

7.6. A Case Study: A Sophisticated Cash Register

One of the most prevalent types of computer equipment today is the cash register. This machine has evolved considerably from the time when it functioned like an old-fashioned mechanical typewriter, recording the amount of each sale on a strip of paper and keeping a running sum. Today, cash registers are located not only in stores, but also within gasoline pumps and airport kiosks, performing many functions above and beyond printing receipts. The data from customers' purchases can be stored on a central computer and analyzed to determine trends in buying behavior. For example, a grocery store may glean from cash register transactions that customers who purchase potato chips are likely to also purchase soft drinks. This might lead the store to stock soft drinks in the same aisle as snacks. In the retail industry, the location of a cash register is called the "point of sale" (abbreviated as "POS").

The Design of the Program

This case study develops a sophisticated cash register that supports three main features: First, it accepts user input for the quantity, price, and department of a particular article. Second, it calculates the totals including sales tax and stores those data along with the payment method into an array. Finally, the program generates a report on the stored data. Each of these features is a task that is executed by clicking on a button:

  1. Enter the price, quantity, and department of a new article to purchase. Display the article's data.

  2. Display the subtotal, sales tax, and total, and record the purchase and payment method in an array.

  3. Generate a report showing (a) the quantity and sales for each department and (b) the number of receipts and amounts for each payment method.

The User Interface

Two text boxes are used to collect input for quantity and price. Buttons that represent each department are used to record and display this data in an output list box. Each payment type is represented by a button that finalizes the purchase and displays the totals. A report button is enabled after a purchase is finalized and, when pressed, generates the report in the same list box. See Figure 7.7 and Table 7.19.


[Page 393]

Figure 7.7. Sample output after pressing the bottom button.


Table 7.19. Controls that comprise the user interface.

Object

Property

Setting

frmCashRegister

Text

Sophisticated Cash Register

lblQuantity

Text

Quantity:

txtQuantity

lblPrice

Text

Price:

txtPrice

lblDepartment

Text

Department

btnWomens

Text

Womens

btnMens

Text

Mens

btnKids

Text

Kids

btnSportswear

Text

Sportswear

btnHousehold

Text

Household

btnHardware

Text

Hardware

lblMethod

Text

Payment Method

btnVisa

Text

Visa

btnMasterCard

Text

MasterCard

btnCash

Text

Cash

lblCash

Text

Tendered:

txtCash

btnReport

Enabled

False

Text

Display

Department Sales and Receipts Report

lstOutput



[Page 394]

The Data Structures

The cash register inputs, stores, and processes data. These data are organized into related fields that lend themselves to structure data types. The program employs an Article structure that stores the data for each article that is purchased and a Purchase structure that stores all of the articles and the totals on one receipt. An array of Purchase structures is declared as a class-level variable and holds all of the data for the store. Figure 7.8 shows a representation of the way the structures are organized.

Figure 7.8. Structures used in the Sophisticated Cash Register program.


Coding the Program

The top row of Figure 7.9 shows the different events to which the program must respond. Table 7.20 identifies the corresponding event procedures and the general procedures they call. Let's examine each event procedure:

  1. frmCashRegister_Load initializes the first Purchase structure by dimensioning its articles array to an initial upper bound of 5. It is necessary to do this in the Load procedure because arrays cannot be sized within the structure definition block, yet they must be dimensioned before they are accessed.

  2. RingupArticle is called by the event procedures connected to the buttons that represent the department names (Womens, Mens, Kids, etc.). It takes as its parameter the number of the department that was clicked. The procedure stores the department, quantity, and price of the article into a new Article structure. If the quantity and price are valid (that is, they are greater than zero), then the new article is stored into the array that is a member of the current Purchase structure. If that array does not have room to accommodate the new article, the array is enlarged using a ReDim Preserve statement. Finally, the procedure calls the Display-Article procedure and resets the quantity to 1 for the next article.


    [Page 395]

    Figure 7.9. Hierarchy chart for Sophisticated Cash Register program.
    (This item is displayed on page 394 in the print version)

    Table 7.20. Tasks and their procedures.

    1.

    Initialize First Purchase

    frmCashRegister_Load

    2.

    Store and Display Article

    RingupArticle

     

    2.1 Store Article

    RingupArticle

     

    2.2 Display Article

    DisplayArticle

    3.

    Store and Display Purchase

    TotalPurchase

     

    3.1 Calculate Totals

    TotalPurchase

     

    3.2 Store Purchase

    TotalPurchase

     

    3.3 Display Purchase

    DisplayTotals

     

    3.4 Initialize Next Purchase

    TotalPurchase

    4.

    Analyze Data

    btnReport_Click

     

    4.1 Aggregate Data

    btnReport_Click

     

    4.2 Total and Display Department Statistics

    btnReport_Click

     

    4.2 Total and Display Payment Method Statistics

    btnReport_Click


    The DisplayArticle procedure displays the quantity, department, price, and total (that is, quantity times price) for an article in the output list box. A heading is displayed along with the first purchase on the receipt. The department names are stored in a string array called department() that is declared as a class-level variable. The procedure displays the article's department name by using its department number as the subscript in the department() array.

  3. TotalPurchase is called by the event procedures that are connected to the buttons representing the methods of payment (Visa, MasterCard, Cash). It takes as its parameter the number of the payment method that was clicked. The procedure first checks to see if any articles have been stored. If not, a message box is displayed. Otherwise, the articles are totaled, and sales tax is applied to calculate the purchase's subtotal and total. If the payment method is Cash, the procedure verifies that the amount tendered by the customer is at least the total amount. If it isn't, a message box is displayed. Otherwise, the purchase is stored, the DisplayTotals procedure is called, and the articles array in the next purchase structure is ReDimmed to the default upper bound of 4.

    The technique used to store a purchase requires elaboration. The class-level array purchases() is declared in the class with an initial upper bound of 30. The integer counter count keeps track of the number of stored purchases and is initialized to the default value of zero. New articles are stored in the purchases() element with subscript count. When a payment method is clicked, the purchase is finalized. The action that does this is the line count + =1, which increments the counter by one. Therefore, the new purchase is stored in the purchases() array all along, but it is only recognized as "stored" when its index is less than the counter.


    [Page 396]

    The DisplayTotals procedure displays the subtotal, applicable sales tax, and total for the purchase. It also displays the payment method in the following manner: If the payment method is Cash (method #3), it displays the cash tendered and the change due. Otherwise it displays the type of credit card used.

  4. btnReport_Click aggregates the data in the purchases() array and displays the resulting analysis. It first declares the arrays and variables that are used for the results. It then loops through all of the articles for each purchase (using a nested loop) to aggregate each article into a department result and a payment method result. It uses the department and payment method numbers as subscripts for the result arrays, the four arrays declared at the top of the procedure. The department statistics are totaled and displayed, then the payment method statistics are totaled and displayed.P

'Define the Purchase and Article structures Structure Article Dim department As Integer  'Department number, see department() below Dim quantity As Integer    'Quantity of articles purchased Dim price As Double        'Price of each article End Structure Structure Purchase  Dim articles() As Article   'Articles purchased Dim articleCount As Integer 'Number of articles purchased Dim subtotal As Double      'Subtotal of articles' prices times quantities Dim total As Double 'Total of purchase including tax Dim method As Integer       'Method of payment, see method() below End Structure 'Declare the class-level variables Dim  purchases(30) As Purchase 'Array that holds all purchases Dim count As Integer          'Number of completed purchases Dim  taxRate As Double = 0.05  '5% sales tax Dim  department() As String = { " Womens ",   " Mens ",   " Kids ",  _      " Sportswear ",   " Household ",   " Hardware "} Dim  method() As String = { " Visa ",   " MasterCard ",   " Cash "} Private Sub frmCashRegister_Load(...) Handles MyBase.Load 'Initialize the first purchase ReDim purchases(0).articles(4) End Sub Sub RingupArticle(ByVal dept As Integer)  'Store the user's input into a new article Dim newArticle As Article      'New article to hold user input Dim size As Integer              'Size of the articles array   With newArticle     .department = dept     .quantity = CInt(txtQuantity.Text) 
[Page 397]
'If blank price then use default of 0 If txtPrice.Text = "" Then .price = 0 Else .price = CDbl(txtPrice.Text) End If End With 'If price and quantity are valid, then store and display article If (newArticle.quantity > 0) And (newArticle.price > 0) Then 'Increment the number of articles in the current purchase purchases(count).articleCount += 1 'Ensure the Purchase's articles array has room for the new article size = purchases(count).articles.GetUpperBound(0) If purchases(count).articleCount >= size Then 'If not enough room, increase the array size by 5 ReDim Preserve purchases(count).articles(size + 5) End If 'Store the new article into the purchase purchases(count).articles(purchases(count).articleCount - 1) = _ newArticle 'Display the article in the receipt DisplayArticle() 'Clear the quantity and price for the next article txtQuantity.Clear() txtPrice.Clear() End If 'Disable the report button until the article is paid for btnReport.Enabled = False txtQuantity.Focus() 'Focus on the quantity for the next article End Sub Private Sub btnWomens_Click(...) Handles btnWomens.Click RingupArticle(0) End Sub Private Sub btnMens_Click(...) Handles btnMens.Click RingupArticle(1) End Sub Private Sub btnKids_Click(...) Handles btnKids.Click RingupArticle(2) End Sub Private Sub btnSportswear_Click(...) Handles btnSportswear.Click RingupArticle(3) End Sub Private Sub btnHousehold_Click(...) Handles btnHousehold.Click RingupArticle(4) End Sub
[Page 398]
Private Sub btnHardware_Click(...) Handles btnHardware.Click RingupArticle(5) End Sub Sub DisplayArticle() Dim cost As Double Dim fmtStr As String = " {0,3} {1,-12} {2,7:C} {3,7:C} " 'If article is the first, clear the display and display the header If purchases(count).articleCount = 1 Then lstOutput.Items.Clear() lstOutput.Items.Add(" Customer Receipt ") lstOutput.Items.Add("") lstOutput.Items.Add(String.Format(fmtStr, " Qty " , " Dept ", _ " Price " , " Total ")) lstOutput.Items.Add(String.Format(fmtStr, " --- " , " ------------ " , _ " ------- " , " ------- ")) End If 'Display the article's information With purchases(count).articles(purchases(count).articleCount - 1) cost = .quantity * .price lstOutput.Items.Add(String.Format(fmtStr, .quantity, _ department(.department), .price, cost)) End With End Sub Sub TotalPurchase(ByVal meth As Integer) Dim cash As Double 'Amount of cash tendered Dim flag As Boolean = True 'If purchase is valid With purchases(count) 'If no articles purchased then display message and exit If .articleCount < 1 Then MsgBox( " No articles purchased. " , 0, " No sale ") txtQuantity.Focus() flag = False End If 'Calculate and store totals .subtotal = 0 For i As Integer = 0 To .articleCount - 1 .subtotal += .articles(i).price * .articles(i).quantity Next 'Add sales tax to get total .total = (1 + taxRate) * .subtotal 'Store the method of payment .method = meth 'If cash method, then get the amount tendered by customer If .method = 2 Then If txtCash.Text = "" Then cash = 0
[Page 399]
Else cash = CDbl(txtCash.Text) End If 'If tendered amount is not enough, then display message If (cash < .total) Then MsgBox( " Not enough cash tendered (need " & _ FormatCurrency(.total) & " ) " , 0, "Insufficient Cash") txtCash.Focus() 'Focus on cash for reinput flag = False End If End If End With 'If purchase is valid, then store and display it If flag Then 'Increment the counter so the latest purchase is considered stored count += 1 'Display purchase totals DisplayTotals() 'Make sure there is room for the next purchase and initialize it If purchases.GetUpperBound(0) <= count Then ReDim purchases(count + 5) End If ReDim purchases(count).articles(4) End If 'Enable the report button btnReport.Enabled = True End Sub Sub DisplayTotals() 'Display subtotal, tax, and total Dim prompt As String = "Tax: ( " & FormatPercent(taxRate) & " ) " Dim cash As Double Dim fmtStr As String = "{0,3} {1,-12} {2,7} {3,7:C} " With purchases(count - 1) lstOutput.Items.Add(String.Format(fmtStr, "", "", "", " ------- ")) lstOutput.Items.Add(String.Format(fmtStr, "", " Sub Total: ", "", _ .subtotal)) lstOutput.Items.Add(String.Format(fmtStr, "" , prompt, "" , _ .total - .subtotal)) lstOutput.Items.Add(String.Format(fmtStr, "", "", "", " ------- ")) lstOutput.Items.Add(String.Format(fmtStr, "", " Total: ", "", .total)) 'If cash purchase, then display amount tendered and change If .method = 2 Then cash = CDbl(txtCash.Text) lstOutput.Items.Add( "") lstOutput.Items.Add(String.Format(fmtStr, "", "Cash:", "" , cash)) lstOutput.Items.Add(String.Format(fmtStr, "", " Change: ", "" , _ cash - .total))
[Page 400]
Else 'If not cash, mention how tendered lstOutput.Items.Add( " Charged to " & method(.method)) End If End With 'Clear the cash, and set focus to quantity for the next purchase txtCash.Clear() txtQuantity.Focus() End Sub Private Sub btnVisa_Click(...) Handles btnVisa.Click TotalPurchase(0) End Sub Private Sub btnMasterCard_Click(...) Handles btnMasterCard.Click TotalPurchase(1) End Sub Private Sub btnCash_Click(...) Handles btnCash.Click TotalPurchase(2) End Sub Private Sub btnReport_Click(...) Handles btnReport.Click Dim deptQuant(5), deptQuantT As Integer 'Quantity per department Dim deptSales(5), deptSalesT As Double 'Sales per department Dim methQuant(2), methQuantT As Integer 'Quantity per method Dim methAmnt(2), methAmntT As Double 'Sales per method Dim liability As Double 'Amount of tax liability Dim fmtStr1 As String = "{0,-15} {1,6} {2,9:C}" Dim fmtStr2 As String = "{0,-15} {1,6:P} {2,9:C}" 'Sum quantity and total amounts per department, without tax For i As Integer = 0 To count - 1 'Sum quantity and total amounts per payment method methQuant(purchases(i).method) += 1 methAmnt(purchases(i).method) += purchases(i).total For j As Integer = 0 To purchases(i).articleCount - 1 With purchases(i).articles(j) deptQuant(.department) += .quantity deptSales(.department) += .price * .quantity End With Next Next 'Display the quantity and sales per department lstOutput.Items.Clear() lstOutput.Items.Add(" Sales Report ") lstOutput.Items.Add("") lstOutput.Items.Add(String.Format(fmtStr1, "Department", "Qty" , _ " Sales ")) lstOutput.Items.Add(String.Format(fmtStr1, " ----------- ", " --- " , _ " --------- "))
[Page 401]
For i As Integer = 0 To 5 lstOutput.Items.Add(String.Format(fmtStr1, department(i), _ deptQuant(i), deptSales(i))) deptQuantT += deptQuant(i) deptSalesT += deptSales(i) Next lstOutput.Items.Add(String.Format(fmtStr1, " ----------- " , " --- " , _ " -------- ")) lstOutput.Items.Add(String.Format(fmtStr1, " Grand Total " , _ deptQuantT, deptSalesT)) 'Display the quantity and sales per payment method lstOutput.Items.Add( "") lstOutput.Items.Add(String.Format(fmtStr1, " Payment ", " Qty " , _ " Amount ")) lstOutput.Items.Add(String.Format(fmtStr1, " ----------- ", " --- " , _ " -------- ")) For i As Integer = 0 To 2 lstOutput.Items.Add(String.Format(fmtStr1, method(i), _ methQuant(i), methAmnt(i))) methQuantT += methQuant(i) methAmntT += methAmnt(i) Next 'Calculate the total amount of sales tax liability = methAmntT - deptSalesT lstOutput.Items.Add(String.Format(fmtStr1, " ----------- ", " --- ", _ " -------- ")) lstOutput.Items.Add(String.Format(fmtStr1, "Gross Receipts:" , _ methQuantT, methAmntT)) lstOutput.Items.Add(String.Format(fmtStr2, "Tax Liability:" , _ taxRate, liability)) lstOutput.Items.Add(String.Format(fmtStr1, "Net Receipts:" , "", _ deptSalesT)) txtQuantity.Focus() 'Focus on quantity for next article End Sub





An Introduction to Programming Using Visual Basic 2005
Introduction to Programming Using Visual Basic 2005, An (6th Edition)
ISBN: 0130306541
EAN: 2147483647
Year: 2006
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net