College Park Auto Repair

Introduction

As always mentioned, XML provides the ability to store information as regular text so that the same information can be accessed from completely independent applications. This provides tremendous opportunities in the areas of storage and sharing of data. To make it even more useful, the .NET Framework provides full support for the Document Object Model (DOM) of XML through various classes.

In this exercise, we are going to create an application used by a car repair business. To use it, an employee of the business can open a form to process a customer's work order. During this, the employee can enter the customer, the information about the car to be fixed, and a text description of the problem.

Practical Learning: Starting the Exercise

  1. Start Microsoft Visual C++ .NET and create a new Windows Forms Application named CPAS2
  2. To add another form, on the main menu, click Project -> Add New Item...
  3. In the Templates list, click Windows Form (.NET)
  4. Set the Name to InfoCenter and click Open
  5. To create a data set, in the Toolbox, click the Data button, then click DataSet, and click the form
  6. In the Add Dataset dialog box, click the Untyped dataset radio button
     
    Add Dataset
  7. Click OK
  8. While the new dataSet1 button is selected, in the Properties window, set its (Name) to dsWorkorders and set its DataSetName to Workorders
  9. To create the necessary structure of a work order, while the DataSet object is still selected, in the Properties window, click Tables and click its ellipsis button
  10. In the Tables Collection Editor, click Add
  11. Set the (Name) to tblWorkorder and set the TableName to Workorder
  12. Set its Modifiers to Public
  13. To create the columns, in the Workorder Properties section, click Columns and click its ellipsis button
  14. In the Columns Collection Editor, click Add
  15. Set the properties as follows:
    (Name): colCustomerName
    ColumnName: CustomerName
    Modifiers: Public
  16. In the same way, create the other columns as follows:
     
    (Name) ColumnName DataType Modifiers
    colCustomerName CustomerName System.String Public
    colAddress Address System.String Public
    colCity City System.String Public
    colState State System.String Public
    colZIPCode ZIPCode System.String Public
    colMake Make System.String Public
    colModel Model System.String Public
    colCarYear CarYear System.String Public
    colProblem Problem System.String Public
    colPartName1 PartName1 System.String Public
    colUnitPrice1 UnitPrice1 System.Double Public
    colQuantity1 Quantity1 System.Int16 Public
    colSubTotal1 SubTotal1 System.Double Public
    colPartName2 PartName2 System.String Public
    colUnitPrice2 UnitPrice2 System.Double Public
    colQuantity2 Quantity2 System.Int16 Public
    colSubTotal2 SubTotal2 System.Double Public
    colPartName3 PartName3 System.String Public
    colUnitPrice3 UnitPrice3 System.Double Public
    colQuantity3 Quantity3 System.Int16 Public
    colSubTotal3 SubTotal3 System.Double Public
    colPartName4 PartName4 System.String Public
    colUnitPrice4 UnitPrice4 System.Double Public
    colQuantity4 Quantity4 System.Int16 Public
    colSubTotal4 SubTotal4 System.Double Public
    colPartName5 PartName5 System.String Public
    colUnitPrice5 UnitPrice5 System.Double Public
    colQuantity5 Quantity5 System.Int16 Public
    colSubTotal5 SubTotal5 System.Double Public
    colJobPerformed1 JobPerformed1 System.String Public
    colJobPrice1 JobPrice1 System.Double Public
    colJobPerformed2 JobPerformed2 System.String Public
    colJobPrice2 JobPrice2 System.Double Public
    colJobPerformed3 JobPerformed3 System.String Public
    colJobPrice3 JobPrice3 System.Double Public
    colJobPerformed4 JobPerformed4 System.String Public
    colJobPrice4 JobPrice4 System.Double Public
    colJobPerformed5 JobPerformed5 System.String Public
    colJobPrice5 JobPrice5 System.Double Public
    colTotalParts TotalParts System.Double Public
    colTotalLabor TotalLabor System.Double Public
    colTaxRate TaxRate System.Double Public
    colTaxAmount TaxAmount System.Double Public
    colTotalOrder TotalOrder System.Double Public
    colRecommendations Recommendations System.Double Public
  17. Click Close twice
  18. To add another form, on the main menu, click Project -> Add New Item...
  19. In the Templates list, click Windows Form (.NET)
  20. Set the Name to NewWorkorder and click Open
  21. Design the form as follows:
     
    Control Name Text Other Properties
    GroupBox   Customer and Car Information  
    Label   Customer Name:  
    TextBox txtCustomerName    
    Label   Address  
    TextBox txtAddress    
    Label   City:  
    TextBox txtCity    
    Label   State:  
    TextBox txtState    
    Label   ZIP Code:  
    TextBox txtZIPCode   TextAlign: Right
    Label   Make / Model:  
    TextBox txtMake    
    TextBox txtModel    
    Label   Year:  
    TextBox txtCarYear   TextAlign: Right
    Label   Problem Description:  
    TextBox txtProblem    
    GroupBox   Parts Used  
    Label   Part Name  
    Label   Unit Price  
    Label   Qty  
    Label   Sub Total  
    TextBox txtPartName1    
    TextBox txtUnitPrice1 0.00 TextAlign: Right
    TextBox txtQuantity1 0 TextAlign: Right
    TextBox txtSubTotal1 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName2    
    TextBox txtUnitPrice2 0.00 TextAlign: Right
    TextBox txtQuantity2 0 TextAlign: Right
    TextBox txtSubTotal2 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName3    
    TextBox txtUnitPrice3 0.00 TextAlign: Right
    TextBox txtQuantity3 0 TextAlign: Right
    TextBox txtSubTotal3 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName4    
    TextBox txtUnitPrice4 0.00 TextAlign: Right
    TextBox txtQuantity4 0 TextAlign: Right
    TextBox txtSubTotal4 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName5    
    TextBox txtUnitPrice5 0.00 TextAlign: Right
    TextBox txtQuantity5 0 TextAlign: Right
    TextBox txtSubTotal5 0.00 TextAlign: Right
    Enabled: False
    GroupBox   Jobs Performed  
    Label   Price  
    TextBox txtJobPerformed1    
    TextBox txtJobPrice1 0.00 TextAlign: Right
    TextBox txtJobPerformed2    
    TextBox txtJobPrice2 0.00 TextAlign: Right
    TextBox txtJobPerformed3    
    TextBox txtJobPrice3 0.00 TextAlign: Right
    TextBox txtJobPerformed4    
    TextBox txtJobPrice4 0.00 TextAlign: Right
    TextBox txtJobPerformed5    
    TextBox txtJobPrice5 0.00 TextAlign: Right
    GroupBox   Recommendations to Customer  
    TextBox txtRecommendations   Multiline: True
    ScrollBars: Vertical
    GroupBox   Order Summary  
    Button btnCalculateOrder Calculate Order  
    Label   Total Parts:  
    TextBox txtTotalParts 0.00 TextAlign: Right
    Label   Total Labor:  
    TextBox txtTotalLabor 0.00 TextAlign: Right
    Label   Tax Rate:  
    TextBox txtTaxRate 7.75 TextAlign: Right
    Label   %  
    Label   Tax Amount:  
    TextBox txtTaxAmount 0.00 TextAlign: Right
    Label   Total Order:  
    TextBox txtTotalOrder 0.00 TextAlign: Right
    Label   Order Date:  
    DateTimePicker dtpOrderDate   Format: Custom
    CustomFormat: ddd dd MMM yyyy
    Button btnSaveOrder Save this Order in the Above Date and Start New One  
    Button btnResetOrder Reset Order  
    Button btnPreview Print Preview  
    Button btnClose Close  
    Form     CancelButton: btnClose
  22. Save all
  23. Press Ctrl + A to select everything
  24. Press Ctrl + C to copy everything
  25. To add another form, on the main menu, click Project -> Add New Item...
  26. In the Templates list, click Windows Form (.NET)
  27. Set the Name to Workorders and click Open
  28. Enlarge the form as much as possible, then right-click it and click Paste
  29. Adjust the design of the form as follows:
     
    Control Name Text Other Properties
    GroupBox   Customer and Car Information  
    Label   Customer Name:  
    TextBox txtCustomerName    
    Label   Address  
    TextBox txtAddress    
    Label   City:  
    TextBox txtCity    
    Label   State:  
    TextBox txtState    
    Label   ZIP Code:  
    TextBox txtZIPCode   TextAlign: Right
    Label   Make / Model:  
    TextBox txtMake    
    TextBox txtModel    
    Label   Year:  
    TextBox txtCarYear   TextAlign: Right
    Label   Problem Description:  
    TextBox txtProblem    
    GroupBox   Parts Used  
    Label   Part Name  
    Label   Unit Price  
    Label   Qty  
    Label   Sub Total  
    TextBox txtPartName1    
    TextBox txtUnitPrice1 0.00 TextAlign: Right
    TextBox txtQuantity1 0 TextAlign: Right
    TextBox txtSubTotal1 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName2    
    TextBox txtUnitPrice2 0.00 TextAlign: Right
    TextBox txtQuantity2 0 TextAlign: Right
    TextBox txtSubTotal2 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName3    
    TextBox txtUnitPrice3 0.00 TextAlign: Right
    TextBox txtQuantity3 0 TextAlign: Right
    TextBox txtSubTotal3 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName4    
    TextBox txtUnitPrice4 0.00 TextAlign: Right
    TextBox txtQuantity4 0 TextAlign: Right
    TextBox txtSubTotal4 0.00 TextAlign: Right
    Enabled: False
    TextBox txtPartName5    
    TextBox txtUnitPrice5 0.00 TextAlign: Right
    TextBox txtQuantity5 0 TextAlign: Right
    TextBox txtSubTotal5 0.00 TextAlign: Right
    Enabled: False
    GroupBox   Jobs Performed  
    Label   Price  
    TextBox txtJobPerformed1    
    TextBox txtJobPrice1 0.00 TextAlign: Right
    TextBox txtJobPerformed2    
    TextBox txtJobPrice2 0.00 TextAlign: Right
    TextBox txtJobPerformed3    
    TextBox txtJobPrice3 0.00 TextAlign: Right
    TextBox txtJobPerformed4    
    TextBox txtJobPrice4 0.00 TextAlign: Right
    TextBox txtJobPerformed5    
    TextBox txtJobPrice5 0.00 TextAlign: Right
    GroupBox   Recommendations to Customer  
    TextBox txtRecommendations   Multiline: True
    ScrollBars: Vertical
    GroupBox   Order Summary  
    Label   Order Date:  
    DateTimePicker dtpOrderDate   Format: Custom
    CustomFormat: ddd dd MMM yyyy
    Button btnOpen Display Orders  
    Label   Total Parts:  
    TextBox txtTotalParts 0.00 TextAlign: Right
    Label   Total Labor:  
    TextBox txtTotalLabor 0.00 TextAlign: Right
    Label   Tax Rate:  
    TextBox txtTaxRate 7.75 TextAlign: Right
    Label   %  
    Label   Tax Amount:  
    TextBox txtTaxAmount 0.00 TextAlign: Right
    Label   Total Order:  
    TextBox txtTotalOrder 0.00 TextAlign: Right
    Button btnFirst First  
    Button btnNext Next  
    Button btnPrevious Previous  
    Button btnLast Last  
    Button btnPreview Print Preview  
    Button btnClose Close  
    Form     CancelButton: btnClose
  30. Save all
  31. Display the first or main form (Form1.h [Design]) and design it as follows:
     
    Control Name Text
    Button btnNewOrder Create New Workorder
    Button btnOpenOrders Open Previous Workorders
    Button btnClose Close
  32. Double-click the Create New Workorder button
  33. Return to the form and double-click the Open Previous Workorders button
  34. Return to the form and double-click the Close button
  35. Implement the Click events as follows:
     
    #pragma once
    
    #include "NewWorkorder.h"
    #include "Workorders.h"
    
    namespace CPAS2
    {
    	. . . No Change 
    	
    		
    private: System::Void btnNewOrder_Click(System::Object *  sender, 
    			System::EventArgs *  e)
    {
    	 NewWorkorder *frmOrder = new NewWorkorder();
    	 frmOrder->ShowDialog();
    }
    
    private: System::Void btnOpenOrders_Click(System::Object *  sender, 
    			System::EventArgs *  e)
    {
    	 Workorders *frmOrders = new Workorders();
    	 frmOrders->ShowDialog();
    }
    
    private: System::Void btnClose_Click(System::Object *  sender, 
    			System::EventArgs *  e)
    {
    	 Close();
    }
    
    };
    }
  36. Execute the application to test it
 
 

Calculating the Order

When a car has been fixed, an employee can complete the form with what was done. A section of the form allows the employee to enter the names, prices, and quantities of parts that were used to fix the car. Each part is entered but its name, a unit price, and a quantity; then, a sub total of each part must be calculated.

Besides the parts used, the employee must also list the types of repairs that were performed and their costs. This also allows the customer to know what was done.

Once the parts information and the jobs performed have been entered, the order can be calculated to know the total the customer will pay.

Practical Learning: Starting the Exercise

  1. Double-click the Reset Order button and implement its Click event as follows:
     
    System::Void btnResetOrder_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 this->txtCustomerName->Text = S"";
    	 this->txtAddress->Text = S"";
    	 this->txtCity->Text = S"";
    	 this->txtState->Text = S"";
    	 this->txtZIPCode->Text = S"";
    	 this->txtMake->Text = S"";
    	 this->txtModel->Text = S"";
    	 this->txtCarYear->Text = S"";
    	 this->txtProblem->Text = S"";
    
    	 this->txtPartName1->Text = S"";
    	 this->txtUnitPrice1->Text = S"0.00";
    	 this->txtQuantity1->Text  = S"0";
    	 this->txtSubTotal1->Text  = S"0.00";
    	 this->txtPartName2->Text = S"";
    	 this->txtUnitPrice2->Text = S"0.00";
    	 this->txtQuantity2->Text  = S"0";
    	 this->txtSubTotal2->Text  = S"0.00";
    	 this->txtPartName3->Text = S"";
    	 this->txtUnitPrice3->Text = S"0.00";
    	 this->txtQuantity3->Text  = S"0";
    	 this->txtSubTotal3->Text  = S"0.00";
    	 this->txtPartName4->Text = S"";
    	 this->txtUnitPrice4->Text = S"0.00";
    	 this->txtQuantity4->Text  = S"0";
    	 this->txtSubTotal4->Text  = S"0.00";
    	 this->txtPartName5->Text = S"";
    	 this->txtUnitPrice5->Text = S"0.00";
    	 this->txtQuantity5->Text  = S"0";
    	 this->txtSubTotal5->Text  = S"0.00";
    
    	 this->txtJobPerformed1->Text = S"";
    	 this->txtJobPrice1->Text = S"0.00";
    	 this->txtJobPerformed2->Text = S"";
    	 this->txtJobPrice2->Text = S"0.00";
    	 this->txtJobPerformed3->Text = S"";
    	 this->txtJobPrice3->Text = S"0.00";
    	 this->txtJobPerformed4->Text = S"";
    	 this->txtJobPrice4->Text = S"0.00";
    	 this->txtJobPerformed5->Text = S"";
    	 this->txtJobPrice5->Text = S"0.00";
    
    	 this->txtTotalParts->Text = S"0.00";
    	 this->txtTotalLabor->Text = S"0.00";
    	 this->txtTaxRate->Text    = S"7.75";
    	 this->txtTaxAmount->Text  = S"0.00";
    	 this->txtTotalOrder->Text = S"0.00";
    
    	 this->txtRecommendations->Text = S"";
    	 this->txtCustomerName->Focus();
    }
  2. Double-click the Calculate Order button and implement its Click event as follows:
      
    System::Void btnCalculateOrder_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 double part1UnitPrice, part1SubTotal, part2UnitPrice, part2SubTotal,
    		    part3UnitPrice, part3SubTotal, part4UnitPrice, part4SubTotal,
    		part5UnitPrice, part5SubTotal, totalParts;
    	 int    part1Quantity = 0, part2Quantity = 0, part3Quantity = 0,
    		    part4Quantity = 0, part5Quantity = 0;
    	 double job1Price = 0.00, job2Price = 0.00, job3Price = 0.00,
    		    job4Price = 0.00, job5Price = 0.00;
    	 double totalLabor;
    	 double taxRate, taxAmount, totalOrder;
    
    	 // Don't charge a part unless it is clearly identified
    	 if( this->txtPartName1->Text->Equals(S"") )
    	 {
    		 this->txtUnitPrice1->Text = S"0.00";
    		 this->txtQuantity1->Text  = S"0";
    		 this->txtSubTotal1->Text  = S"0.00";
    		 part1UnitPrice = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 part1UnitPrice = this->txtUnitPrice1->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Unit Price");
    			 this->txtUnitPrice1->Text = S"0.00";
    			 this->txtUnitPrice1->Focus();
    		 }
    
    		 try {
    			 part1Quantity = this->txtQuantity1->Text->ToInt16(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Quantity");
    			 this->txtQuantity1->Text = S"0";
    			 this->txtQuantity1->Focus();
    		 }
    	 }
    
    	 if( this->txtPartName2->Text->Equals(S"") )
    	 {
    		 this->txtUnitPrice2->Text = S"0.00";
    		 this->txtQuantity2->Text  = S"0";
    		 this->txtSubTotal2->Text  = S"0.00";
    		 part2UnitPrice = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 part2UnitPrice = this->txtUnitPrice2->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Unit Price");
    			 this->txtUnitPrice2->Text = S"0.00";
    			 this->txtUnitPrice2->Focus();
    		 }
    
    		 try {
    			 part2Quantity = this->txtQuantity2->Text->ToInt16(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Quantity");
    			 this->txtQuantity2->Text = S"0";
    			 this->txtQuantity2->Focus();
    		 }
    	 }
    
    	 if( this->txtPartName3->Text->Equals(S"") )
    	 {
    		 this->txtUnitPrice3->Text = S"0.00";
    		 this->txtQuantity3->Text  = S"0";
    		 this->txtSubTotal3->Text  = S"0.00";
    		 part3UnitPrice = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 part3UnitPrice = this->txtUnitPrice3->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Unit Price");
    			 this->txtUnitPrice3->Text = S"0.00";
    			 this->txtUnitPrice3->Focus();
    		 }
    
    		 try {
    			 part3Quantity = this->txtQuantity3->Text->ToInt16(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Quantity");
    			 this->txtQuantity3->Text = S"0";
    			 this->txtQuantity3->Focus();
    		 }
    	 }
    
    	 if( this->txtPartName4->Text->Equals(S"") )
    	 {
    		 this->txtUnitPrice4->Text = S"0.00";
    		 this->txtQuantity4->Text  = S"0";
    		 this->txtSubTotal4->Text  = S"0.00";
    		 part4UnitPrice = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 part4UnitPrice = this->txtUnitPrice4->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Unit Price");
    			 this->txtUnitPrice4->Text = S"0.00";
    			 this->txtUnitPrice4->Focus();
    		 }
    
    		 try {
    			 part4Quantity = this->txtQuantity4->Text->ToInt16(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Quantity");
    			 this->txtQuantity4->Text = S"0";
    			 this->txtQuantity4->Focus();
    		 }
    	 }
    
    	 if( this->txtPartName5->Text->Equals(S"") )
    	 {
    		 this->txtUnitPrice5->Text = S"0.00";
    		 this->txtQuantity5->Text  = S"0";
    		 this->txtSubTotal5->Text  = S"0.00";
    		 part5UnitPrice = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 part5UnitPrice = this->txtUnitPrice5->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Unit Price");
    			 this->txtUnitPrice5->Text = S"0.00";
    			 this->txtUnitPrice5->Focus();
    		 }
    
    		 try {
    			 part5Quantity = this->txtQuantity5->Text->ToInt16(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Quantity");
    			 this->txtQuantity5->Text = S"0";
    			 this->txtQuantity5->Focus();
    		 }
    	 }
    
    	 // Don't bill the customer for a job that is not specified
    	 if( this->txtJobPerformed1->Text->Equals(S"") )
    	 {
    		 this->txtJobPrice1->Text = S"0.00";
    		 job1Price = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 job1Price = this->txtJobPrice1->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Job Price");
    			 this->txtJobPrice1->Text = S"0.00";
    			 this->txtJobPrice1->Focus();
    		 }
    	 }
    				 
    	 if( this->txtJobPerformed2->Text->Equals(S"") )
    	 {
    		 this->txtJobPrice2->Text = S"0.00";
    		 job2Price = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 job2Price = this->txtJobPrice2->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Job Price");
    			 this->txtJobPrice2->Text = S"0.00";
    			 this->txtJobPrice2->Focus();
    		 }
    	 }
    				 
    	 if( this->txtJobPerformed3->Text->Equals(S"") )
    	 {
    		 this->txtJobPrice3->Text = S"0.00";
    		 job3Price = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 job3Price = this->txtJobPrice3->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Job Price");
    			 this->txtJobPrice3->Text = S"0.00";
    			 this->txtJobPrice3->Focus();
    		 }
    	 }
    				 
    	 if( this->txtJobPerformed4->Text->Equals(S"") )
    	 {
    		 this->txtJobPrice4->Text = S"0.00";
    		 job4Price = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 job4Price = this->txtJobPrice4->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Job Price");
    			 this->txtJobPrice4->Text = S"0.00";
    			 this->txtJobPrice4->Focus();
    		 }
    	 }
    				 
    	 if( this->txtJobPerformed5->Text->Equals(S"") )
    	 {
    		 this->txtJobPrice5->Text = S"0.00";
    		 job5Price = 0.00;
    	 }
    	 else
    	 {
    		 try {
    			 job5Price = this->txtJobPrice5->Text->ToDouble(0);
    		 }
    		 catch(FormatException *)
    		 {
    			 MessageBox::Show(S"Invalid Job Price");
    			 this->txtJobPrice5->Text = S"0.00";
    			 this->txtJobPrice5->Focus();
    		 }
    	 }
    				 
    	 part1SubTotal = part1UnitPrice * part1Quantity;
    	 part2SubTotal = part2UnitPrice * part2Quantity;
    	 part3SubTotal = part3UnitPrice * part3Quantity;
    	 part4SubTotal = part4UnitPrice * part4Quantity;
    	 part5SubTotal = part5UnitPrice * part5Quantity;
    
    	 this->txtSubTotal1->Text = part1SubTotal.ToString(S"F");
    	 this->txtSubTotal2->Text = part2SubTotal.ToString(S"F");
    	 this->txtSubTotal3->Text = part3SubTotal.ToString(S"F");
    	 this->txtSubTotal4->Text = part4SubTotal.ToString(S"F");
    	 this->txtSubTotal5->Text = part5SubTotal.ToString(S"F");
    
    	 totalParts    = part1SubTotal + part2SubTotal + part3SubTotal +
    			 part4SubTotal + part5SubTotal;
    				 
    	 totalLabor    = job1Price + job2Price + job3Price +
    		             job4Price + job5Price;
    				 
    	 try {
    		 taxRate = this->txtTaxRate->Text->ToDouble(0);
    	 }
    	 catch(FormatException *)
    	 {
    		 MessageBox::Show(S"Invalid Tax Rate");
    		 this->txtTaxRate->Text = S"7.75";
    		 this->txtTaxRate->Focus();
    	 }
    				 
    	 double totalPartsAndLabor = totalParts + totalLabor;
    	 taxAmount  = totalPartsAndLabor * taxRate / 100;
    	 totalOrder = totalPartsAndLabor + taxAmount;
    				 
    	 this->txtTotalParts->Text = totalParts.ToString(S"F");
    	 this->txtTotalLabor->Text = totalLabor.ToString(S"F");
    	 this->txtTaxAmount->Text  = taxAmount.ToString(S"F");
    	 this->txtTotalOrder->Text = totalOrder.ToString(S"F");
    }
  3. Execute the application to test it and fill the form with a record
  4. Click the Calculate Order button
  5. Close the form and return to your programming environment
 

Saving the Customer Order

Once a work order has been completed, it can be saved. There are various ways you can solve this. One of the easiest ways would consist of saving each order directly in its own file. The problem is that this would create too many files, especially if this business is successful. Another easy solution would consist of directly saving all orders of one customer in a particular file. This is suitable if the business deals with regularly returning customers, which is not always the case. Overall, you should provide as much flexibility as possible.

To make our application useful, we will allow the user to save an order to a file that whose name is after the day this order was placed. We will prompt the user so he or she can change the name of the file if necessary. When saving an order, if there is no order with that name, we will create a new XML file and store the order in it. If a file already exists under that name, then we will add the current order as part of the file. That way, all orders of a certain date can be saved in the same file, making it possible to retrieve the list of repairs that were completed on a certain day.

Practical Learning: Saving a Work Order

  1. Display the New Workorder form (NewWorkorder.h [Design]))
  2. Double-click the Save this Order button
  3. In the top section of the file, type the following:
     
    #pragma once
    
    #include "InfoCenter.h"
    
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::IO;
    using namespace System::Xml;
  4. Implement the event as follows:
     
    System::Void btnSaveOrder_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 // Get the date that the Order Date displays
    	 DateTime tmeToday = this->dtpOrderDate->Value;
    	 int day   = tmeToday.Day;
    	 int month = tmeToday.Month;
    	 int year  = tmeToday.Year;
    	 String *strMonth[] = { S"Jan", S"Feb", S"Mar", S"Apr",
    			S"May", S"Jun", S"Jul", S"Aug",
    			S"Sep", S"Oct", S"Nov", S"Dec" };
    	 String *strFilename = String::Concat(day.ToString(), strMonth[month-1],
    	                                  year.ToString(), S".xml");
    
    			 // Get a reference to the Data Center because 
    	 // that's where the DataSet object resides
    	 InfoCenter *frmData = new InfoCenter;
    
    	 // If the file exists already, open it
    	 if( File::Exists(strFilename) )
    		 frmData->dsWorkorders->ReadXml(strFilename);
    
    	 // Create a new record for the Workorder table
    	DataRow *rowNewOrder = 
    		frmData->dsWorkorders->Tables->Item[S"Workorder"]->NewRow();
    
     	rowNewOrder->Item[S"CustomerName"] = this->txtCustomerName->Text;
    	rowNewOrder->Item[S"Address"] = this->txtAddress->Text;
    	rowNewOrder->Item[S"City"] = this->txtCity->Text;
    	rowNewOrder->Item[S"State"] = this->txtState->Text;
    rowNewOrder->Item[S"ZIPCode"] = this->txtZIPCode->Text;
    rowNewOrder->Item[S"Make"] = this->txtMake->Text;
    rowNewOrder->Item[S"Model"] = this->txtModel->Text; 
    rowNewOrder->Item[S"CarYear"] = this->txtCarYear->Text;
    rowNewOrder->Item[S"Problem"] = this->txtProblem->Text;
    
    rowNewOrder->Item[S"PartName1"]  = this->txtPartName1->Text;
    rowNewOrder->Item[S"UnitPrice1"] = this->txtUnitPrice1->Text;
    rowNewOrder->Item[S"Quantity1"]  = this->txtQuantity1->Text;
    rowNewOrder->Item[S"SubTotal1"]  = this->txtSubTotal1->Text;
    
    rowNewOrder->Item[S"PartName2"]  = this->txtPartName2->Text;
    rowNewOrder->Item[S"UnitPrice2"] = this->txtUnitPrice2->Text;
    rowNewOrder->Item[S"Quantity2"]  = this->txtQuantity2->Text;
    rowNewOrder->Item[S"SubTotal2"]  = this->txtSubTotal2->Text;
    
    rowNewOrder->Item[S"PartName3"]  = this->txtPartName3->Text;
    rowNewOrder->Item[S"UnitPrice3"] = this->txtUnitPrice3->Text;
    rowNewOrder->Item[S"Quantity3"]  = this->txtQuantity3->Text;
    rowNewOrder->Item[S"SubTotal3"]  = this->txtSubTotal3->Text;
    	
    rowNewOrder->Item[S"PartName4"]  = this->txtPartName4->Text;
    rowNewOrder->Item[S"UnitPrice4"] = this->txtUnitPrice4->Text;
    rowNewOrder->Item[S"Quantity4"]  = this->txtQuantity4->Text;
    rowNewOrder->Item[S"SubTotal4"]  = this->txtSubTotal4->Text;
    
    rowNewOrder->Item[S"PartName5"]  = this->txtPartName5->Text;
    rowNewOrder->Item[S"UnitPrice5"] = this->txtUnitPrice5->Text;
    rowNewOrder->Item[S"Quantity5"]  = this->txtQuantity5->Text;
    rowNewOrder->Item[S"SubTotal5"]  = this->txtSubTotal5->Text;
    	
    rowNewOrder->Item[S"JobPerformed1"] = this->txtJobPerformed1->Text;
    rowNewOrder->Item[S"JobPrice1"] = this->txtJobPrice1->Text;
    rowNewOrder->Item[S"JobPerformed2"] = this->txtJobPerformed2->Text;
    rowNewOrder->Item[S"JobPrice2"] = this->txtJobPrice2->Text;
    rowNewOrder->Item[S"JobPerformed3"] = this->txtJobPerformed3->Text;
    rowNewOrder->Item[S"JobPrice3"] = this->txtJobPrice3->Text;
    rowNewOrder->Item[S"JobPerformed4"] = this->txtJobPerformed4->Text;
    rowNewOrder->Item[S"JobPrice4"] = this->txtJobPrice4->Text;
    rowNewOrder->Item[S"JobPerformed5"] = this->txtJobPerformed5->Text;
    rowNewOrder->Item[S"JobPrice5"] = this->txtJobPrice5->Text;
    
    rowNewOrder->Item[S"Recommendations"] = this->txtRecommendations->Text;
    
    rowNewOrder->Item[S"TotalParts"] = this->txtTotalParts->Text;
    rowNewOrder->Item[S"TotalLabor"] = this->txtTotalLabor->Text;
    rowNewOrder->Item[S"TaxRate"] = this->txtTaxRate->Text;
    rowNewOrder->Item[S"TaxAmount"] = this->txtTaxAmount->Text;
    rowNewOrder->Item[S"TotalOrder"] = this->txtTotalOrder->Text;
    
    	 // Add the new record to the AvailableItems table
    frmData->dsWorkorders->Tables->Item[S"Workorder"]->Rows->Add(rowNewOrder);
    
    	 // Update the XML file
    	 frmData->dsWorkorders->WriteXml(strFilename);
    
    	 // Reset the controls in case the user wants to add another record
    	 this->btnResetOrder_Click(sender, e);
    }
  5. Execute the application to test it
  6. Create a new record then click Calculate Order and save the order
  7. Create another order, calculate it and save it
  8. Close the form and return to your programming environment
 

Opening Customers' Orders

It is typical for a business to sell many products on the same way, just as is usual for a repair business to perform various transactions on the same day. When addressing the ability to save work orders, we allowed the user to save many orders of a typical day in the same file. In the same way, we will allow the user to open a file that contains all orders placed on a certain day. This would allow the management to review daily easily.

Practical Learning: Opening and Reviewing Daily Orders

  1. Display the Workorders form
  2. In the Data section of the Toolbox, click DataSet and click the form
  3. In the Add Dataset dialog box, click the Untyped Dataset radio button and click OK
  4. Change its properties as follows:
    (Name): dsDailyOrders
    DataSetName: DailyOrders
  5. Double-click an unoccupied area of the form outside of any group box
  6. In the top section of the file, type the following:
     
    #pragma once
    
    #include "InfoCenter.h"
    
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::IO;
    using namespace System::Xml;
  7. Implement the Load event as follows:
     
    System::Void Workorders_Load(System::Object *  sender, System::EventArgs *  e)
    {
    	 InfoCenter *frmData = new InfoCenter;
    	 this->dsDailyOrders = frmData->dsWorkorders;
    }
  8. Return to the form and double-click the Display Orders button
  9. Implement the event as follows:
     
    System::Void btnOpen_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 // Get the date that the Order Date displays
    	 DateTime tmeToday = this->dtpOrderDate->Value;
    	 int day   = tmeToday.Day;
    	 int month = tmeToday.Month;
    	 int year  = tmeToday.Year;
    	 String *strMonth[] = { S"Jan", S"Feb", S"Mar", S"Apr",
    			S"May", S"Jun", S"Jul", S"Aug",
    			S"Sep", S"Oct", S"Nov", S"Dec" };
    			 String *strFilename = String::Concat(day.ToString(), strMonth[month-1],
    				                                  year.ToString(), S".xml");
    
    	 // If the file exists already, open it
    	 if( File::Exists(strFilename) )
    	 {
    		 // Get a reference to the object that holds the daily repairs
    		 InfoCenter *frmInfo = new InfoCenter();
    		 // Empty the local data set of any data. This is required if
    		 // we want the user to be able to open different daily sets of repairs
    		 this->dsDailyOrders->Clear();
    		 // Refresh or initialize the local set with the information
    		 // stored centrally
    		 this->dsDailyOrders = frmInfo->dsWorkorders;
    
    		 // Open the set of orders placed on the day selected
    		 dsDailyOrders->ReadXml(strFilename);
    
    		 // Because a control can be bound anew every time the user opens a new set
    		 // Unbind each control to refresh it
    		 txtCustomerName->DataBindings->Clear();
    		 txtAddress->DataBindings->Clear();
    		 txtCity->DataBindings->Clear();
    		 txtState->DataBindings->Clear();
    		 txtZIPCode->DataBindings->Clear();
    		 txtMake->DataBindings->Clear();
    		 txtModel->DataBindings->Clear();
    		 txtCarYear->DataBindings->Clear();
    		 txtProblem->DataBindings->Clear();
    		 txtPartName1->DataBindings->Clear();
    		 txtUnitPrice1->DataBindings->Clear();
    		 txtQuantity1->DataBindings->Clear();
    		 txtSubTotal1->DataBindings->Clear();
    		 txtPartName2->DataBindings->Clear();
    		 txtUnitPrice2->DataBindings->Clear();
    		 txtQuantity2->DataBindings->Clear();
    		 txtSubTotal2->DataBindings->Clear();
    		 txtPartName3->DataBindings->Clear();
    		 txtUnitPrice3->DataBindings->Clear();
    		 txtQuantity3->DataBindings->Clear();
    		 txtSubTotal3->DataBindings->Clear();
    		 txtPartName4->DataBindings->Clear();
    		 txtUnitPrice4->DataBindings->Clear();
    		 txtQuantity4->DataBindings->Clear();
    		 txtSubTotal4->DataBindings->Clear();
    		 txtPartName5->DataBindings->Clear();
    		 txtUnitPrice5->DataBindings->Clear();
    		 txtQuantity5->DataBindings->Clear();
    		 txtSubTotal5->DataBindings->Clear();
    		 txtJobPerformed1->DataBindings->Clear();
    		 txtJobPrice1->DataBindings->Clear();
    		 txtJobPerformed2->DataBindings->Clear();
    		 txtJobPrice2->DataBindings->Clear();
    		 txtJobPerformed3->DataBindings->Clear();
    		 txtJobPrice3->DataBindings->Clear();
    		 txtJobPerformed4->DataBindings->Clear();
    		 txtJobPrice4->DataBindings->Clear();
    		 txtJobPerformed5->DataBindings->Clear();
    		 txtJobPrice5->DataBindings->Clear();
    		 txtRecommendations->DataBindings->Clear();
    		 txtTotalParts->DataBindings->Clear();
    		 txtTotalLabor->DataBindings->Clear();
    		 txtTaxRate->DataBindings->Clear();
    		 txtTaxAmount->DataBindings->Clear();
    		 txtTotalOrder->DataBindings->Clear();
    
    		 // Bind each control with data gotten from the newly opened file
    txtCustomerName->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.CustomerName"));
    	 txtAddress->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Address"));
    	 txtCity->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.City"));
    	 txtState->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.State"));
    	 txtZIPCode->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.ZIPCode"));
    	 txtMake->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Make"));
    	 txtModel->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Model"));
    	 txtCarYear->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.CarYear"));
    	 txtProblem->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Problem"));
    	 txtPartName1->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.PartName1"));
    	 txtUnitPrice1->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.UnitPrice1"));
    	 txtQuantity1->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Quantity1"));
    	 txtSubTotal1->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.SubTotal1"));
    	 txtPartName2->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.PartName2"));
    	 txtUnitPrice2->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.UnitPrice2"));
    	 txtQuantity2->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Quantity2"));
    	 txtSubTotal2->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.SubTotal2"));
    	 txtPartName3->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.PartName3"));
    	 txtUnitPrice3->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.UnitPrice3"));
    	 txtQuantity3->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Quantity3"));
    	 txtSubTotal3->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.SubTotal3"));
    	 txtPartName4->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.PartName4"));
    	 txtUnitPrice4->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.UnitPrice4"));
    	 txtQuantity4->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Quantity4"));
    	 txtSubTotal4->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.SubTotal4"));
    	 txtPartName5->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.PartName5"));
    	 txtUnitPrice5->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.UnitPrice5"));
    	 txtQuantity5->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Quantity5"));
    	 txtSubTotal5->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.SubTotal5"));
    txtJobPerformed1->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPerformed1"));
    	 txtJobPrice1->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPrice1"));
    txtJobPerformed2->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPerformed2"));
    	 txtJobPrice2->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPrice2"));
    txtJobPerformed3->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPerformed3"));
    	 txtJobPrice3->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPrice3"));
    txtJobPerformed4->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPerformed4"));
    	 txtJobPrice4->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPrice4"));
    txtJobPerformed5->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPerformed5"));
    	 txtJobPrice5->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.JobPrice5"));
    txtRecommendations->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.Recommendations"));
    	 txtTotalParts->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.TotalParts"));
    	 txtTotalLabor->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.TotalLabor"));
    	 txtTaxRate->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.TaxRate"));
    	 txtTaxAmount->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.TaxAmount"));
    	 txtTotalOrder->DataBindings->Add(new System::Windows::Forms::Binding(S"Text", dsDailyOrders, S"Workorder.TotalOrder"));
    	 }	 
    	 else // If there is no data, let the user know
    		 MessageBox::Show(String::Concat(S"No workorder available for ", this->dtpOrderDate->Value.ToString()));
    }
  10. Return to the Workorders form. Double-click the First button and implement its Click event as follows:
     
    System::Void btnFirst_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 this->BindingContext->get_Item(dsDailyOrders, S"Workorder")->Position = 0;
    }
  11. Return to the Workorders form. Double-click the Previous button and implement its Click event as follows:
     
    System::Void btnPrevious_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 this->BindingContext->get_Item(dsDailyOrders, S"Workorder")->Position = 
    		 this->BindingContext->get_Item(dsDailyOrders, S"Workorder")->Position - 1;
    }
  12. Return to the Workorders form. Double-click the Next button and implement its Click event as follows:
     
    System::Void btnNext_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 this->BindingContext->get_Item(dsDailyOrders, S"Workorder")->Position = 
    		 this->BindingContext->get_Item(dsDailyOrders, S"Workorder")->Position + 1;
    }
  13. Return to the Workorders form. Double-click the Last button and implement its Click event as follows:
     
    System::Void btnLast_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 this->BindingContext->get_Item(dsDailyOrders, S"Workorder")->Position = 
    		 this->BindingContext->get_Item(dsDailyOrders, S"Workorder")->Count - 1;
    }
  14. Display the Workorders form and try opening a previously saved order
  15. Close the forms
 

Home Copyright © 2004-2006 FunctionX, Inc.