Application Setup

Introduction

In this exercise, we will create a semi-small graphical application for a water distribution company that provides water for various types of customers, including residential families, private businesses, government buildings, etc. The application uses a text-based database that processes records using collection classes. The records are saved in JSON files.

Practical LearningPractical Learning: Introducing the Application

  1. Start Microsoft Visual Studio
  2. In the Visual Studio 2026 dialog box, click Create a New Project
  3. In the Create a New Project dialog box, in the Languages combo box, select Visual Basic
  4. In the list of projects templates, click Windows Forms App
  5. Click Next
  6. Change the Project Name to StellarWaterPoint2
  7. Click Next
  8. In the Framework combo box, select the highest version: .NET 10.0 (Long Term Support)
  9. Click Create
  10. To create a folder, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Folder
  11. Type Models as the name of the folder

The Main Form of the Application

Our application will use a central form acting as a switchboard from which other section-based forms can be accessed.

Practical LearningPractical Learning: Preparing the Main Form of the Application

  1. In the Solution Explorer, right-click Form1.vb and click Rename
  2. Type WaterDistribution (to get WaterDistribution.vb) and press Enter
  3. Read the message on the message box and click Yes
  4. Click the body of the form to make sure it is selected.
    In the Properties window, change the following characteristics:
    Text: Stellar Water Point
    StartPosition: CenterScreen
    MaximizeBox: False
  5. Right-click the body of the form and click View Code
  6. Change the document as follows:
    Imports System.IO
    
    Public Class WaterDistribution
        private sub WaterDistribution_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Directory.CreateDirectory("C:\Stellar Water Point2")
        End Sub
    End Class

Water Meters

Introduction

The company of our application uses water meters to monitor the amount of water its customers consume. To start, the application needs a list of water meters that are available.

Practical LearningPractical Learning: Displaying Water Meters

  1. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. In the Solution Explorer, right-click Models -> Add -> Class
  3. Replace the name with WaterMeter
  4. Click Add
  5. Change the code as follows:
    Public Class WaterMeter
        Public Property WaterMeterId As Integer
        Public Property MeterNumber As String
        Public Property Make As String
        Public Property Model As String
        Public Property MeterSize As String
    End Class

Displaying Water Meters

To let the user see a list of the water meters in the database, we will use a form equipped with a list view.

Practical LearningPractical Learning: Displaying Water Meters

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. For the Name of the form, type WaterMetersCentral
  3. Click Add
  4. In the Toolbox, click the ListView button and click the form
  5. On the form, right-click the list view and click Edit Columns...
  6. Create the columns as follows:
    (Name) Text Width TextAlign
    colWaterMeterId Water Meter Id 150  
    colMeterNumber Meter # 150 Center
    ColMake Make 300  
    ColModel Model 150  
    ColMeterSize Meter Size 150  
  7. Click OK
  8. Position and resize the list view on the form as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View LvwWaterMeters FullRowSelect: True
    GridLines: True
    View: Details
  9. Right-click the body of the form and click View Code
  10. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class Central
        Private Sub ShowWaterMeters()
            Dim StrWaterMeters As String = nothing
            Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point2\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                Using TrWaterMeters As TextReader = New StreamReader(FiWaterMeters.FullName)
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = CType(JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                    LvwWaterMeters.Items.Clear()
    
                    For Each Wm As WaterMeter In WaterMeters
                        Dim LviWaterMeter As ListViewItem = New ListViewItem(CStr(Wm.WaterMeterId))
    
                        LviWaterMeter.SubItems.Add(Wm.MeterNumber)
                        LviWaterMeter.SubItems.Add(Wm.Make)
                        LviWaterMeter.SubItems.Add(Wm.Model)
                        LviWaterMeter.SubItems.Add(Wm.MeterSize)
    
                        LvwWaterMeters.Items.Add(LviWaterMeter)
                    Next
                End Using
            End If
        End Sub
    
        private sub Central_Load(sender As Object, e As EventArgs) handles  Central.Load Handles MyBase.Load
            ShowWaterMeters()
        End Sub
    End Class
  11. In the Solution Explorer, double-click WaterDistribution.vb to display the main form of the application
  12. From the Toolbox, add a button to the form
  13. From the Properties window, change the characteristics of the button as follows:

    Stellar Water Point

    Control (Name) Text Font
    Button Button BtnWaterMeters &Water Meters... Times New Roman, 24pt, style=Bold
  14. Right-click the body of the form and click View Code
  15. Impliment an event as follows:
    Imports System.IO
    
    Public Class WaterDistribution
        private sub WaterDistribution_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Directory.CreateDirectory("C:\Stellar Water Point2")
        End Sub
    
        private sub BtnWaterMeters_Click(sender As Object, e As EventArgs) Handles BtnWaterMeters.Click
            Dim Listing = New WaterMetersCentral()
    
            Listing.Show()
        End Sub
    End Class

A Water Meter Record

A water meter must be installed in the location where water is consumed. We will create a form that allows a user to create a new record for a water meter.

Practical LearningPractical Learning: Creating a Water Meter Record

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. Type WaterMetersCreate
  3. Design the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text Other Properties
    Label Label   &Meter #:  
    MaskedTextBox Masked Text Box MtbMeterNumber   Masked: 000-000-000
    Modifiers: Public
    Label Label   &Water Meter Id:  
    TextBox Text Box TxtWaterMeterId   Modifiers: Public
    Label Label   M&ake:  
    TextBox Text Box TxtMake   Modifiers: Public
    Label Label   M&odel:  
    TextBox Text Box TxtModel   Modifiers: Public
    Label Label   Me&ter Size:  
    TextBox Text Box TxtMeterSize   Modifiers: Public
    Button Button BtnOK &OK DialogResult: OK
    Button Button BtnCancel &Cancel DialogResult: Cancel
  4. Using the Properties window, change some characteristics of the form as follows:
    FormBorderStyle: FixedDialog
    Text:            Stellar Water Point - Create Water Meter
    StartPosition:   CenterScreen
    AcceptButton:    BtnOK
    CancelButton:    BtnCancel
  5. Right-click the body of the form and click View Code
  6. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterMetersCreate
        Private Sub WaterMetersCreate_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim strWaterMeters = Nothing
            Dim WaterMeters = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point2\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            Dim WaterMeterId = 0
    
            If FiWaterMeters.Exists = True Then
                Using TrWaterMeters As TextReader = New StreamReader(FiWaterMeters.FullName)
                    strWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = CType(JsonSerializer.Deserialize(strWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                    For Each Meter As WaterMeter In waterMeters
                        WaterMeterId = Meter.WaterMeterId
                    Next
                End Using
            End If
    
            TxtWaterMeterId.Text = CStr(WaterMeterId + 1)
        End Sub
    End Class
  7. In the Solution Explorer, double-click WaterMetersCentral.vb
  8. From the Toolbox, add a button to the form below the list view
  9. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Text
    ListView List View No Change No Change
    Button Button BtnNewWaterMeter &New Water Meter...
  10. Right-click anywhere on the form and click View Code
  11. Add code for the Click event of the button as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterMetersCentral
        Private Sub ShowWaterMeters()
            . . .
        End Sub
    
        private sub Central_Load(sender As Object, e As EventArgs) handles  Central.Load Handles MyBase.Load
            ShowWaterMeters()
        End Sub
    
        Private Sub BtnNewWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnNewWaterMeter.Click
            Dim Make = New WaterMetersCreate()
    
            If Make.ShowDialog() = DialogResult.OK Then
                If Make.MtbMeterNumber.Text.Replace("-", "").Trim() = "" Then
                    MsgBox("You must type a meter number. " &
                           "Otherwise, the water meter cannot be set up.",
                           MsgBoxStyle.OkOnly, "Stellar Water Point")
                    Exit Sub
                End If
    
                Dim StrWaterMeters As String = Nothing
                Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
                Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
                Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
                If FiWaterMeters.Exists = True Then
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = CType(JsonSerializer.Deserialize((StrWaterMeters, GetType(List(Of WaterMeter)), options:=New JsonSerializerOptions() With {.WriteIndented = True})
                End If
    
                Dim Meter As WaterMeter = New WaterMeter()
    
                If Make.TxtWaterMeterId.Text = "" Then
                    Meter.WaterMeterId = 1
                Else
                    Meter.WaterMeterId = CInt(Make.TxtWaterMeterId.Text)
                End If
    
                Meter.MeterNumber = Make.MtbMeterNumber.Text
                Meter.Make = Make.TxtMake.Text
                Meter.Model = Make.TxtModel.Text
                Meter.MeterSize = Make.TxtMeterSize.Text
    
                WaterMeters.Add(Meter)
    
                Dim Options As JsonSerializerOptions = New JsonSerializerOptions()
                Options.WriteIndented = True
    
                Dim jsWaterMeters = JsonSerializer.Serialize(WaterMeters, GetType(List(Of WaterMeter)), Options)
                File.WriteAllText(FiWaterMeters.FullName, jsWaterMeters)
            End If
    
            ShowWaterMeters()
        End Sub
    End Class
  12. To execute the application, on the main menu, click Debug -> Start Without Debugging

    Stellar Water Point

  13. On the Central form, click the Water Meters button:

    Stellar Water Point - Water Meters

  14. Click the New Water Meter button:

    Stellar Water Point - New Water Meter

  15. Enter the value for each of the following records and click OK (or press Enter) for each:

    Meter # Make Model Meter Size
    392-494-572 Constance Technologies TG-4822 5/8 Inches
    938-705-869 Stan Wood 66-G 1 Inch
    588-279-663 Estellano NCF-226 3/4 Inches

    Stellar Water Point - Water Meters

  16. Close the forms and return to your programming environment

Water Meter Details

When the records of water meters have been created, sometimes, a user may want to view some details about a water meter. We are going to create such a form.

Practical LearningPractical Learning: Creating a Water Meter Record

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. For the Name of the form, type WaterMetersDetails
  3. Press Enter
  4. Design the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text Enabled Modifiers Other Properties
    Label Label   &Meter #:      
    MaskedTextBox Masked Text Box MtbMeterNumber   False Public Masked: 000-000-000
    Button Button BtnFindWaterMeter &Find Water Meter      
    Label Label   Make:      
    TextBox Text Box TxtMake   False Public  
    Label Label   Model:      
    TextBox Text Box TxtModel   False Public  
    Label Label   Meter Size:      
    TextBox Text Box TxtMeterSize   False Public  
    Label Label   Water Meter Id:      
    TextBox Text Box TxtWaterMeterId   False Public  
    Button Button BtnClose &Close      
  5. Right-click anywhere on the form and click View Code
  6. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterMetersDetails
        private sub BtnFindWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnFindWaterMeter.Click
            If String.IsNullOrEmpty(MtbMeterNumber.Text) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrWaterMeters = Nothing
            Dim WaterMeters = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = CType(JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                For Each Meter As WaterMeter In WaterMeters
                    If Meter.MeterNumber = MtbMeterNumber.Text Then
                        TxtWaterMeterId.Text = Meter.WaterMeterId
                        TxtMake.Text = Meter.Make
                        TxtModel.Text = Meter.Model
                        TxtMeterSize.Text = Meter.MeterSize
                    End If
                Next
            End If
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) handles btnclose.click Handles BtnClose.Click
            Close()
        End Sub
    End Class
  7. In the Solution Explorer, below the WaterMeters folder, double-click Central.vb to open its form
  8. From the Toolbox, add a button to the form below the list view and to the right of the New Water Meter button
  9. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View No Change No Change
    Button Button No Change No Change
    Button Button BtnViewWaterMeter &View Water Meter...
  10. Right-click the form and click View Code
  11. Add code for the Click event of the new button as follows:
    Private Sub BtnWaterMeterDetails_Click(sender As Object, e As EventArgs) Handles BtnWaterMeterDetails.Click
        Dim Details As New WaterMetersDetails
    
        Details.Show()
    End Sub
  12. To execute the application, on the main menu, click Debug -> Start Without Debugging

    Stellar Water Point

  13. On the Water Distribution form, click the Water Meters button
  14. On the Central form of water meters, click the View Water Meter button:

    Stellar Water Point - View Water Meter

  15. In the Meter # text, type 392-494-572
  16. Click the Find Water Button button:

    Stellar Water Point - View Water Meter

  17. Close the forms and return to your programming environment

Updating a Water Meter Record

One of the routine operations performed on a database is to change the details of a record. To support this operation for a water meter, we will create a form that can be used to update the information of a water meter.

Practical LearningPractical Learning: Updating a Water Meter

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint -> Add -> Form (Windows Forms)...
  2. For the Name of the file, type WaterMetersEditor as the name of the form
  3. Click Add
  4. Design the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text Enabled Other Properties
    Label Label   &Meter #:    
    MaskedTextBox Masked Text Box MtbMeterNumber   False Masked: 000-000-000
    Button Button BtnFindWaterMeter &Find Water Meter    
    Label Label   Make:    
    TextBox Text Box TxtMake   False  
    Label Label   Model:    
    TextBox Text Box TxtModel   False  
    Label Label   Meter Size:    
    TextBox Text Box TxtMeterSize   False  
    Button Button BtnUpdateWaterMeter &Update Water Meter    
    Button Button BtnClose &Close    
  5. Right-click somewhere on the form and click View Code
  6. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterMetersEditor
    
        private sub BtnFindWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnFindWaterMeter.Click
            If String.IsNullOrEmpty(MtbMeterNumber.Text) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrWaterMeters = Nothing
            Dim WaterMeters = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = CType(JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                For Each Meter As WaterMeter In WaterMeters
                    If Meter.MeterNumber = MtbMeterNumber.Text Then
                        TxtWaterMeterId.Text = Meter.WaterMeterId
                        TxtMake.Text = Meter.Make
                        TxtModel.Text = Meter.Model
                        TxtMeterSize.Text = Meter.MeterSize
                    End If
                Next
            End If
        End Sub
    
        Private Sub BtnUpdateWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnUpdateWaterMeter.Click
            If String.IsNullOrEmpty(MtbMeterNumber.Text) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim strWaterMeters = Nothing
            Dim WaterMeters = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                strWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = CType(JsonSerializer.Deserialize(strWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                Dim meter = WaterMeters.Find(Function(Mtr) Mtr.MeterNumber = MtbMeterNumber.Text)
    
                If Not meter Is Nothing Then
                    meter.WaterMeterId = CInt(TxtWaterMeterId.Text)
                    meter.Make = TxtMake.Text
                    meter.Model = TxtModel.Text
                    meter.MeterSize = TxtMeterSize.Text
    
                    Dim options = New JsonSerializerOptions()
                    options.WriteIndented = True
    
                    Dim jsWaterMeters = JsonSerializer.Serialize(WaterMeters, GetType(List(Of WaterMeter)), options)
                    File.WriteAllText(FiWaterMeters.FullName, jsWaterMeters)
                End If
            End If
    
            Close()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  7. In the Solution Explorer, double-click WaterMetersCentral.vb
  8. From the Toolbox, add a button to the form below the list view and on the right side of the View Water Meter button
  9. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View No Change No Change
    Button Button No Change No Change
    Button Button No Change No Change
    Button Button BtnEditWaterMeter &Edit Water Meter...
  10. Right-click the form and click View Code
  11. Add a procedure as follows:
    Private Sub BtnWaterMeterEitor_Click(sender As Object, e As EventArgs) Handles BtnWaterMeterEditor.Click
        Dim Editor As New WaterMetersEditor
    
        Editor.ShowDialog()
    
        ShowWaterMeters()
    End Sub
  12. To execute the application, on the main menu, click Debug -> Start Without Debugging:

    Stellar Water Point

  13. On the Central form, click the Water Meters button:

    Stellar Water Point - Water Meters

  14. Click the Update Water Meter button:

    Stellar Water Point - Water Meter Editor

  15. In the Meter # text, type 938-705-869
  16. Click the Find button

    Stellar Water Point - Water Meter Editor

  17. Change the values as follows:
    Make: Stanford Trend
    Model: 266G
    Meter Size: 1 1/2 Inches

    Stellar Water Point - Water Meter Editor

  18. Click the Update button:

    Stellar Water Point - Water Meters

  19. Close the forms and return to your programming environment

Removing a Water Meter from the Database

If a record of a water meter is not necessary anymore, a user can be asked to delete such a record. We are going to create a form for such an operation.

Practical LearningPractical Learning: Deleting a Water Meter Record

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form(Windows Forms)...
  2. In the Name text box, replace the string with WaterMetersDelete as the name of the form
  3. Press Enter
  4. Design the form as follows:

    Stellar Water Point - Water Meter Deletion

    Control (Name) Text Enabled Other Properties
    Label Label   &Meter #:    
    MaskedTextBox Masked Text Box MtbMeterNumber   False Masked: 000-000-000
    Label Label   Make:    
    TextBox Text Box TxtMake   False  
    Label Label   Model:    
    TextBox Text Box TxtModel   False  
    Label Label   Meter Size:    
    TextBox Text Box TxtMeterSize   False  
    Button Button BtnClose &Close    
  5. Right-click anywhere on the form and click View Code
  6. Change the document as tollows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterMetersDelete
        private sub BtnFindWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnFindWaterMeter.Click
            If String.IsNullOrEmpty(MtbMeterNumber.Text) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrWaterMeters = Nothing
            Dim WaterMeters = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = CType(JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                For Each Meter As WaterMeter In WaterMeters
                    If Meter.MeterNumber = MtbMeterNumber.Text Then
                        TxtWaterMeterId.Text = Meter.WaterMeterId
                        TxtMake.Text = Meter.Make
                        TxtModel.Text = Meter.Model
                        TxtMeterSize.Text = Meter.MeterSize
                    End If
                Next
            End If
        End Sub
    
        Private Sub BtnDeleteWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnDeleteWaterMeter.Click
            If MtbMeterNumber.Text.Replace("-", "").Trim().Equals(Nothing) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrWaterMeters = Nothing
            Dim WaterMeters = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = CType(JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                Dim Meter = WaterMeters.Find(Function(Mtr) Mtr.MeterNumber = MtbMeterNumber.Text)
    
                If Not Meter Is Nothing Then
                    If MsgBox("Are you sure you want to delete this water meter " &
                              "(you cannot undo the action)?",
                              MsgBoxStyle.YesNoCancel, "Stellar Water Point") = MsgBoxResult.Yes Then
                        WaterMeters.Remove(Meter)
    
                        Dim options = New JsonSerializerOptions()
                        options.WriteIndented = True
    
                        Dim jsWaterMeters = JsonSerializer.Serialize(WaterMeters, GetType(List(Of WaterMeter)), options)
                        File.WriteAllText(FiWaterMeters.FullName, jsWaterMeters)
    
                        MsgBox("The water meter has been removed from our database.",
                               MsgBoxStyle.OkOnly, "Stellar Water Point")
                    End If
                End If
            End If
    
            Close()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  7. In the Solution Explorer, double-click WaterMetersCentral.vb
  8. From the Toolbox, add two buttons to the form below the list view and on the right side of the Edit Water Meter button
  9. Change the characteristics of the buttons as follows:

    Stellar Water Point - Water Meters

    Control (Name) Text Anchor
    ListView List View LvwWaterMeters   Top, Bottom, Left, Right
    Button Button BtnNewWaterMeter &New Water Meter... Bottom, Right
    Button Button BtnViewWaterMeter &View Water Meter... Bottom, Right
    Button Button BtnEditWaterMeter &Edit Water Meter... Bottom, Right
    Button Button BtnDeleteWateMeter &Delete Water Meter... Bottom, Right
    Button Button BtnClose &Close Bottom, Right
  10. On the form, double-click the Delete Water Meter button
  11. Return to the Central form of the water meters and double-click the Close button
  12. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterMetersCentral
        Private Sub ShowWaterMeters()
            Dim StrWaterMeters As String = String.Empty
            Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                Using TrWaterMeters As TextReader = New StreamReader(FiWaterMeters.FullName)
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = CType(JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter))), List(Of WaterMeter))
    
                    LvwWaterMeters.Items.Clear()
    
                    For Each Wm As WaterMeter In WaterMeters
                        Dim LviWaterMeter As ListViewItem = New ListViewItem(Wm.WaterMeterId)
    
                        LviWaterMeter.SubItems.Add(Wm.MeterNumber)
                        LviWaterMeter.SubItems.Add(Wm.Make)
                        LviWaterMeter.SubItems.Add(Wm.Model)
                        LviWaterMeter.SubItems.Add(Wm.MeterSize)
    
                        LvwWaterMeters.Items.Add(LviWaterMeter)
                    Next
                End Using
            End If
        End Sub
    
        private sub Central_Load(sender As Object, e As EventArgs) handles  Central.Load Handles MyBase.Load
            ShowWaterMeters()
        End Sub
    
        Private Sub BtnNewWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnNewWaterMeter.Click
            Dim Make = New WaterMetersCreate
    
            If Make.ShowDialog = DialogResult.OK Then
                If Make.MtbMeterNumber.Text.Replace("-", "").Trim = "" Then
                    MsgBox("You must type a meter number. " &
                           "Otherwise, the water meter cannot be set up.",
                           MsgBoxStyle.OkOnly, "Stellar Water Point")
                    Exit Sub
                End If
    
                Dim StrWaterMeters As String = Nothing
                Dim WaterMeters = New List(Of WaterMeter)
                Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
                Dim FiWaterMeters = New FileInfo(FileWaterMeters)
    
                If FiWaterMeters.Exists = True Then
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
                End If
    
                Dim Meter = New WaterMeter
    
                If Make.TxtWaterMeterId.Text = "" Then
                    Meter.WaterMeterId = 1
                Else
                    Meter.WaterMeterId = CInt(Make.TxtWaterMeterId.Text)
                End If
    
                Meter.MeterNumber = Make.MtbMeterNumber.Text
                Meter.Make = Make.TxtMake.Text
                Meter.Model = Make.TxtModel.Text
                Meter.MeterSize = Make.TxtMeterSize.Text
    
                WaterMeters.Add(Meter)
    
                Dim Options = New JsonSerializerOptions
                Options.WriteIndented = True
    
                Dim jsWaterMeters = JsonSerializer.Serialize(WaterMeters, GetType(List(Of WaterMeter)), Options)
                File.WriteAllText(FiWaterMeters.FullName, jsWaterMeters)
            End If
    
            ShowWaterMeters()
        End Sub
    
        Private Sub BtnWaterMeterDetails_Click(sender As Object, e As EventArgs) Handles BtnWaterMeterDetails.Click
            Dim Details As New WaterMetersDetails
    
            Details.Show()
        End Sub
    
        Private Sub BtnWaterMeterEitor_Click(sender As Object, e As EventArgs) Handles BtnWaterMeterEditor.Click
            Dim Editor As New WaterMetersEditor
    
            Editor.ShowDialog()
    
            ShowWaterMeters()
        End Sub
    
        Private Sub BtnDeleteWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnDeleteWaterMeter.Click
            Dim Delete As New WaterMetersDelete
    
            Delete.ShowDialog()
    
            ShowWaterMeters()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  13. To execute the application, on the main menu, click Debug -> Start Without Debugging:

    Stellar Water Point - Water Meters

  14. On the Central form, click the Water Meters button:

    Stellar Water Point - Water Meters

  15. On the Central form of the water meters, click the Delete Water Meter button:

    Stellar Water Point - Water Meter Deletion

  16. In the Meter # text, type 588-279-663
  17. Click the Find button:

    Stellar Water Point - Water Meter Deletion

  18. Click the Delete button:

    Stellar Water Point - Water Meter Deletion

  19. Read the text on the message box and click Yes
  20. Read the other message box and click OK
  21. In the same way, delete the other two records
  22. Close the forms and return to your programming environment

Customers

Introduction

For a water distribution company, a customer is a person, a business, or any entity that consumes water. At a minimum, a computer must keep a list of entities that use its business.

Accounts Types

To help the company manage customers accounts and especially for accounting purpose, every customer account will be identified with its type of account. This is because the company deals with regular residences, businesses, government entitites, etc. To assist with this, we will create a class for accounts types.

Practical LearningPractical Learning: Introducing Accounts Types

  1. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. In the Solution Explorer, right-click Models -> Add -> Class
  3. Set the file Name to AccountType
  4. Click Add
  5. Change the code as follows:
    Public Class AccountType
        Public Property AccountTypeId As Integer
        Public Property TypeCode As String
        Public Property TypeDecription As String
    End Class
  6. In the Solution Explorer, right-click WaterDistribution.vb and click View Code
  7. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterDistribution
        Private Sub CreateWaterMeters()
            Dim WaterMeters = New List(Of WaterMeter) From {
                New WaterMeter With {.WaterMeterId = 1, .MeterNumber = "392-494-572", .Make = "Constance Technologies", .Model = "TG-4822", .MeterSize = "5/8 Inches"},
                New WaterMeter With {.WaterMeterId = 2, .MeterNumber = "938-725-869", .Make = "Stanford Trend", .Model = "266G", .MeterSize = "1 1/2 Inches"},
                New WaterMeter With {.WaterMeterId = 3, .MeterNumber = "588-279-663", .Make = "Estellano", .Model = "NCF-226", .MeterSize = "4 Inches"},
                New WaterMeter With {.WaterMeterId = 4, .MeterNumber = "186-962-805", .Make = "Lansome", .Model = "2800", .MeterSize = "1 1/2 Inches"},
                New WaterMeter With {.WaterMeterId = 5, .MeterNumber = "379-386-979", .Make = "Planetra", .Model = "P-2020", .MeterSize = "4 Inches"},
                New WaterMeter With {.WaterMeterId = 6, .MeterNumber = "580-742-825", .Make = "Kensa Sons", .Model = "KS2000A", .MeterSize = "1 3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 7, .MeterNumber = "849-351-444", .Make = "Raynes Energica", .Model = "a1088", .MeterSize = "2 Inches"},
                New WaterMeter With {.WaterMeterId = 8, .MeterNumber = "208-428-308", .Make = "Constance Technologies", .Model = "808D", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 9, .MeterNumber = "738-588-249", .Make = "Warrington", .Model = "W4242", .MeterSize = "5/8 Inches"},
                New WaterMeter With {.WaterMeterId = 10, .MeterNumber = "496-813-794", .Make = "Estellano", .Model = "NCF-226", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 11, .MeterNumber = "862-715-006", .Make = "Warrington", .Model = "W-4040", .MeterSize = "1/2 Inch"},
                New WaterMeter With {.WaterMeterId = 12, .MeterNumber = "649-358-184", .Make = "Raynes Energica", .Model = "b1700", .MeterSize = "1 1/2 Inches"},
                New WaterMeter With {.WaterMeterId = 13, .MeterNumber = "928-317-924", .Make = "Gongola", .Model = "GN1000", .MeterSize = "2 Inch"},
                New WaterMeter With {.WaterMeterId = 14, .MeterNumber = "595-753-147", .Make = "Grass Grill", .Model = "CRC-1000", .MeterSize = "1 Inch"},
                New WaterMeter With {.WaterMeterId = 15, .MeterNumber = "799-528-461", .Make = "Kensa Sons", .Model = "K-584-L", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 16, .MeterNumber = "386-468-057", .Make = "Estellano", .Model = "NCF-226", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 17, .MeterNumber = "938-275-294", .Make = "Constance Technologies", .Model = "TT-8822", .MeterSize = "4 Inches"},
                New WaterMeter With {.WaterMeterId = 18, .MeterNumber = "288-427-585", .Make = "Planetra", .Model = "P-2020", .MeterSize = "1/2 Inch"},
                New WaterMeter With {.WaterMeterId = 19, .MeterNumber = "394-835-297", .Make = "Raynes Energica", .Model = "i2022", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 20, .MeterNumber = "847-252-246", .Make = "Master Stream", .Model = "2000-MS", .MeterSize = "1 1/2 Inches"},
                New WaterMeter With {.WaterMeterId = 21, .MeterNumber = "349-725-848", .Make = "Planetra", .Model = "P-8000", .MeterSize = "4 Inches"},
                New WaterMeter With {.WaterMeterId = 22, .MeterNumber = "713-942-058", .Make = "Master Stream", .Model = "3366-MS", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 23, .MeterNumber = "747-581-379", .Make = "Warrington", .Model = "W4242", .MeterSize = "5/8 Inches"},
                New WaterMeter With {.WaterMeterId = 24, .MeterNumber = "582-755-263", .Make = "Kensa Sons", .Model = "KS2000A", .MeterSize = "1 Inch"},
                New WaterMeter With {.WaterMeterId = 25, .MeterNumber = "827-260-758", .Make = "Raynes Energica", .Model = "a1088", .MeterSize = "1-1/4 Inch"},
                New WaterMeter With {.WaterMeterId = 26, .MeterNumber = "837-806-836", .Make = "Lansome", .Model = "7400", .MeterSize = "5/8 Inches"},
                New WaterMeter With {.WaterMeterId = 27, .MeterNumber = "207-964-835", .Make = "Constance Technologies", .Model = "TG-6220", .MeterSize = "5/8 Inches"},
                New WaterMeter With {.WaterMeterId = 28, .MeterNumber = "296-837-495", .Make = "Raynes Energica", .Model = "QG505", .MeterSize = "4 Inches"},
                New WaterMeter With {.WaterMeterId = 29, .MeterNumber = "468-359-486", .Make = "Grass Grill", .Model = "KLP-8822", .MeterSize = "1-1/4 Inch"},
                New WaterMeter With {.WaterMeterId = 30, .MeterNumber = "931-486-003", .Make = "Planetra", .Model = "P-2020", .MeterSize = "1/2 Inch"},
                New WaterMeter With {.WaterMeterId = 31, .MeterNumber = "483-770-648", .Make = "Warren", .Model = "WWW", .MeterSize = "0.1 Inches"},
                New WaterMeter With {.WaterMeterId = 32, .MeterNumber = "592-824-957", .Make = "Kensa Sons", .Model = "D-497-H", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 33, .MeterNumber = "293-835-704", .Make = "Gongola", .Model = "GOL1000", .MeterSize = "1/2 Inch"},
                New WaterMeter With {.WaterMeterId = 34, .MeterNumber = "739-777-749", .Make = "Warrington", .Model = "W2200W", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 35, .MeterNumber = "374-886-284", .Make = "Raynes Energica", .Model = "i2022", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 36, .MeterNumber = "186-959-757", .Make = "Kensa Sons", .Model = "M-686-G", .MeterSize = "1 1/2 Inches"},
                New WaterMeter With {.WaterMeterId = 37, .MeterNumber = "594-827-359", .Make = "Planetra", .Model = "P-8000", .MeterSize = "1 Inch"},
                New WaterMeter With {.WaterMeterId = 38, .MeterNumber = "394-739-242", .Make = "Master Stream", .Model = "9393-TT", .MeterSize = "5/8 Inches"},
                New WaterMeter With {.WaterMeterId = 39, .MeterNumber = "529-283-752", .Make = "Constance Technologies", .Model = "404T", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 40, .MeterNumber = "295-770-695", .Make = "Warrington", .Model = "W-2286", .MeterSize = "1-1/4 Inch"},
                New WaterMeter With {.WaterMeterId = 41, .MeterNumber = "739-749-737", .Make = "Kensa Sons", .Model = "KS2000A", .MeterSize = "1 Inch"},
                New WaterMeter With {.WaterMeterId = 42, .MeterNumber = "947-528-317", .Make = "Gondola", .Model = "GDL-5000", .MeterSize = "1 Inch"},
                New WaterMeter With {.WaterMeterId = 43, .MeterNumber = "630-207-055", .Make = "Lansome", .Model = "2800", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 44, .MeterNumber = "827-508-248", .Make = "Standard Trend", .Model = "428T", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 45, .MeterNumber = "293-924-869", .Make = "Grass Grill", .Model = "CRC-2020", .MeterSize = "1/2 Inch"},
                New WaterMeter With {.WaterMeterId = 46, .MeterNumber = "928-247-580", .Make = "Gondola", .Model = "GOL2000", .MeterSize = "0.34 Inch"},
                New WaterMeter With {.WaterMeterId = 47, .MeterNumber = "682-537-380", .Make = "Planetra", .Model = "P-2020", .MeterSize = "1-1/4 Inch"},
                New WaterMeter With {.WaterMeterId = 48, .MeterNumber = "470-628-850", .Make = "Estellano", .Model = "WRT-482", .MeterSize = "3/4 Inches"},
                New WaterMeter With {.WaterMeterId = 49, .MeterNumber = "649-373-505", .Make = "Constance Technologies", .Model = "BD-7000", .MeterSize = "5/8 Inches"},
                New WaterMeter With {.WaterMeterId = 50, .MeterNumber = "306-842-497", .Make = "Lansome", .Model = "9000", .MeterSize = "3/4 Inches"}
            }
    
            Dim strWaterMeters = Nothing
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim options = New JsonSerializerOptions()
            options.WriteIndented = True
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
            Dim jsWaterMeters As String = JsonSerializer.Serialize(WaterMeters, GetType(List(Of WaterMeter)), options)
            File.WriteAllText(FiWaterMeters.FullName, jsWaterMeters)
        End Sub
    
        Private Sub CreateAccountsTypes()
            Dim Types = New List(Of AccountType)
    
            Types.Add(New AccountType With {.AccountTypeId = 1, .TypeCode = "OTH", .TypeDecription = "Other"})
            Types.Add(New AccountType With {.AccountTypeId = 3, .TypeCode = "RES", .TypeDecription = "Residential Household"})
            Types.Add(New AccountType With {.AccountTypeId = 2, .TypeCode = "BUS", .TypeDecription = "General Business, Commercial, Industrial"})
            Types.Add(New AccountType With {.AccountTypeId = 5, .TypeCode = "UUO", .TypeDecription = "Unidentified or Unclassified Type of Organization"})
            Types.Add(New AccountType With {.AccountTypeId = 4, .TypeCode = "SGO", .TypeDecription = "Social/Government/Non-Profit Organization, Institutional"})
            Types.Add(New AccountType With {.AccountTypeId = 6, .TypeCode = "WAT", .TypeDecription = "Water Intensive Business (Agricultural, Laudromat, Hair Salon, Restaurant, etc"})
    
    
            Dim StrAccountsTypes = Nothing
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim Options = New JsonSerializerOptions()
            Options.WriteIndented = True
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
            Dim jsAccountsTypes = JsonSerializer.Serialize(Types, GetType(List(Of AccountType)), Options)
            File.WriteAllText(FiAccountsTypes.FullName, jsAccountsTypes)
        End Sub
        
        private sub WaterDistribution_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            REM        Directory.CreateDirectory("C:\Stellar Water Point16")
    
            CreateWaterMeters()
            CreateAccountsTypes()
        End Sub
    
        private sub BtnWaterMeters_Click(sender As Object, e As EventArgs) Handles BtnWaterMeters.Click
            Dim Listing = New WaterMetersCentral()
    
            Listing.Show()
        End Sub
    End Class
  8. To execute the application, on the main menu, click Debug -> Start Without Debugging
  9. Close the forms and return to your programming environment
  10. Change the WaterDistribution.vb document as follows:
    private sub WaterDistribution_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        REM Directory.CreateDirectory("C:\Stellar Water Point16")
    
        REM CreateWaterMeters()
        REM CreateAccountsTypes()
    End Sub

Practical LearningPractical Learning: Introducing Customers

  1. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. On the main menu, click Project -> Add Class...
  3. Replace the name with Customer
  4. Click Add
  5. Change the code as follows:
    Public Class Customer
        Public Property CustomerId As Integer
        Public Property AccountNumber As String
        Public Property AccountName As String
        Public Property AccountType As String
        Public Property MeterNumber As String
        Public Property Address As String
        Public Property City As String
        Public Property County As String
        Public Property State As String
        Public Property ZIPCode As String
    End Class

Displaying Customers

In a later section, we will learn how to create a customer record. When those records exist, a user can display them. We are going to make it possible through a form equipped with a list view

Practical LearningPractical Learning: Displaying Customers

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. For the Name of the form, type CustomersCentral
  3. Click Add
  4. In the Toolbox, click the ListView button and click the form
  5. On the form, right-click the list view and click Edit Columns...
  6. Create the columns as follows:
    (Name) Text TextAlign Width
    ColCustomerId Id   40
    ColAccountNumber Account # Center 150
    ColAccountName Account Name   200
    ColAccountType Account Type   200
    ColMeterNumber Meter # Center 100
    ColAddress Address   250
    ColCity City   125
    ColCounty County   125
    ColState State Center  
    ColZIPCode ZIP-Code Center 125
  7. Click OK
  8. Position and resize the list view on the form as follows:

    Stellar Water Point - Customers

    Control (Name) Other Properties
    ListView List View LvwCustomers FullRowSelect: True
    GridLines: True
    View: Details
  9. Right-click any area of the form and click View Code
  10. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class CustomersCentral
    
        Private Sub ShowCustomers()
            Dim StrCustomers = Nothing
            Dim Customers As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
            Dim StrAccountsTypes = Nothing
            Dim AccountsTypes = New List(Of AccountType)
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Customers = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    LvwCustomers.Items.Clear()
    
                    For Each Client As Customer In Customers
                        Dim LviCustomer As ListViewItem = New ListViewItem(CStr(Client.CustomerId))
    
                        LviCustomer.SubItems.Add(Client.AccountNumber)
                        LviCustomer.SubItems.Add(Client.AccountName)
                        LviCustomer.SubItems.Add(Client.MeterNumber)
    
                        Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
                        StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                        AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                        For Each ActType As AccountType In AccountsTypes
                            If Client.AccountType = ActType.TypeCode Then
                                LviCustomer.SubItems.Add(String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription))
                            End If
                        Next
    
                        LviCustomer.SubItems.Add(Client.Address)
                        LviCustomer.SubItems.Add(Client.City)
                        LviCustomer.SubItems.Add(Client.County)
                        LviCustomer.SubItems.Add(Client.State)
                        LviCustomer.SubItems.Add(Client.ZIPCode)
                        LvwCustomers.Items.Add(LviCustomer)
                    Next
                End Using
            End If
        End Sub
    
        Private Sub CustomersCentral_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ShowCustomers()
        End Sub
    End Class
  11. In the Solution Explorer, double-click WaterDistribution.vb to display the main form of the application
  12. From the Toolbox, add a button to the form
  13. From the Properties window, change the characteristics of the button as follows:

    Stellar Water Point

    Control (Name) Text Font
    Button Button BtnCustomers C&ustomers... Times New Roman, 24pt, style=Bold
  14. Right-click andy part of the form and click View Code
  15. Impliment the Click event of the Customers as follows:
    Private Sub BtnCustomers_Click(sender As Object, e As EventArgs) Handles BtnCustomers.Click
        Dim Central = New CustomersCentral
    
        Central.ShowDialog()
    End Sub

A New Customer Account

To use the services of a water distribution company, a customer must have an account. We are going to create a form that an employee can use to establish an account for a new customer.

Practical LearningPractical Learning: Creating a Customer Account

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. For the Name of the file, type CustomersCreate as the name of the form
  3. Click Add
  4. Design the form as follows:

    Stellar Water Point - New Customer Account

    Control (Name) Text Other Properties
    Label Label   &Account #:  
    MaskedTextBox Masked Text Box MtbAccountNumber   Masked: 0000-000-0000
    Label Label   &Account Name:  
    TextBox Text Box TxtAccountName    
    Label Label   &Meter #:  
    MaskedTextBox Masked Text Box MtbMeterNumber   Masked: 000-000-000
    Button Button BtnFindWaterMeter &Find Water Meter  
    Label Label   Meter &Details:  
    TextBox Text Box TxtMeterDetails   Enabled: False
    Label Label   &Account Type:  
    ComboBox Combo Box cbxAccountsTypes  
    Label Label   &Address:  
    TextBox Text Box TxtAddress    
    Label Label   C&ity:  
    TextBox Text Box TxtCity    
    Label Label   C&ounty:  
    TextBox Text Box TxtCounty    
    Label Label   &State:  
    TextBox Text Box TxtState    
    Label Label   &ZIP-Code:  
    MaskedTextBox Masked Text Box MtbZIPCode   Masked: Zip-Code
    Label Label   Customer Id:&  
    TextBox Text Box TxtCustomerId    
    Button Button BtnSaveCustomerAccount S&ave Customer Account DialogResult: OK
    Button Button BtnClose &Close DialogResult: Cancel
  5. Using the Properties window, change some characteristics of the form as follows:
    FormBorderStyle: FixedDialog
    Text:            Stellar Water Point - Create Customer Account
    StartPosition:   CenterScreen
    AcceptButton:    BtnSaveCustomerAccount
    CancelButton:    BtnCancel
  6. Right-click an area of the form and click View Code
  7. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class CustomersCreate
        Private Sub SetCustomerId()
            Dim StrCustomers = Nothing
            Dim Customers As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            Dim CustomerId = 0
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Customers = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    For Each Client As Customer In Customers
                        CustomerId = Client.CustomerId
                    Next
                End Using
            End If
    
            TxtCustomerId.Text = CStr(CustomerId + 1)
        End Sub
    
        Private Sub SetAccountsTypes()
            Dim StrAccountsTypes = Nothing
            Dim Types As List(Of AccountType) = New List(Of AccountType)
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiAccountsTypes.Exists = True Then
                StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                Types = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                For Each Type As AccountType In Types
                    CbxAccountsTypes.Items.Add(Type.TypeCode & " - " & Type.TypeDecription)
                Next
            End If
        End Sub
    
        Private Sub CustomersCreate_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            SetCustomerId()
            SetAccountsTypes()
        End Sub
    
        Private Sub BtnFindWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnFindWaterMeter.Click
            If MtbMeterNumber.Text.Replace("-", "").Trim().Equals(Nothing) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim strWaterMeters = Nothing
            Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                strWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = JsonSerializer.Deserialize(strWaterMeters, GetType(List(Of WaterMeter)))
    
                For Each Meter As WaterMeter In WaterMeters
                    If Meter.MeterNumber = MtbMeterNumber.Text Then
                        TxtMeterDetails.Text = Meter.WaterMeterId.ToString() & " - " &
                                           Meter.Make & " " &
                                           Meter.Model &
                                           " (Meter Size: " & Meter.MeterSize & ")"
                    End If
                Next
            End If
        End Sub
    End Class
  8. In the Solution Explorer, below the Customers folder, double-click CustomersCentral.vb
  9. From the Toolbox, add a button to the form below the list view
  10. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View LvwCustomers FullRowSelect: True
    GridLines: True
    View: Details
    Button Button BtnNewCustomerAccount &New Customer Account...
  11. Right-click the body of the form and click View Code
  12. Create an event as follows:
    Private Sub BtnCreateCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnCreateCustomerAccount.Click
        Dim Create As CustomersCreate = New CustomersCreate()
    
        If Create.ShowDialog() = DialogResult.OK Then
            If Create.MtbAccountNumber.Text.Replace("-", "").Trim().Equals("") Then
                MsgBox("You must provide an account number for a new customer. " &
                       "Otherwise, the account cannot be created.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            If Create.MtbMeterNumber.Text.Replace("-", "").Trim().Equals(Nothing) Then
                MsgBox("You must type a valid meter number to associate " &
                       "a water meter to a customer's account. After providing " &
                       "a meter number, click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            If FiCustomers.Exists = True Then
                StrCustomers = File.ReadAllText(FiCustomers.FullName)
                Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
            End If
    
            Dim Consumer As Customer = New Customer With {
                .CustomerId = CInt(Create.TxtCustomerId.Text),
                .AccountNumber = Create.MtbAccountNumber.Text,
                .AccountName = Create.TxtAccountName.Text,
                .AccountType = Create.CbxAccountsTypes.Text.Substring(0, 3),
                .MeterNumber = Create.MtbMeterNumber.Text,
                .Address = Create.TxtAddress.Text,
                .City = Create.TxtCity.Text,
                .County = Create.TxtCounty.Text,
                .State = Create.TxtState.Text,
                .ZIPCode = Create.MtbZIPCode.Text
            }
    
            Clients.Add(Consumer)
    
            Dim options = New JsonSerializerOptions()
            options.WriteIndented = True
    
            Dim jsCustomers As String = JsonSerializer.Serialize(Clients, GetType(List(Of Customer)), options)
            File.WriteAllText(FiCustomers.FullName, jsCustomers)
        End If
    
        ShowCustomers()
    End Sub
  13. To execute the application, on the main menu, click Debug -> Start Without Debugging:

    Stellar Water Point - New Customer Account

  14. On the Water Distribution form, click the Customers button:

    Stellar Water Point - Customers Accounts

  15. On the Central form of the customers, click the Create Customer Account button:

    Stellar Water Point - Customers Accounts

  16. In the account # text box, type 9279-570-8394
  17. In the meter # text box, type 799-528-461
  18. Click the Find water meter button
  19. Enter the other values as follows:
    Account #:    9279-570-8394
    Account Name: Thomas Stones
    Meter #:      799-528-461
    Account Type: RES - Residential Household
    Address:      10252 Broward Ave #D4
    City:         Frederick
    County:       Frederick
    State:        MD
    ZIP-Code:     21703-4422

    Stellar Water Point - New Customer Account

  20. Click Save Customer Account
  21. In the same way, create the following two records:

    Account # Account Name Meter # Account Type Address City County State ZIP-Code
    4086-938-4783 Hernola Dough 594-827-359 UUO - Unidentified or Unclassified Type of Organization 10 10 Hexagonal Drv Winston Yoke Penn 11402-4411
    7080-583-5947 Sunny Yard 827-508-248 WAT - Water Intensive Business(Laudromat, Hair Salon, Restaurant, etc 663 Sherry Wood East Street Shimpstown Franklin PA 17236-2626

    Stellar Water Point - Customers

  22. Close the forms and return to your programming environment

Customer Account Details

When a customer account has been created, at any time, an employee may want to simply review such an account. Our application needs a form for that.

Practical LearningPractical Learning: Showing Customer Account

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. For the Name of the form, type CustomersDetails
  3. Press Enter
  4. Design the form as follows:

    Stellar Water Point - New Customer Account

    Control (Name) Text Other Properties
    Label Label   &Account #:  
    MaskedTextBox Masked Text Box MtbAccountNumber   Masked: 0000-000-0000
    Button Button BtnFindCustomerAccount &Find Customer Account  
    Label Label   &Account Name:  
    TextBox Text Box TxtAccountName   Enabled: False
    Label Label   Meter &Details:  
    TextBox Text Box TxtMeterDetails   Enabled: False
    Label Label   &Account Type:  
    TextBox Combo Box TxtAccountsTypes   Enabled: False
    Label Label   &Address:  
    TextBox Text Box TxtAddress   Enabled: False
    Label Label   C&ity:  
    TextBox Text Box TxtCity   Enabled: False
    Label Label   C&ounty:  
    TextBox Text Box TxtCounty   Enabled: False
    Label Label   &State:  
    TextBox Text Box TxtState   Enabled: False
    Label Label   &ZIP-Code:  
    TextBox Masked Text Box TxtZIPCode   Enabled: False
    Label Label   Customer Id:&:  
    TextBox Text Box TxtCustomerId   Enabled: False
    Button Button BtnClose &Close  
  5. Right-click any area of the form and click View Code
  6. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class CustomersDetails
        Private Sub btnFindCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnFindCustomerAccount.Click
            If MtbAccountNumber.Text.Replace("-", "").Trim() = "" Then
                MsgBox("You must type a valid account number of a customer, " &
                                "and then click the Find Customer Account button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers = String.Empty
            Dim StrAccountType = String.Empty
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            Dim StrMeterNumber = Nothing
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim Customers As IEnumerable(Of Customer) = From consumer
                                                                In Clients
                                                                Where consumer.AccountNumber = MtbAccountNumber.Text
                                                                Select consumer
    
                    For Each Client As Customer In Customers
                        TxtCustomerId.Text = Client.CustomerId
                        TxtAccountName.Text = Client.AccountName
                        StrMeterNumber = Client.MeterNumber
                        StrAccountType = Client.AccountType
                        TxtAddress.Text = Client.Address
                        TxtCity.Text = Client.City
                        TxtCounty.Text = Client.County
                        TxtState.Text = Client.State
                        TxtZIPCode.Text = Client.ZIPCode
                    Next
                End Using
            End If
    
            If Len(StrMeterNumber) > 0 Then
                Dim StrWaterMeters = Nothing
                Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
                Dim fileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
                Dim fiWaterMeters As FileInfo = New FileInfo(fileWaterMeters)
    
                If fiWaterMeters.Exists = True Then
                    StrWaterMeters = File.ReadAllText(fiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
    
                    Dim Meters As IEnumerable(Of WaterMeter) = From measure
                                                                         In WaterMeters
                                                               Where measure.MeterNumber = StrMeterNumber
                                                               Select measure
    
                    For Each Meter As WaterMeter In WaterMeters
                        TxtMeterDetails.Text = Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    Next
                End If
            End If
    
            Dim StrAccountsTypes = Nothing
            Dim Types As List(Of AccountType) = New List(Of AccountType)
            Dim fileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(fileAccountsTypes)
    
            If FiAccountsTypes.Exists = True Then
                StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                Types = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                Dim ActType As IEnumerable(Of AccountType) = From category
                                                             In Types
                                                             Where category.TypeCode = StrAccountType
                                                             Select category
    
    
                For Each Type As AccountType In Types
                    TxtAccountType.Text = $"{Type.TypeCode } - {Type.TypeDecription}"
                Next
            End If
        End Sub
    
        Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  7. In the Solution Explorer, double-click CustomersCentral.vb to open its form
  8. From the Toolbox, add a button to the form below the list view and to the right of the New Customer Account button
  9. Change the characteristics of the button as follows:

    Stellar Water Point - Customer Account Details

    Control (Name) Other Properties
    ListView List View LvwCustomers No Change
    Button Button No Change No Change
    Button Button BtnCustomerAccountDetails Customer Account &Details...
  10. Double-click the Customer Account &Details button
  11. Change the document as follows:
    Private Sub BtnCustomerAccountDetails_Click(sender As Object, e As EventArgs) Handles BtnCustomerAccountDetails.Click
        Dim Details As CustomersDetails = New CustomersDetails()
    
        Details.Show()
    End Sub
  12. To execute the application, on the main menu, click Debug -> Start Without Debugging

    Stellar Water Point

  13. On the Water Distribution form, click the Customers button
  14. On the Central form of the customers form, click the Customer Account &Details button:

    Stellar Water Point - View Water Meter

  15. In the Account # text, type 4086-938-4783
  16. Click the Find Customer Account button:

    Stellar Water Point - View Water Meter

  17. Close the forms and return to your programming environment

Editing a Customer Account

When a piece of information has changed about a customer, an employee should update the customer account. We will provide a for such an operation.

Practical LearningPractical Learning: Editing a Customer Account

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. For the Name of the file, type CustomersEditor as the name of the form
  3. Click Add
  4. Design the form as follows:

    Stellar Water Point - Customer Account Editor

    Control (Name) Text Other Properties
    Label Label   &Account #:  
    MaskedTextBox Masked Text Box MtbAccountNumber   Masked: 0000-000-0000
    Button Button BtnFindCustomerAccount &Find Customer Account  
    Label Label   &Account Name:  
    TextBox Text Box TxtAccountName    
    Label Label   &Meter #:  
    MaskedTextBox Masked Text Box MtbMeterNumber   Masked: 000-000-000
    Button Button BtnFindWaterMeter Find &Water Meter  
    Label Label   Meter &Details:  
    TextBox Text Box TxtMeterDetails   Enabled: False
    Label Label   &Account Type:  
    ComboBox Combo Box cbxAccountsTypes  
    Label Label   &Address:  
    TextBox Text Box TxtAddress    
    Label Label   C&ity:  
    TextBox Text Box TxtCity    
    Label Label   C&ounty:  
    TextBox Text Box TxtCounty    
    Label Label   &State:  
    TextBox Text Box TxtState    
    Label Label   &ZIP-Code:  
    MaskedTextBox Masked Text Box MtbZIPCode   Masked: Zip-Code
    Label Label   Customer Id:&:  
    TextBox Text Box TxtCustomerId   Enabled: False
    Button Button BtnUpdateCustomerAccount &Update Customer Account DialogResult: OK
    Button Button BtnClose &Close DialogResult: Cancel
  5. Right-click any area of the form cnad click View Code
  6. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class CustomersEditor
        Private Sub Editor_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim StrAccountsTypes = Nothing
            Dim Types As List(Of AccountType) = New List(Of AccountType)
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiAccountsTypes.Exists = True Then
                StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                Types = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                For Each ActType As AccountType In Types
                    CbxAccountsTypes.Items.Add(ActType.TypeCode & " - " & ActType.TypeDecription)
                Next
            End If
        End Sub
    
        Private Sub BtnFindCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnFindCustomerAccount.Click
            If MtbAccountNumber.Text.Replace("-", "").Trim() = "" Then
                MsgBox("You must type a valid account number of a customer, " &
                       "and then click the Find Customer Account button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers = Nothing
            Dim StrAccountType = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim Customers As IEnumerable(Of Customer) = From consumer
                                                                In Clients
                                                                Where consumer.AccountNumber = MtbAccountNumber.Text
                                                                Select consumer
    
                    For Each Client As Customer In Customers
                        TxtCustomerId.Text = Client.CustomerId.ToString()
                        TxtAccountName.Text = Client.AccountName
                        MtbMeterNumber.Text = Client.MeterNumber
                        StrAccountType = Client.AccountType
                        TxtAddress.Text = Client.Address
                        TxtCity.Text = Client.City
                        TxtCounty.Text = Client.County
                        TxtState.Text = Client.State
                        MtbZIPCode.Text = Client.ZIPCode
                    Next
                End Using
            End If
    
            If Len(MtbAccountNumber.Text) > 0 Then
                Dim strWaterMeters = Nothing
                Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
                Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
                Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
                If FiWaterMeters.Exists = True Then
                    strWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(strWaterMeters, GetType(List(Of WaterMeter)))
    
                    Dim Meters As IEnumerable(Of WaterMeter) = From measure
                                                               In WaterMeters
                                                               Where measure.MeterNumber = MtbMeterNumber.Text
                                                               Select measure
    
                    For Each Meter As WaterMeter In WaterMeters
                        TxtMeterDetails.Text = Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    Next
                End If
            End If
    
            Dim StrAccountsTypes = Nothing
            Dim Types As List(Of AccountType) = New List(Of AccountType)
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiAccountsTypes.Exists = True Then
                StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                Types = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                Dim ActType As IEnumerable(Of AccountType) = From category
                                                             In Types
                                                             Where category.TypeCode = StrAccountType
                                                             Select category
    
    
                For Each Type As AccountType In Types
                    CbxAccountsTypes.Text = $"{Type.TypeCode} - {Type.TypeDecription}"
                Next
            End If
        End Sub
    
        Private Sub BtnFindWaterMeter_Click(sender As Object, e As EventArgs) Handles BtnFindWaterMeter.Click
            If MtbMeterNumber.Text.Replace("-", "").Trim().Equals(Nothing) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrWaterMeters = Nothing
            Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point2\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
    
                For Each Meter As WaterMeter In WaterMeters
                    If Meter.MeterNumber = MtbMeterNumber.Text Then
                        TxtMeterDetails.Text = Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    End If
                Next
            End If
        End Sub
    
        Private Sub BtnUpdateCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnUpdateCustomerAccount.Click
            If String.IsNullOrEmpty(MtbAccountNumber.Text) Then
                MsgBox("Please enter an account number for a customer. " &
                       "You can then click the Find Customer Account button " &
                       "to indicate the customer whose account you want o update.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            If String.IsNullOrEmpty(MtbMeterNumber.Text) Then
                MsgBox("You must type a valid meter number, " &
                       "and then click the Find Water Meter button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers As String = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(fileCustomers)
    
            If fiCustomers.Exists = True Then
                StrCustomers = File.ReadAllText(FiCustomers.FullName)
                Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                Dim Client As Customer = Clients.Find(Function(Cust) Cust.AccountNumber = MtbAccountNumber.Text)
    
                If Not Client Is Nothing Then
                    Client.CustomerId = TxtCustomerId.Text
                    Client.AccountNumber = MtbAccountNumber.Text
                    Client.AccountName = TxtAccountName.Text
                    Client.MeterNumber = MtbMeterNumber.Text
                    Client.AccountType = CbxAccountsTypes.Text.Substring(0, 3)
                    Client.Address = TxtAddress.Text
                    Client.City = TxtCity.Text
                    Client.County = TxtCounty.Text
                    Client.State = TxtState.Text
                    Client.ZIPCode = MtbZIPCode.Text
    
                    Dim Options As JsonSerializerOptions = New JsonSerializerOptions()
                    Options.WriteIndented = True
    
                    Dim JsCustomers As String = JsonSerializer.Serialize(Clients, GetType(List(Of Customer)), Options)
                    File.WriteAllText(FiCustomers.FullName, JsCustomers)
                End If
            End If
    
            Close()
        End Sub
    
        Private sub BtnClose_Click(sender As Object, e As EventArgs) handles btnclose.click
                Close()
            end sub
    End Class
  7. In the Solution Explorer, below the Customers folder, double-click Central.vb
  8. From the Toolbox, add a button to the form below the list view and on the right side of the Customer Account Editor button
  9. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View LvwCustomers No Change
    Button Button BtnNewCustomerAccount No Change
    Button Button BtnCustomerAccountDetails No Change
    Button Button BtnUpdateCustomerAccount &Update Customer Account...
  10. Display the Central form of the Customers folder
  11. Double-click the Update Customer Account button
  12. Change the document as follows:
    Private Sub BtnCustomerAccountEditor_Click(sender As Object, e As EventArgs) Handles BtnCustomerAccountEditor.Click
        Dim Editor As CustomersEditor = New CustomersEditor()
    
        Editor.ShowDialog()
    
        ShowCustomers()
    End Sub
  13. To execute the application, on the main menu, click Debug -> Start Without Debugging

    Stellar Water Point

  14. On the main form of the application, click the Customers button:

    Stellar Water Point - Customers

  15. Click the Edit Customer Account button:

    Stellar Water Point - Customer Account Editor

  16. In the Account # text, type 4086-938-4783
  17. Click the Find Customer Account button

    Stellar Water Point - Customer Account Editor

  18. Change the values as follows:
    Account Name: Bernotte Doughnuts
    Meter #:      580-742-825 and click Find Water Meter
    Account Type: BUS - General Business, Commercial, Industrial
    Address:      10103 Hexagon Drive
    City:         Winterstown
    County:       York
    State:        PA
    ZIP-Code:     17402-8828

    Stellar Water Point - Customer Account Editor

  19. Click the Update Customer Account button:

    Stellar Water Point - Customers Accounts

  20. Close the forms and return to your programming environment

Deleting a Customer Account from the Database

If an employee realizes that a customer account must not exist anymore, the employee can delete that account. We will provide a form for such an operation.

Practical LearningPractical Learning: Deleting a Customer Account

  1. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  2. In the Name text box, replace the string with Delete as the name of the form
  3. Press Enter
  4. Design the form as follows:

    Stellar Water Point - Customer Account Deletion

    Control (Name) Text Other Properties
    Label Label   &Account #:  
    MaskedTextBox Masked Text Box MtbAccountNumber   Masked: 0000-000-0000
    Button Button BtnFindCustomerAccount &Find Customer Account  
    Label Label   &Account Name:  
    TextBox Text Box TxtAccountName   Enabled: False
    Label Label   Meter &Details:  
    TextBox Text Box TxtMeterDetails   Enabled: False
    Label Label   &Account Type:  
    TextBox Combo Box TxtAccountsTypes   Enabled: False
    Label Label   &Address:  
    TextBox Text Box TxtAddress   Enabled: False
    Label Label   C&ity:  
    TextBox Text Box TxtCity   Enabled: False
    Label Label   C&ounty:  
    TextBox Text Box TxtCounty   Enabled: False
    Label Label   &State:  
    TextBox Text Box TxtState   Enabled: False
    Label Label   &ZIP-Code:  
    TextBox Masked Text Box TxtZIPCode   Enabled: False
    Button Button BtnDeleteCustomerAccount &Delete Customer Account  
    Button Button BtnClose &Close  
  5. Right-click any part of the form and click View Code
  6. Change the document as tollows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class CustomersDelete
        Private Sub BtnFindCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnFindCustomerAccount.Click
            If MtbAccountNumber.Text.Replace("-", "").Trim() = "" Then
                MsgBox("You must type a valid account number of a customer, " &
                                "and then click the Find Customer Account button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers = Nothing
            Dim StrAccountType = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            Dim strMeterNumber = Nothing
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim Customers As IEnumerable(Of Customer) = From consumer
                                                                In Clients
                                                                Where consumer.AccountNumber = MtbAccountNumber.Text
                                                                Select consumer
    
                    For Each Client As Customer In Clients
                        TxtCustomerId.Text = Client.CustomerId
                        TxtAccountName.Text = Client.AccountName
                        strMeterNumber = Client.MeterNumber
                        StrAccountType = Client.AccountType
                        TxtAddress.Text = Client.Address
                        TxtCity.Text = Client.City
                        TxtCounty.Text = Client.County
                        TxtState.Text = Client.State
                        TxtZIPCode.Text = Client.ZIPCode
                    Next
                End Using
            End If
    
            If Len(strMeterNumber) > 0 Then
                Dim strWaterMeters = Nothing
                Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
                Dim FileWaterMeters = "C:\Stellar Water Point2\WaterMeters.json"
    
                Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
                If FiWaterMeters.Exists = True Then
                    strWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(strWaterMeters, GetType(List(Of WaterMeter)))
    
                    Dim Meters As IEnumerable(Of WaterMeter) = From measure
                                                               In WaterMeters
                                                               Where measure.MeterNumber = strMeterNumber
                                                               Select measure
    
                    For Each Meter As WaterMeter In WaterMeters
                        TxtMeterDetails.Text = Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    Next
                End If
            End If
    
            Dim StrAccountsTypes = Nothing
            Dim Types As List(Of AccountType) = New List(Of AccountType)
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiAccountsTypes.Exists = True Then
                StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                Types = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                Dim ActType As IEnumerable(Of AccountType) = From category
                                                             In Types
                                                             Where category.TypeCode = StrAccountType
                                                             Select category
    
    
                For Each Type As AccountType In Types
                    TxtAccountType.Text = $"{Type.TypeCode} - {Type.TypeDecription}"
                Next
            End If
        End Sub
    
        Private Sub BtnDeleteCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnDeleteCustomerAccount.Click
            If MtbAccountNumber.Text.Replace("-", "").Trim() = "" Then
                MsgBox("You must type a valid account number of a customer, " &
                       "and then click the Find Customer Account button. " &
                       "Only then can you delete an customer account.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            If FiCustomers.Exists = True Then
                StrCustomers = File.ReadAllText(FiCustomers.FullName)
                Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                Dim Client As Customer = Clients.Find(Function(Acnt) Acnt.AccountNumber = MtbAccountNumber.Text)
    
                If Not Client Is Nothing Then
                    If MsgBox("Are you sure you want to delete this customer's account " &
                              "(you cannot undo the action)?",
                              MsgBoxStyle.YesNoCancel, "Stellar Water Point") = MsgBoxResult.Yes Then
                        Clients.Remove(Client)
    
                        Dim Options As JsonSerializerOptions = New JsonSerializerOptions()
                        Options.WriteIndented = True
    
                        Dim JsCustomers As String = JsonSerializer.Serialize(Clients, GetType(List(Of Customer)), Options)
                        File.WriteAllText(FiCustomers.FullName, JsCustomers)
    
                        MsgBox("The customer's account has been deleted from our system.",
                               MsgBoxStyle.OkOnly, "Stellar Water Point")
                    End If
                End If
            End If
    
            Close()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  7. In the Solution Explorer, below the Customers folder, double-click Central.vb
  8. From the Toolbox, add two buttons to the form below the list view and on the right side of the Update Customer Account button
  9. Change the characteristics of the buttons as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View LvwCustomers FullRowSelect: True
    GridLines: True
    View: Details
    Anchor: Top, Bottom, Left, Right
    Button Button BtnCreateCustomerAccount Create Customer &Account....
    Anchor: Bottom, Right
    Button Button BtnCustomerAccountDetails Customer Account &Details...
    Anchor: Bottom, Right
    Button Button BtnEditCustomerAccount &Edit Customer Account...
    Anchor: Bottom, Right
    Button Button BtnDeleteCustomerAccount &Delete Customer Account...
    Anchor: Bottom, Right
    Button Button BtnClose &Close
    Anchor: Bottom, Right
  10. Right-click andy area of the form and click View Code
  11. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class CustomersCentral
        Private Sub ShowCustomers()
            Dim StrCustomers = Nothing
            Dim Customers As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
            Dim StrAccountsTypes = Nothing
            Dim AccountsTypes = New List(Of AccountType)
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Customers = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    LvwCustomers.Items.Clear()
    
                    For Each Client As Customer In Customers
                        Dim LviCustomer As ListViewItem = New ListViewItem(CStr(Client.CustomerId))
    
                        LviCustomer.SubItems.Add(Client.AccountNumber)
                        LviCustomer.SubItems.Add(Client.AccountName)
    
                        Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
                        StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                        AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                        For Each ActType As AccountType In AccountsTypes
                            If Client.AccountType = ActType.TypeCode Then
                                LviCustomer.SubItems.Add(String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription))
                            End If
                        Next
    
                        LviCustomer.SubItems.Add(Client.MeterNumber)
    
                        LviCustomer.SubItems.Add(Client.Address)
                        LviCustomer.SubItems.Add(Client.City)
                        LviCustomer.SubItems.Add(Client.County)
                        LviCustomer.SubItems.Add(Client.State)
                        LviCustomer.SubItems.Add(Client.ZIPCode)
                        LvwCustomers.Items.Add(LviCustomer)
                    Next
                End Using
            End If
        End Sub
    
        Private Sub CustomersCentral_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ShowCustomers()
        End Sub
    
        Private Sub BtnCreateCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnCreateCustomerAccount.Click
            Dim Create As CustomersCreate = New CustomersCreate()
    
            If Create.ShowDialog() = DialogResult.OK Then
                If Create.MtbAccountNumber.Text.Replace("-", "").Trim().Equals("") Then
                    MsgBox("You must provide an account number for a new customer. " &
                           "Otherwise, the account cannot be created.",
                           MsgBoxStyle.OkOnly, "Stellar Water Point")
                    Exit Sub
                End If
    
                If Create.MtbMeterNumber.Text.Replace("-", "").Trim().Equals(Nothing) Then
                    MsgBox("You must type a valid meter number to associate " &
                           "a water meter to a customer's account. After providing " &
                           "a meter number, click the Find Water Meter button.",
                           MsgBoxStyle.OkOnly, "Stellar Water Point")
                    Exit Sub
                End If
    
                Dim StrCustomers = Nothing
                Dim Clients As List(Of Customer) = New List(Of Customer)
                Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
                Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
                If FiCustomers.Exists = True Then
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
                End If
    
                Dim Consumer As Customer = New Customer With {
                    .CustomerId = Create.TxtCustomerId.Text,
                    .AccountNumber = Create.MtbAccountNumber.Text,
                    .AccountName = Create.TxtAccountName.Text,
                    .AccountType = Create.CbxAccountsTypes.Text.Substring(0, 3),
                    .MeterNumber = Create.MtbMeterNumber.Text,
                    .Address = Create.TxtAddress.Text,
                    .City = Create.TxtCity.Text,
                    .County = Create.TxtCounty.Text,
                    .State = Create.TxtState.Text,
                    .ZIPCode = Create.MtbZIPCode.Text
                }
    
                Clients.Add(Consumer)
    
                Dim options = New JsonSerializerOptions()
                options.WriteIndented = True
    
                Dim jsCustomers As String = JsonSerializer.Serialize(Clients, GetType(List(Of Customer)), options)
                File.WriteAllText(FiCustomers.FullName, jsCustomers)
            End If
    
            ShowCustomers()
        End Sub
    
        Private Sub BtnCustomerAccountDetails_Click(sender As Object, e As EventArgs) Handles BtnCustomerAccountDetails.Click
            Dim Details As CustomersDetails = New CustomersDetails()
    
            Details.Show()
        End Sub
    
        Private Sub BtnCustomerAccountEditor_Click(sender As Object, e As EventArgs) Handles BtnCustomerAccountEditor.Click
            Dim Editor As CustomersEditor = New CustomersEditor()
    
            Editor.ShowDialog()
    
            ShowCustomers()
        End Sub
    
        Private Sub BtnDeleteCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnDeleteCustomerAccount.Click
            Dim Delete As CustomersDelete = New CustomersDelete()
    
            Delete.ShowDialog()
    
            ShowCustomers()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  12. To execute the application, on the main menu, click Debug -> Start Without Debugging:

    Stellar Water Point

  13. On the Central form, click the Customers button:

    Stellar Water Point - Customers

  14. On the Central form of the customers, click the Delete Customer Account button:

    Stellar Water Point - Water Meter Deletion

  15. In the Account # text box, type 7080-583-5947
  16. Click the Find Customer Account button:

    Stellar Water Point - Customer Account Deletion

  17. Click the Delete Customer Account button

    Stellar Water Point - Customers

  18. Read the text on the message box.
    On the message box, click Yes

    Stellar Water Point - Customers

  19. In the same way, delete the other two records
  20. Close the forms and return to your programming environment
  21. Open the Customers.json file. Replace its contents with the following and save:
    [
      {
        "CustomerId": 1,
        "AccountNumber": "9279-570-8394",
        "AccountName": "Thomas Stones",
        "MeterNumber": "799-528-461",
        "AccountType": "RES",
        "Address": "10252 Broward Ave #D4",
        "City": "Frederick",
        "County": "Frederick",
        "State": "MD",
        "ZIPCode": "21703-4422"
      },
      {
        "CustomerId": 2,
        "AccountNumber": "4086-938-4783",
        "AccountName": "Bernotte Doughnuts",
        "MeterNumber": "580-742-825",
        "AccountType": "BUS",
        "Address": "10103 Hexagon Drv",
        "City": "Winterstown",
        "County": "York",
        "State": "PA",
        "ZIPCode": "17402-8818"
      },
      {
        "CustomerId": 3,
        "AccountNumber": "2068-258-9486",
        "AccountName": "Yollanda Training",
        "MeterNumber": "186-962-805",
        "AccountType": "UUO",
        "Address": "4819 East Munk Street",
        "City": "Whitehall",
        "County": "Fulton",
        "State": "PA",
        "ZIPCode": "17340-1188"
      },
      {
        "CustomerId": 4,
        "AccountNumber": "6986-829-3741",
        "AccountName": "Eyes Wide",
        "MeterNumber": "208-428-308",
        "AccountType": "BUS",
        "Address": "12087 Avencia Court #4D1",
        "City": "Silver Spring",
        "County": "Montgomery",
        "State": "MD",
        "ZIPCode": "20910-2288"
      },
      {
        "CustomerId": 5,
        "AccountNumber": "9947-374-2648",
        "AccountName": "Marianne Harrington",
        "MeterNumber": "862-715-006",
        "AccountType": "RES",
        "Address": "708 Correta Drv",
        "City": "Arlington",
        "State": "VA",
        "ZIPCode": "22222-6060"
      },
      {
        "CustomerId": 6,
        "AccountNumber": "4293-802-8506",
        "AccountName": "Kelly Davids",
        "MeterNumber": "496-813-794",
        "AccountType": "RES",
        "Address": "938 East Panchot Str",
        "City": "Greenwood",
        "County": "Sussex",
        "State": "DE",
        "ZIPCode": "19950-4242"
      },
      {
        "CustomerId": 7,
        "AccountNumber": "6240-857-4965",
        "AccountName": "First Methodist Congregation",
        "MeterNumber": "739-777-749",
        "AccountType": "RES",
        "Address": "7702 Charles Road",
      },
      {
        "CustomerId": 8,
        "AccountNumber": "7928-131-4850",
        "AccountName": "Department of Public Affairs",
        "AccountType": "SGO",
        "City": "Hyattsville",
        "County": "Prince Georges",
        "State": "MD",
        "ZIPCode": "20783-2277"
      },
      {
        "CustomerId": 9,
        "AccountNumber": "1386-949-2058",
        "AccountName": "Watson Country Buffet",
        "MeterNumber": "296-837-495",
        "AccountType": "WAT",
        "Address": "4862 Wellington Street",
        "City": "Hammonton",
        "County": "Atlantic ",
        "State": "NJ",
        "ZIPCode": "08037-2828"
      },
      {
        "CustomerId": 10,
        "AccountNumber": "7943-686-9786",
        "AccountName": "Angel Bulzaides",
        "MeterNumber": "394-835-297",
        "AccountType": "RES",
        "Address": "10227 Old Harbor Drv",
        "City": "Elkview",
        "County": "Kanawha",
        "State": "WV",
        "ZIPCode": "25071-5858"
      },
      {
        "CustomerId": 11,
        "AccountNumber": "4820-375-2842",
        "AccountName": "Sun Communal",
        "MeterNumber": "392-494-572",
        "AccountType": "SGO",
        "Address": "748 Red Hills Rd",
        "City": "Roanoke",
        "State": "VA",
        "ZIPCode": "24012-4824"
      },
      {
        "CustomerId": 12,
        "AccountNumber": "9618-579-2577",
        "AccountName": "Gerald Place",
        "MeterNumber": "847-252-246",
        "AccountType": "UUO",
        "Address": "3666 Hanchor Drv",
        "City": "Granville",
        "County": "Licking",
        "State": "OH",
        "ZIPCode": "43023-2777"
      },
      {
        "CustomerId": 13,
        "AccountNumber": "",
        "AccountName": ""
      },
      {
        "CustomerId": 14,
        "AccountNumber": "2037-495-8528",
        "AccountName": "Astral Sequence",
        "AccountType": "BUS",
        "Address": "12715 Eastern Gateway",
        "City": "Catonsville",
        "County": "Baltimore County"
      },
      {
        "CustomerId": 15,
        "AccountNumber": "6003-386-3955",
        "AccountName": "Mandiakandara Marmoudi",
        "MeterNumber": "374-886-284",
        "AccountType": "OTH",
        "Address": "539 Avalon Court",
        "City": "Greenwood",
        "County": "Sussex",
        "State": "DE",
        "ZIPCode": "19950-5550"
      },
      {
        "CustomerId": 16,
        "AccountNumber": "5294-859-7513",
        "AccountName": "Jeannette Schiller",
        "MeterNumber": "713-942-058",
        "AccountType": "RES",
        "Address": "10110 Winslow Ave",
        "City": "Mercerville",
        "County": "Mercer",
        "State": "NJ",
        "ZIPCode": "08619-7472"
      },
      {
        "CustomerId": 17,
        "AccountNumber": "9249-379-6848",
        "AccountName": "Country West Eatery",
        "MeterNumber": "588-279-663",
        "AccountType": "BUS",
        "Address": "8280 Sligo North Way",
        "City": "Albright",
        "County": "Preston",
        "State": "WV",
        "ZIPCode": "26519-6620"
      },
      {
        "CustomerId": 18,
        "AccountNumber": "5252-757-9595",
        "AccountName": "Sathyavanthara Khooni",
        "MeterNumber": "379-386-979",
        "AccountType": "RES",
        "Address": "4992 Preston Street",
        "State": "OH"
      },
      {
        "CustomerId": 19,
        "AccountNumber": "7080-583-5947",
        "AccountName": "Sunny Yard",
        "MeterNumber": "827-508-248",
        "AccountType": "WAT",
        "Address": "663 Sherry Wood East Street",
        "City": "Shimpstown",
        "County": "Franklin",
        "State": "PA",
        "ZIPCode": "17236-2626"
      },
      {
        "CustomerId": 20,
        "AccountNumber": "8027-304-6829",
        "AccountName": "Anthony Clarcksons",
        "MeterNumber": "837-806-836",
        "AccountType": "RES",
        "Address": "904 Augusta Drive",
        "City": "Blackbird",
        "County": "New Castle",
        "State": "DE",
        "ZIPCode": "19734-8822"
      },
      {
        "CustomerId": 21,
        "AccountNumber": "6699-396-2905",
        "AccountName": "Spencer Reuter",
        "MeterNumber": "649-373-505",
        "AccountType": "RES",
        "Address": "2850 Burnsweak Avenue",
        "City": "Silver Spring",
        "County": "Montgomery",
        "State": "MD",
        "ZIPCode": "20910-4044"
      },
      {
        "CustomerId": 22,
        "AccountNumber": "1827-395-0203",
        "AccountName": "Watson Country Buffet",
        "MeterNumber": "470-628-850",
        "AccountType": "WAT",
        "Address": "10331 Chryswell Road",
        "City": "Washington",
        "State": "DC",
        "ZIPCode": "20008-2426"
      },
      {
        "CustomerId": 23,
        "AccountNumber": "5862-736-9741",
        "AccountName": "Eastern Cage",
    
        "AccountType": "BUS",
        "Address": "2039 Night Stand Court",
        "City": "Hammonton",
        "State": "NJ"
      },
      {
        "CustomerId": 24,
        "AccountNumber": "3947-957-4958",
        "AccountName": "Patsil Industries",
        "MeterNumber": "747-581-379",
        "AccountType": "BUS",
        "Address": "10348 Larrens Drive",
        "City": "Baltimore",
        "County": "Baltimore",
        "State": "MD",
        "ZIPCode": "21215-2222"
      },
      {
        "CustomerId": 25,
        "AccountNumber": "2836-485-9699",
        "AccountName": "Red Oak High School",
        "MeterNumber": "379-386-979",
        "AccountType": "SGO",
        "Address": "442 Donham Road",
        "City": "Silver Spring",
        "County": "Montgomery",
        "State": "MD",
        "ZIPCode": "20910-8822"
      },
      {
        "CustomerId": 26,
        "AccountNumber": "5938-074-5293",
        "AccountName": "Park and Roll",
        "MeterNumber": "592-824-957",
        "AccountType": "SGO",
        "Address": "582G Dunhill Avenue",
        "City": "Lanham",
        "County": "Prince Georges",
        "State": "MD",
        "ZIPCode": "20706-8284"
      },
      {
        "CustomerId": 27,
        "AccountNumber": "3028-502-9418",
        "AccountName": "Spencer Kershaw",
        "MeterNumber": "186-959-757",
        "AccountType": "RES",
        "Address": "338C Grayson Street",
        "City": "Gatchellville",
        "County": "York",
        "State": "PA",
        "ZIPCode": "17352-6464"
      },
      {
        "CustomerId": 28,
        "AccountNumber": "9684-759-2227",
        "AccountName": "Country West Eatery",
        "MeterNumber": "928-317-924",
        "AccountType": "BUS"
      },
      {
        "CustomerId": 29,
        "AccountNumber": "2974-972-8139",
        "AccountName": "Paul Arnette",
        "MeterNumber": "295-770-695",
        "AccountType": "OTH",
        "Address": "8127 Bledsoe Str",
        "City": "Hyattsville",
        "County": "Prince Georges",
        "State": "MD",
        "ZIPCode": "20783-5858"
      },
      {
        "CustomerId": 30,
        "AccountNumber": "2758-493-7249",
        "AccountName": "Hervey Smile",
        "MeterNumber": "293-924-869",
        "AccountType": "WAT",
        "Address": "12973 Sonaa Street #E42",
        "City": "Silver Spring",
        "County": "Montgomery",
        "State": "MD",
        "ZIPCode": "20910-4488"
      },
      {
        "CustomerId": 31,
        "AccountNumber": "9337-947-3664",
        "AccountName": "Awesome Aid",
        "MeterNumber": "649-358-184",
        "AccountType": "SGO",
        "City": "Bellefontaine",
        "State": "OH"
      },
      {
        "CustomerId": 32,
        "AccountNumber": "7518-302-6895",
        "AccountName": "Grace Brenner",
        "MeterNumber": "207-964-835",
        "AccountType": "BUS",
        "Address": "4299 Peachtree Court",
        "City": "Rockville",
        "County": "Montgomery",
        "State": "MD",
        "ZIPCode": "20853-1888"
      },
      {
        "CustomerId": 33,
        "AccountNumber": "2937-947-3008",
        "AccountName": "Jeffrey Maney",
        "AccountType": "RES"
      },
      {
        "CustomerId": 34,
        "AccountNumber": "7028-405-9381",
        "AccountName": "Valley Services",
        "MeterNumber": "306-842-497",
        "AccountType": "WAT",
        "Address": "613 Meadowhill Road",
        "City": "Alonzaville",
        "County": "Shenandoah",
        "State": "VA",
        "ZIPCode": "22664-8080"
      },
      {
        "CustomerId": 35,
        "AccountNumber": "5293-957-3395",
        "AccountName": "Wellway Community Center",
        "MeterNumber": "386-468-057",
        "AccountType": "RES",
        "Address": "10484 Greenway Avenue",
        "City": "Mt Storm",
        "County": "Grant",
        "State": "WV",
        "ZIPCode": "26739-7700"
      },
      {
        "CustomerId": 36,
        "AccountNumber": "2038-413-9680",
        "AccountName": "Eastern Friandise",
        "MeterNumber": "938-725-869",
        "AccountType": "BUS",
        "Address": "2075 Rose Hills Avenue",
        "City": "Washington",
        "State": "DC",
        "ZIPCode": "20004-2626"
      },
      {
        "CustomerId": 37,
        "AccountNumber": "7484-744-9708",
        "AccountName": "Amidou Gomah",
        "AccountType": "RES",
        "Address": "14118 Yellow Burrough Blvd",
        "City": "Philadelphia",
        "State": "PA"
      },
      {
        "CustomerId": 38,
        "AccountNumber": "3792-853-6885",
        "AccountName": "Department of Public Affairs",
        "MeterNumber": "595-753-147",
        "City": "Upper Marlboro",
        "County": "Prince George County"
      },
      {
        "CustomerId": 39,
        "AccountNumber": "8282-777-8282",
        "AccountName": "Garland Hotel",
        "MeterNumber": "938-275-294",
        "AccountType": "BUS",
        "Address": "4222 Extell Ave",
        "City": "Cambridge",
        "State": "MD",
        "ZIPCode": "21613-2288"
      },
      {
        "CustomerId": 40,
        "AccountNumber": "5975-863-7057",
        "AccountName": "Single Connection",
        "MeterNumber": "288-427-585",
        "AccountType": "BUS",
        "City": "Mansfield",
        "State": "OH",
        "ZIPCode": "44903-3030"
      },
      {
        "CustomerId": 41,
        "AccountNumber": "2499-636-4444",
        "AccountName": "Bryanna Spencer",
        "AccountType": "RES",
        "Address": "6282 Sheppherd Str",
        "County": "Anne Arundel"
      },
      {
        "CustomerId": 42,
        "AccountNumber": "2842-585-7260",
        "AccountName": "District Community Reserves",
        "MeterNumber": "349-725-848",
        "AccountType": "SGO",
        "Address": "3280 Hopewell Street, NE",
        "City": "Washington"
      },
      {
        "CustomerId": 43,
        "AccountNumber": "9282-794-7937",
        "AccountName": "Yashua Yáñés",
        "MeterNumber": "392-494-572",
        "AccountType": "RES",
        "Address": "10214 Monroe Ave",
        "City": "Easton",
        "State": "MD"
      },
      {
        "CustomerId": 44,
        "AccountNumber": "6837-468-4750",
        "AccountName": "Miguel Altieri",
        "AccountType": "RES",
        "Address": "10941 Patriot Blvd",
        "City": "Crenshaw",
        "County": "Jefferson",
        "State": "PA",
        "ZIPCode": "15824-6628"
      },
      {
        "CustomerId": 45,
        "AccountNumber": "2847-597-2829",
        "AccountName": "Jameson",
        "MeterNumber": "379-386-979",
        "AccountType": "WAT",
        "Address": "7373 Gold Town Rd",
        "State": "WV"
      },
      {
        "CustomerId": 46,
        "AccountNumber": "6381-748-2222",
        "AccountName": "Up Eyes",
        "AccountType": "BUS",
        "Address": "4149 Deerfield Str"
      },
      {
        "CustomerId": 47,
        "AccountNumber": "4968-274-9638",
        "AccountName": "Annette Wald",
        "AccountType": "RES",
        "Address": "11441  Eastern Friendshi Rd"
      },
      {
        "CustomerId": 48,
        "AccountNumber": "8384-708-2941",
        "AccountName": "Department of Environment Affairs",
        "AccountType": "SGO",
        "State": "OH"
      },
      {
        "CustomerId": 49,
        "AccountNumber": "3728-138-2947",
        "AccountName": "Marie Rath",
        "Address": "8802 Atlantic Ave",
        "State": "PA"
      },
      {
        "CustomerId": 50,
        "AccountNumber": "1793-857-9413",
        "AccountName": "Body Care",
        "AccountType": "WAT",
        "City": "Ocean City",
        "State": "NJ"
      },
      {
        "CustomerId": 51,
        "AccountNumber": "6028-695-2068",
        "AccountName": "Ronald Glassman",
        "MeterNumber": "468-359-486",
        "AccountType": "BUS",
      },
      {
        "CustomerId": 52,
        "AccountNumber": "4069-37-49728",
        "AccountName": "Lucette Wash N Dry",
        "AccountType": "WAT",
        "Address": "8812 Lawrence Ave",
        "State": "NW"
      },
      {
        "CustomerId": 53,
        "AccountNumber": "9616-283-7249",
        "AccountName": "Department of Public Affairs",
        "AccountType": "SGO",
        "Address": "13006 Blueberry Ave",
        "City": "Greenbelt",
        "State": "MD",
        "ZIPCode": "20770-2040"
      },
      {
        "CustomerId": 54,
        "AccountNumber": "2829-516-8353",
        "AccountName": "Richard Eghert",
        "AccountType": "RES",
        "Address": "662 Placido Road"
      },
      {
        "CustomerId": 55,
        "AccountNumber": "6296-875-9607",
        "AccountName": "Country West Eatery",
        "AccountType": "BUS",
        "Address": "837 Larrenson Drv",
        "City": "Cumberland",
        "State": "MD"
      },
      {
        "CustomerId": 56,
        "AccountNumber": "9684-794-6379",
        "AccountName": "Eye Care",
        "AccountType": "BUS",
        "Address": "8626 Cameron Str"
      },
      {
        "CustomerId": 57,
        "AccountNumber": "2405-839-5820",
        "AccountName": "Watson Country Buffet",
        "AccountType": "WAT",
        "City": "Harrisburg",
        "State": "PA"
      }
    ]

Water Bills

Introduction

A water bill is an intermediary document between the water distribution company and a consumer. We will create the classes, forms, and operations to present that information.

Practical LearningPractical Learning: Introducing Water Bills

  1. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. Type WaterBill as the Name of the file
  3. Click Add
  4. Define the class as follows:
    Public Class WaterBill
        Public Property WaterBillId As Integer
        Public Property BillNumber As Integer
        Public Property AccountNumber As String
        Public Property MeterReadingStartDate As Date
        Public Property MeterReadingEndDate As Date
        Public Property BillingDays As Integer
        Public Property CounterReadingStart As Integer
        Public Property CounterReadingEnd As Integer
        Public Property TotalHCF As Integer
        Public Property TotalGallons As Integer
        Public Property FirstTierConsumption As Double
        Public Property SecondTierConsumption As Double
        Public Property LastTierConsumption As Double
        Public Property WaterCharges As Double
        Public Property SewerCharges As Double
        Public Property EnvironmentCharges As Double
        Public Property ServiceCharges As Double
        Public Property TotalCharges As Double
        Public Property StateTaxes As Double
        Public Property LocalTaxes As Double
        Public Property PaymentDueDate As Date
        Public Property AmountDue As Double
        Public Property LatePaymentDueDate As Date
        Public Property LateAmountDue As Double
    End Class
    
  5. To create another class, in the Solution Explorer, right-click Models -> Add -> Class...
  6. Type WaterBillManager as the Name of the file
  7. Click Add
  8. Define the class as follows:
    Friend Class WaterBillManager
        Friend Shared Function CalculateTiers(Acnt As String, Total As Double) As (a As Double, b As Double, c As Double)
            Dim Results As (Tier1 As Double, Tier2 As Double, Tier3 As Double) = (0.00, 0.00, 0.00)
    
            Select Case Acnt
                Case "RES"
                    Results.Tier1 = Total * 39.35 / 10000.0
                    Results.Tier2 = Total * 18.25 / 10000.0
                    Results.Tier3 = Total * 11.65 / 10000.0
    
                Case "SGO"
                    Results.Tier1 = Total * 41.38 / 10000.0
                    Results.Tier2 = Total * 15.26 / 10000.0
                    Results.Tier3 = Total * 8.13 / 10000.0
    
                Case "BUS"
                    Results.Tier1 = Total * 51.25 / 10000.0
                    Results.Tier2 = Total * 34.65 / 10000.0
                    Results.Tier3 = Total * 15.1 / 10000.0
    
                Case "UUO"
                    Results.Tier1 = Total * 25.0 / 10000.0
                    Results.Tier2 = Total * 35.0 / 10000.0
                    Results.Tier3 = Total * 40.0 / 10000.0
    
                Case "WAT"
                    Results.Tier1 = (Total / 6) * 3 * 50.0 / 10000.0
                    Results.Tier2 = (Total / 6) * 2 * 35.0 / 10000.0
                    Results.Tier3 = Total * 15.0 / 10000.0
                Case Else
                    Results.Tier1 = Total * (48.0 / 10000.0)
                    Results.Tier2 = Total * (32.0 / 10000.0)
                    Results.Tier3 = Total * (20.0 / 10000.0)
            End Select
    
            Return Results
        End Function
    
        Friend Shared Function CalculateSewerCharges(Acnt As String, Total As Double) As Double
            Dim Result As Double
    
            If Acnt = "RES" Then
                Result = Total * 1.028641 / 100.0
            ElseIf Acnt = "SGO" Then
                Result = Total * 4.162522 / 100.0
            ElseIf Acnt = "BUS" Then
                Result = Total * 8.446369 / 100.0
            ElseIf Acnt = "UUO" Then
                Result = Total * 10.622471 / 100.0
            ElseIf Acnt = "WAT" Then
                Result = Total * 12.053152 / 100.0
            Else ' if acnt = "OTH" then
                Result = Total * 9.206252 / 100.0
            End If
    
            Return Result
        End Function
    
        Friend Shared Function CalculateEnvironmentCharges(Acnt As String, Total As Double) As Double
            Dim Result As Double
    
            Select Case Acnt
                Case "RES"
                    Result = Total * 0.004524
    
                Case "SGO"
                    Result = Total * 0.118242
    
                Case "BUS"
                    Result = Total * 0.161369
    
                Case "UUO"
                    Result = Total * 0.082477
    
                Case "WAT"
                    Result = Total * 0.413574
    
                Case Else
                    Result = Total * 0.221842
    
            End Select
    
            Return Result
        End Function
    
        Friend Shared Function CalculateServiceCharges(Acnt As String, Total As Double) As Double
            Select Case Acnt
                Case "RES"
                    Return Total * 0.006248
                Case "SGO"
                    Return Total * 0.102246
                Case "BUS"
                    Return Total * 0.155227
                Case "UUO"
                    Return Total * 0.186692
                Case "WAT"
                    Return Total * 0.412628
                Case Else
                    Return Total * 0.210248
            End Select
        End Function
    
        Friend Shared Function CalculateLocalTaxes(Acnt As String, Total As Double) As Double
            Select Case Acnt
                Case "RES"
                    Return Total * 0.035749
                Case "SGO"
                    Return Total * 0.044026
                Case "BUS"
                    Return Total * 0.122517
                Case "UUO"
                    Return Total * 0.105737
                Case "WAT"
                    Return Total * 0.153248
                Case Else
                    Return Total * 0.125148
            End Select
        End Function
    
        Friend Shared Function CalculateStateTaxes(Acnt As String, Total As Double) As Double
            Select Case Acnt
                Case "RES"
                    Return Total * 0.007124
                Case "SGO"
                    Return Total * 0.008779
                Case "BUS"
                    Return Total * 0.042448
                Case "UUO"
                    Return Total * 0.067958
                Case "WAT"
                    Return Total * 0.081622
                Case Else
                    Return Total * 0.013746
            End Select
        End Function
    
        Friend Shared Function SetPaymentDueDate(Acnt As String, Dt As Date) As Date
            Dim TsPaymentDueDate As TimeSpan = New TimeSpan(1, 0, 0, 0)
    
            If Acnt = "RES" Then
                TsPaymentDueDate = New TimeSpan(15, 0, 0, 0)
            ElseIf Acnt = "SGO" Then
                TsPaymentDueDate = New TimeSpan(20, 0, 0, 0)
            ElseIf Acnt = "BUS" Then
                TsPaymentDueDate = New TimeSpan(30, 0, 0, 0)
            ElseIf Acnt = "UUO" Then
                TsPaymentDueDate = New TimeSpan(15, 0, 0, 0)
            ElseIf Acnt = "WAT" Then
                TsPaymentDueDate = New TimeSpan(40, 0, 0, 0)
            Else
                TsPaymentDueDate = New TimeSpan(35, 0, 0, 0)
            End If
    
            Return Dt + TsPaymentDueDate
        End Function
    
        Friend Shared Function SetLatePaymentDueDate(Acnt As String, Dt As Date) As Date
            Select Case Acnt
                Case "RES"
                    Return Dt + New TimeSpan(30, 0, 0, 0)
                Case "SGO"
                    Return Dt + New TimeSpan(40, 0, 0, 0)
                Case "BUS"
                    Return Dt + New TimeSpan(50, 0, 0, 0)
                Case "UUO"
                    Return Dt + New TimeSpan(60, 0, 0, 0)
                Case "WAT"
                    Return Dt + New TimeSpan(65, 0, 0, 0)
                Case Else
                    Return Dt + New TimeSpan(45, 0, 0, 0)
            End Select
        End Function
    
        Friend Shared Function CalculateLateAmountDue(Acnt As String, Amt As Double) As Double
            Select Case Acnt
                Case "RES"
                    Return Amt + 8.95
                Case "SGO"
                    Return Amt + (Amt / 4.575)
                Case "BUS"
                    Return Amt + (Amt / 12.315)
                Case "UUO"
                    Return Amt + (Amt / 7.425)
                Case "WAT"
                    Return Amt + (Amt / 15.225)
                Case Else
                    Return Amt + (Amt / 6.735)
            End Select
        End Function
    End Class

Showing Water Bills

A water distribution company has many records for water bills, and a typical water bill includes many pieces of information. We will create a form that displays a list of some pieces of information about a water bill.

Practical LearningPractical Learning: Showing Water Bills

  1. To create a form, in the Solution Explorer, right-click WaterBills -> Add -> Form (Windows Forms)...
  2. For the Name of the form, type Central
  3. Click Add
  4. In the Toolbox, click the ListView button and click the form
  5. On the form, right-click the list view and click Edit Columns...
  6. Create the columns as follows:
    (Name) Text TextAlign Width
    ColWaterBillId Id   40
    ColBillNumber Bill # Center 80
    ColAccountSummary Account Summary   550
    ColStartDate Start Date Center 150
    ColEndDate End Date Center 150
    ColBillingDays Days Center  
    ColCounterStart Counter Start Right 125
    ColCounterEnd Counter End Right 125
    ColTotalHCF Total HCF Right 100
    ColGallons Gallons Right 95
    ColPaymentDueDate Pmt Due Date Center 125
    ColAmountDue Amt Due Right 90
  7. Click OK
  8. Position and resize the list view on the form as follows:

    Stellar Water Point - Water Bills

    Control (Name) Other Properties
    ListView List View LvwWaterBills FullRowSelect: True
    GridLines: True
    View: Details
  9. Right-click an area of the form and click View Code
  10. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterBillsCentral
        Private Sub ShowWaterBills()
            Dim StrCustomers = Nothing
            Dim StrWaterBills = Nothing
            Dim StrAccountsTypes = Nothing
    
            Dim AccountsTypes = New List(Of AccountType)
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
    
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
    
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
                End Using
            End If
    
            Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
            StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
            AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
            Dim StrAccountSummary As String
    
            If FiWaterBills.Exists = True Then
                Using TrWaterBills As TextReader = New StreamReader(FiWaterBills.FullName)
                    StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
    
                    WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                    LvwWaterBills.Items.Clear()
    
                    For Each Invoice As WaterBill In WaterBills
                        Dim LviWaterBill As ListViewItem = New ListViewItem(Invoice.WaterBillId)
    
                        LviWaterBill.SubItems.Add(Invoice.BillNumber)
    
                        Dim Client As IEnumerable(Of Customer) = Clients.Where(Function(Cust) Cust.AccountNumber = Invoice.AccountNumber)
    
                        StrAccountSummary = Invoice.AccountNumber
    
                        For Each Cust In Clients
                            If Cust.AccountNumber = Invoice.AccountNumber Then
    
                                For Each ActType As AccountType In AccountsTypes
                                    If Cust.AccountType = ActType.TypeCode Then
                                        StrAccountSummary = StrAccountSummary & " - " &
                                                            Cust.AccountName & ", Acnt Type: " & String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription) &
                                                            ", (Mtr #: " & Cust.MeterNumber & ")"
                                    End If
                                Next
                            End If
                        Next
    
                        For Each Cust As Customer In Clients
                            LviWaterBill.SubItems.Add(StrAccountSummary)
    
                            LviWaterBill.SubItems.Add(Invoice.MeterReadingStartDate.ToShortDateString())
                            LviWaterBill.SubItems.Add(Invoice.MeterReadingEndDate.ToShortDateString())
                            LviWaterBill.SubItems.Add(Invoice.BillingDays)
                            LviWaterBill.SubItems.Add(Invoice.CounterReadingStart)
                            LviWaterBill.SubItems.Add(Invoice.CounterReadingEnd)
                            LviWaterBill.SubItems.Add(Invoice.TotalHCF)
                            LviWaterBill.SubItems.Add(Invoice.TotalGallons)
                            LviWaterBill.SubItems.Add(Invoice.PaymentDueDate.ToShortDateString())
                            LviWaterBill.SubItems.Add(Invoice.AmountDue)
                        Next
    
                        LvwWaterBills.Items.Add(LviWaterBill)
                    Next
                End Using
            End If
        End Sub
    
        Private Sub WaterBillsCentral_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ShowWaterBills()
        End Sub
    End Class
  11. In the Solution Explorer, double-click WaterDistribution.vb to display the main form of the application
  12. From the Toolbox, add two buttons to the form
  13. From the Properties window, change the characteristics of the button as follows:

    Stellar Water Point

    Control (Name) Text Font
    Button Button BtnWaterBills C&Water Bills... Times New Roman, 24pt, style=Bold
    Button Button BtnClose &Close Times New Roman, 24pt, style=Bold
  14. Right-click any area of the form and click View Code
  15. Impliment an event for the new button as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterDistribution
        Private Sub CreateWaterMeters()
            . . .
    
        End Sub
    
        Private Sub CreateAccountsTypes()
            . . .
        End Sub
        Private Sub WaterDistribution_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            REM Directory.CreateDirectory("C:\Stellar Water Point16")
    
            REM CreateWaterMeters()
            REM CreateAccountsTypes()
        End Sub
    
        Private Sub BtnWaterBills_Click(sender As Object, e As EventArgs) Handles BtnWaterBills.Click
            Dim Central = New WaterBillsCentral()
    
            Central.Show()
        End Sub
    
        Private Sub BtnCustomers_Click(sender As Object, e As EventArgs) Handles BtnCustomers.Click
            Dim Central = New CustomersCentral
    
            Central.Show()
        End Sub
    
        Private Sub BtnWaterMeters_Click(sender As Object, e As EventArgs) Handles BtnWaterMeters.Click
            Dim Central = New WaterMetersCentral()
    
            Central.Show()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class

A New Water Bill

A water is probably the most important aspect of water distribution. We will provide a form that allows an employee to register the information necessary for water consumption. Then we will perform some operations. Finally, we will present the amount the consumer should pay and when.

Practical LearningPractical Learning: Processing a Water Bill

  1. To create a form, in the Solution Explorer, right-click WaterBills -> Add -> Form (Windows Forms)...
  2. Set the name to Create
  3. Click Add
  4. Design the form as follows:

    Stellar Water Point - New Water Bill

    Control Text Name Other Properties
    Label Label &Water Bill #:    
    TextBox Text Box   TxtBillNumber  
    GroupBox Group Box Customer Information    
    Label Label &Account #:    
    MaskedTextBox Masked Text Box   MtbAccountNumber Mask: 0000-000-0000
    Button Button Find Customer &Account BtnFindCustomerAccount  
    Label Label Account Name:    
    TextBox Text Box   TxtAccountName  
    Label Label Account Type:    
    TextBox Text Box   TxtAccountType  
    Label Label Address:    
    TextBox Text Box   TxtAddress  
    TextBox Text Box   TxtCity  
    TextBox Text Box   TxtCounty  
    TextBox Text Box   TxtState  
    TextBox Text Box   TxtZIPCode  
    Label Label ___________________________    
    Label Label Meter Details:    
    TextBox Text Box   TxtMeterDetails  
    GroupBox Group Box Meter Reading    
    Label Label Meter &Reading Start Date:    
    Date Time Picker Text Box   DtpMeterReadingStartDate  
    Label Label Meter Reading &End Date:    
    Date Time Picker Text Box   DtpMeterReadingEndDate  
    Label Label Coun&ter Reading Start:    
    TextBox Text Box   TxtCounterReadingStart  
    Label Label Counter Readi&ng End:    
    TextBox Text Box   TxtCounterReadingEnd  
    Button Button &Evaluate Water Bill BtnEvaluateWaterBill Times New Roman, 24pt, style=Bold
    GroupBox Group Box Meter Result    
    Label Label Billing Days:    
    TextBox Text Box   TxtBillingDays  
    Label Label Total HCF:    
    TextBox Text Box   TxtTotalHCF  
    Label Label Total Gallons:    
    TextBox Text Box   TxtTotalGallons  
    Label Label First Tier Consumption:    
    TextBox Text Box   TxtFirstTierConsumption  
    Label Label Second Tier:    
    TextBox Text Box   TxtSecondTierConsumption  
    Label Label Last Tier:    
    TextBox Text Box   TxtLastTierConsumption  
    GroupBox Group Box Consumption Charges    
    Label Label Water Charges:    
    TextBox Text Box   TxtWaterCharges  
    Label Label Sewer Charges:    
    TextBox Text Box   TxtSewerCharges  
    Label Label Environment Charges:    
    TextBox Text Box   TxtEnvironmentCharges  
    Label Label Service Charges:    
    TextBox Text Box   TxtServiceCharges  
    Label Label Total Charges:    
    TextBox Text Box   TxtTotalCharges  
    GroupBox Group Box Taxes    
    Label Label Local Taxes:    
    TextBox Text Box   TxtLocalTaxes  
    Label Label State Taxes:    
    TextBox Text Box   TxtStateTaxes  
    GroupBox Group Box Water Bill Payment    
    Label Label Payment Due Date:    
    Date Time Picker Text Box   dtpPaymentDueDate  
    Label Label Amount Due:    
    TextBox Text Box   TxtAmountDue  
    Label Label Late Payment Due Date:    
    Date Time Picker Text Box   dtpLatePaymentDueDate  
    Label Label &Late Amount Due:    
    TextBox Text Box   TxtLateAmountDue  
    Label Label Water Bill Id:&    
    TextBox Text Box   TxtWaterBillId  
    Button Button Save Water Bill BtnSaveWaterBill  
    Button Button &Close BtnClose  

    Form Properties

    Form Property Value
    FormBorderStyle FixedDialog
    Text Stellar Water Point - Water Bill Processing
    StartPosition CenterScreen
    MaximizeBox False
    MinimizeBox False
  5. Right-click an area of the form and click View Code
  6. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterBillsCreate
        Private Sub WaterBillsCreate_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim StrWaterBills = Nothing
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
            Dim fileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiWaterBills As FileInfo = New FileInfo(fileWaterBills)
    
            Dim waterBillId = 0
    
            If FiWaterBills.Exists = True Then
                Using TrWaterBills As TextReader = New StreamReader(FiWaterBills.FullName)
                    StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
                    WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                    For Each Bill As WaterBill In WaterBills
                        waterBillId = Bill.WaterBillId
                    Next
                End Using
            End If
    
            TxtWaterBillId.Text = CStr(waterBillId + 1)
        End Sub
    
        Private Sub BtnFindCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnFindCustomerAccount.Click
            If String.IsNullOrEmpty(MtbAccountNumber.Text) Then
                MsgBox("You must type a valid account number of a customer, " &
                       "and then click the Find Customer Account button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers = Nothing
            Dim StrAccountsTypes = Nothing
            Dim AccountsTypes = New List(Of AccountType)
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            Dim StrMeterNumber = Nothing
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim customers As IEnumerable(Of Customer) = Clients.Where(Function(Client) Client.AccountNumber = MtbAccountNumber.Text)
    
                    For Each Client As Customer In customers
                        TxtAccountName.Text = Client.AccountName
                        StrMeterNumber = Client.MeterNumber
    
                        Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
                        StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                        AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                        For Each ActType As AccountType In AccountsTypes
                            If Client.AccountType = ActType.TypeCode Then
                                TxtAccountType.Text = String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription)
                            End If
                        Next
    
                        TxtAddress.Text = Client.Address
                            TxtCity.Text = Client.City
                            TxtCounty.Text = Client.County
                            TxtState.Text = Client.State
                            TxtZIPCode.Text = Client.ZIPCode
                        Next
                End Using
            End If
    
            If Len(StrMeterNumber) > 0 Then
                Dim StrWaterMeters As String = Nothing
                Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
                Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
                Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
                If FiWaterMeters.Exists = True Then
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
    
                    Dim Meters As IEnumerable(Of WaterMeter) = WaterMeters.Where(Function(Mtr) Mtr.MeterNumber = StrMeterNumber)
    
                    For Each Meter As WaterMeter In Meters
                        TxtMeterDetails.Text = Meter.WaterMeterId & " - " &
                                               Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    Next
                End If
            End If
        End Sub
    
        Private Sub DtpMeterReadingEndDate_ValueChanged(sender As Object, e As EventArgs) Handles DtpMeterReadingEndDate.ValueChanged
            TxtBillingDays.Text = DateDiff(DateInterval.Day, DtpMeterReadingStartDate.Value, DtpMeterReadingEndDate.Value) + 1
        End Sub
    
        Private Sub BtnEvaluateWaterBill_Click(sender As Object, e As EventArgs) Handles BtnEvaluateWaterBill.Click
            Dim CounterStart As Double = 0, CounterEnd = 0
    
            Try
                CounterStart = CDbl(TxtCounterReadingStart.Text)
            Catch FeCRStart As FormatException
                MsgBox("You must enter a valid value in the Counter Reading Start text box. " &
                       "The error produced is: " & FeCRStart.Message,
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
            End Try
    
            Try
                counterEnd = CDbl(TxtCounterReadingEnd.Text)
            Catch FeCREnd As FormatException
                MsgBox("You must enter a valid value in the Counter Reading End text box. " &
                       "The error produced is: " & FeCREnd.Message,
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
            End Try
    
            Dim Consumption As Double = CounterEnd - CounterStart
            Dim Gallons As Double = Consumption * 748.05
            Dim StrAccountType As String = TxtAccountType.Text.Substring(1, 3)
    
            Dim Tiers As (first As Double, second As Double, last As Double) = WaterBillManager.CalculateTiers(strAccountType, gallons)
    
            Dim WaterCharges = Tiers.first + Tiers.second + Tiers.last
            Dim SewerCharges = WaterBillManager.CalculateSewerCharges(StrAccountType, WaterCharges)
            Dim EnvCharges = WaterBillManager.CalculateEnvironmentCharges(StrAccountType, WaterCharges)
            Dim SrvCharges = WaterBillManager.CalculateServiceCharges(StrAccountType, WaterCharges)
            Dim TotalCharges = WaterCharges + SewerCharges + EnvCharges + SrvCharges
            Dim LocalTaxes = WaterBillManager.CalculateLocalTaxes(StrAccountType, WaterCharges)
            Dim StateTaxes = WaterBillManager.CalculateStateTaxes(StrAccountType, WaterCharges)
            Dim AmtDue = TotalCharges + LocalTaxes + StateTaxes
    
            TxtTotalHCF.Text = consumption.ToString()
            TxtTotalGallons.Text = Math.Ceiling(Gallons)
            TxtFirstTierConsumption.Text = FormatNumber(Tiers.first)
            TxtSecondTierConsumption.Text = FormatNumber(Tiers.second)
            TxtLastTierConsumption.Text = FormatNumber(Tiers.last)
            TxtWaterCharges.Text = FormatNumber(WaterCharges)
            TxtSewerCharges.Text = FormatNumber(SewerCharges)
            TxtEnvironmentCharges.Text = FormatNumber(EnvCharges)
            TxtServiceCharges.Text = FormatNumber(SrvCharges)
            TxtTotalCharges.Text = FormatNumber(TotalCharges)
            TxtLocalTaxes.Text = FormatNumber(LocalTaxes)
            TxtStateTaxes.Text = FormatNumber(StateTaxes)
            DtpPaymentDueDate.Value = WaterBillManager.SetPaymentDueDate(strAccountType, dtpMeterReadingEndDate.Value)
            TxtAmountDue.Text = FormatNumber(AmtDue)
            DtpLatePaymentDueDate.Value = WaterBillManager.SetLatePaymentDueDate(strAccountType, dtpMeterReadingEndDate.Value)
            TxtLateAmountDue.Text = FormatNumber(WaterBillManager.CalculateLateAmountDue(StrAccountType, AmtDue))
        End Sub
    
        Private Sub BtnSaveWaterBill_Click(sender As Object, e As EventArgs) Handles BtnSaveWaterBill.Click
            If String.IsNullOrEmpty(TxtWaterBillNumber.Text) Then
                MsgBox("You must type a (unique) bill number for the " &
                       "water bill you are processing.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            If String.IsNullOrEmpty(MtbAccountNumber.Text) Then
                MsgBox("You must specify the account number of the customer " &
                       "whose water bill you are preparing.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrWaterBills As String = Nothing
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
    
            If FiWaterBills.Exists = True Then
                StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
                WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
            End If
    
            Dim Bill As WaterBill = New WaterBill() With
            {
            .WaterBillId = TxtWaterBillId.Text,
                .BillNumber = TxtWaterBillNumber.Text,
     .AccountNumber = MtbAccountNumber.Text,
      .MeterReadingStartDate = DtpMeterReadingStartDate.Value,
       .MeterReadingEndDate = DtpMeterReadingEndDate.Value,
        .BillingDays = TxtBillingDays.Text,
         .CounterReadingStart = TxtCounterReadingStart.Text,
          .CounterReadingEnd = TxtCounterReadingEnd.Text,
           .TotalHCF = TxtTotalHCF.Text,
            .TotalGallons = TxtTotalGallons.Text,
             .FirstTierConsumption = TxtFirstTierConsumption.Text,
              .SecondTierConsumption = TxtSecondTierConsumption.Text,
               .LastTierConsumption = TxtLastTierConsumption.Text,
                .WaterCharges = TxtWaterCharges.Text,
                 .SewerCharges = TxtSewerCharges.Text,
                  .EnvironmentCharges = TxtEnvironmentCharges.Text,
                   .ServiceCharges = TxtServiceCharges.Text,
                    .TotalCharges = TxtTotalCharges.Text,
         .LocalTaxes = TxtLocalTaxes.Text,
        .StateTaxes = TxtStateTaxes.Text,
       .PaymentDueDate = DtpPaymentDueDate.Value,
      .AmountDue = TxtAmountDue.Text,
     .LatePaymentDueDate = DtpLatePaymentDueDate.Value,
    .LateAmountDue = TxtLateAmountDue.Text
                }
    
            WaterBills.Add(Bill)
    
            Dim Options As JsonSerializerOptions = New JsonSerializerOptions()
            Options.WriteIndented = True
    
            Dim JsWaterBills = JsonSerializer.Serialize(WaterBills, GetType(List(Of WaterBill)), Options)
            File.WriteAllText(FiWaterBills.FullName, JsWaterBills)
    
            Close()
        End Sub
    
        Private sub BtnClose_Click(sender As Object, e As EventArgs) handles btnclose.click
                Close()
            end sub
    End Class
  7. In the Solution Explorer, below the WaterBills folder, double-click Central.vb
  8. From the Toolbox, add a button to the form below the list view
  9. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View LvwWaterBills No Change
    Button Button BtnProcessWaterBill &Process Water Bill...
  10. On the Central form, double-click the Process Water Bill button
  11. Implement the event as follows:
    Private Sub BtnProcessWaterBill_Click(sender As Object, e As EventArgs) Handles BtnProcessWaterBill.Click
        Dim Create As WaterBillsCreate = New WaterBillsCreate
    
        Create.ShowDialog()
    
        ShowWaterBills()
    End Sub
  12. To execute the application, on the main menu, click Debug -> Start Without Debugging:

    Stellar Water Point

  13. On the Water Distribution form, click the Water Bills button:

    Stellar Water Point - Water Bills

  14. On the Water Bills form, click the Create Water Bill button:

    Stellar Water Point - Create Water Bill

  15. Enter the following values in the indicated text boxes or select the date values. Then click Find Customer Account, followed by Evaluate Water Bill, followed by Save Water Bill:

    Stellar Water Point - Create Water Bill

    Stellar Water Point - Create Water Bill

    Water Bill # Account # Reading Start Date Reading End Date Counter Reading Start Counter Reading End
    451474 2068-258-9486 01/11/2010 04/12/2010 103943 103956
    923633 5293-957-3395 01/17/2010 08/18/2010 256945 256972
    917829 9279-570-8394 02/15/2010 05/14/2010 5205 5222
    202666 6986-829-3741 03/08/2010 06/06/2010 5679 5690

    Stellar Water Point - Water Bills

  16. Close the forms and return to your programming environment

Water Bill Details

Sometimes, an employee just wants to view the information that is related to a water bill. We will create a form to make it possible.

Practical LearningPractical Learning: Showing a Water Bill

  1. To create a form, in the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms)...
  2. For the Name of the form, type WaterBillsDetails
  3. Press Enter
  4. Design the form as follows:

    Stellar Water Point - New Water Bill

    Control Text Name Enabled
    Label Label &Water Bill #:    
    TextBox Text Box   TxtBillNumber  
    Button Button &Find Water Bill BtnFindWaterBill  
    GroupBox Group Box Customer Information    
    Label Label &Account #:    
    TextBox Text Box   TxtAccountNumber False
    Label Label Account Name:    
    TextBox Text Box   TxtAccountName False
    Label Label Account Type:    
    TextBox Text Box   TxtAccountType  
    Label Label Address:   False
    TextBox Text Box   TxtAddress False
    TextBox Text Box   TxtCity  
    TextBox Text Box   TxtCounty False
    TextBox Text Box   TxtState False
    TextBox Text Box   TxtZIPCode False
    Label Label _______________________________    
    Label Label Meter Details:    
    TextBox Text Box   TxtMeterDetails False
    GroupBox Group Box Meter Reading    
    Label Label Meter &Reading Start Date:    
    Text Box Text Box   TxtMeterReadingStartDate False
    Label Label Meter Reading &End Date:    
    Text Box Text Box   TxtMeterReadingEndDate False
    Label Label Coun&ter Reading Start:    
    TextBox Text Box   TxtCounterReadingStart False
    Label Label Counter Readi&ng End:    
    TextBox Text Box   TxtCounterReadingEnd False
    GroupBox Group Box Meter Result    
    Label Label Billing Days:    
    TextBox Text Box   TxtBillingDays False
    Label Label Total HCF:    
    TextBox Text Box   TxtTotalHCF False
    Label Label Total Gallons:    
    TextBox Text Box   TxtTotalGallons False
    Label Label First Tier Consumption:    
    TextBox Text Box   TxtFirstTierConsumption False
    Label Label Second Tier:    
    TextBox Text Box   TxtSecondTierConsumption False
    Label Label Last Tier:    
    TextBox Text Box   TxtLastTierConsumption False
    GroupBox Group Box Consumption Charges    
    Label Label Water Charges:    
    TextBox Text Box   TxtWaterCharges False
    Label Label Sewer Charges:    
    TextBox Text Box   TxtSewerCharges False
    Label Label Environment Charges:    
    TextBox Text Box   TxtEnvironmentCharges False
    Label Label Service Charges:    
    TextBox Text Box   TxtServiceCharges False
    Label Label Total Charges:    
    TextBox Text Box   TxtTotalCharges False
    GroupBox Group Box Taxes    
    Label Label Local Taxes:    
    TextBox Text Box   TxtLocalTaxes False
    Label Label State Taxes:    
    TextBox Text Box   TxtStateTaxes False
    GroupBox Group Box Water Bill Payment    
    Label Label Payment Due Date:    
    Date Time Picker Text Box   dtpPaymentDueDate False
    Label Label Amount Due:    
    TextBox Text Box   TxtAmountDue False
    Label Label Late Payment Due Date:    
    Text Box Text Box   TxtLatePaymentDueDate False
    Label Label &Late Amount Due:    
    TextBox Text Box   TxtLateAmountDue  
    Label Label Water Bill Id:    
    TextBox Text Box   TxtWaterBillId False
    Button Button &Close BtnClose  

    Form Properties

    Form Property Value
    FormBorderStyle FixedDialog
    Text Stellar Water Point - Water Bill Details
    StartPosition CenterScreen
    MaximizeBox False
    MinimizeBox False
  5. Right-click anywhere on the form and click View Code
  6. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterBillsDetails
        Private Sub BtnFindWaterBill_Click(sender As Object, e As EventArgs) Handles BtnFindWaterBill.Click
            If String.IsNullOrEmpty(TxtWaterBillNumber.Text) Then
                MsgBox("You must provide a water bill number and then click the Find Water Bill button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                REM If the user didn't type a bill number but clicked Find Water Bill, don't do anything
                Exit Sub
            End If
    
            Dim StrWaterBills As String = Nothing
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
    
            Dim StrAccountsTypes As String = Nothing
            Dim AccountsTypes = New List(Of AccountType)
            Dim FileAccountsTypes As String = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If fiWaterBills.Exists = True Then
                Using TrWaterBills As TextReader = New StreamReader(fiWaterBills.FullName)
                    StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
                    WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                    Dim Selected As IEnumerable(Of WaterBill) = WaterBills.Where(Function(Invoice) Invoice.BillNumber = TxtWaterBillNumber.Text)
    
                    For Each Bill In Selected
                        TxtWaterBillId.Text = Bill.WaterBillId
                        TxtAccountNumber.Text = Bill.AccountNumber
                        TxtMeterReadingStartDate.Text = FormatDateTime(Bill.MeterReadingStartDate, DateFormat.LongDate)
                        TxtMeterReadingEndDate.Text = FormatDateTime(Bill.MeterReadingEndDate, DateFormat.LongDate)
                        TxtBillingDays.Text = Bill.BillingDays
                        TxtCounterReadingStart.Text = Bill.CounterReadingStart
                        TxtCounterReadingEnd.Text = Bill.CounterReadingEnd
                        TxtTotalHCF.Text = Bill.TotalHCF
                        TxtTotalGallons.Text = Bill.TotalGallons
                        TxtFirstTierConsumption.Text = FormatNumber(Bill.FirstTierConsumption)
                        TxtSecondTierConsumption.Text = FormatNumber(Bill.SecondTierConsumption)
                        TxtLastTierConsumption.Text = FormatNumber(Bill.LastTierConsumption)
                        TxtWaterCharges.Text = FormatNumber(Bill.WaterCharges)
                        TxtSewerCharges.Text = FormatNumber(Bill.SewerCharges)
                        TxtEnvironmentCharges.Text = FormatNumber(Bill.EnvironmentCharges)
                        TxtServiceCharges.Text = FormatNumber(Bill.ServiceCharges)
                        TxtTotalCharges.Text = FormatNumber(Bill.TotalCharges)
                        TxtLocalTaxes.Text = FormatNumber(Bill.LocalTaxes)
                        TxtStateTaxes.Text = FormatNumber(Bill.StateTaxes)
                        TxtPaymentDueDate.Text = FormatDateTime(Bill.PaymentDueDate, DateFormat.LongDate)
                        TxtAmountDue.Text = FormatNumber(Bill.AmountDue)
                        TxtLatePaymentDueDate.Text = FormatDateTime(Bill.LatePaymentDueDate, DateFormat.LongDate)
                        TxtLateAmountDue.Text = FormatNumber(Bill.LateAmountDue)
                    Next
                End Using
            End If
    
            Dim StrCustomers = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            Dim StrMeterNumber = Nothing
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim Customers As IEnumerable(Of Customer) = From Consumer
                                                                In Clients
                                                                Where Consumer.AccountNumber = TxtAccountNumber.Text
                                                                Select Consumer
    
                    For Each Client As Customer In Customers
                        TxtAccountName.Text = Client.AccountName
                        StrMeterNumber = Client.MeterNumber
    
                        Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
                        StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                        AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                        For Each ActType As AccountType In AccountsTypes
                            If Client.AccountType = ActType.TypeCode Then
                                TxtAccountType.Text = String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription)
                            End If
                        Next
    
                        TxtAddress.Text = Client.Address
                        TxtCity.Text = Client.City
                        TxtCounty.Text = Client.County
                        TxtState.Text = Client.State
                        TxtZIPCode.Text = Client.ZIPCode
                    Next
                End Using
            End If
    
            If Len(StrMeterNumber) > 0 Then
                Dim StrWaterMeters As String = Nothing
                Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
                Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
                Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
                If FiWaterMeters.Exists = True Then
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
    
                    Dim Meters As IEnumerable(Of WaterMeter) = From Measure
                                                               In WaterMeters
                                                               Where Measure.MeterNumber = StrMeterNumber
                                                               Select Measure
    
                    For Each Meter As WaterMeter In Meters
                        TxtMeterDetails.Text = Meter.WaterMeterId & " - " &
                                               Meter.MeterNumber & " - " &
                                               Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    Next
                End If
            End If
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  7. In the Solution Explorer, below the WaterBills folder, double-click Central.vb to open its form
  8. From the Toolbox, add a button to the form below the list view and to the right of the New Water Bill button
  9. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View LvwWaterBills No Change
    Button Button No Change No Change
    Button Button BtnWaterBillDetails Water Bill &Details...
  10. Double-click the Water Bill &Details button
  11. Change the document as follows:
    Private Sub BtnWaterBillsDetails(ByVal sender As Object, e As EventArgs) Handles BtnWaterBillDetails.Click
        Dim Details As WaterBillsDetails = New WaterBillsDetails
    
        Details.ShowDialog()
    
        ShowWaterBills()
    End Sub
  12. To execute the application, on the main menu, click Debug -> Start Without Debugging

    Stellar Water Point

  13. On the Water Distribution form, click the Water Bills button:

    Stellar Water Point - Customers

  14. On the Water Bills form, click the View Water Bill button:

    Stellar Water Point - View Water Bill

  15. In the Water Bill # text box, type 917829
  16. Click the Find Water Bill button:

    Stellar Water Point - View Water Bill

  17. Close the forms and return to your programming environment

Water Bill Edition

If some aspect of a water bill changes, we will create a form that an employee can use to update the record.

Practical LearningPractical Learning: Creating a Water Bill Editor

  1. In the Solution Explorer, right-click StellarWaterPoint2 -> Add -> Form (Windows Forms...)
  2. Set the name of the form to WaterBillsEditor
  3. Click Add
  4. Using the Properties window, change the size of the new form to match the size of the WaterBillsCreate form
  5. Select everything in the Process Water Bill form and copy it
  6. Paste it in Water Bill Editor form
  7. Change the design of the Water Bill Editor form as follows (you will add only the controls that are not found in the New Water Bill form):

    Stellar Water Point - Water Bill Editor

    Control (Name) Text
    Button Button BtnFindWaterBill &Find Water Bill
    Button Button BtnUpdateWaterBill &Update Water Bill
  8. Right-click any section of the form and click View Code
  9. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterBillsEditor
        Private Sub BtnFindWaterBill_Click(sender As Object, e As EventArgs) Handles BtnFindWaterBill.Click
            If String.IsNullOrEmpty(TxtWaterBillNumber.Text) Then
                MsgBox("You must provide a water bill number and then click the Find Water Bill button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                REM If the user didn't type a bill number but clicked Find Water Bill, don't do anything
                Exit Sub
            End If
    
            Dim StrWaterBills = Nothing
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
    
            Dim StrAccountsTypes As String = Nothing
            Dim AccountsTypes = New List(Of AccountType)
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiWaterBills.Exists = True Then
                Using TrWaterBills As TextReader = New StreamReader(FiWaterBills.FullName)
                    StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
                    WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                    Dim Selected As IEnumerable(Of WaterBill) = WaterBills.Where(Function(Bill) Bill.BillNumber = TxtWaterBillNumber.Text)
    
                    For Each Bill In Selected
                        TxtWaterBillId.Text = Bill.WaterBillId
                        MtbAccountNumber.Text = Bill.AccountNumber
                        DtpMeterReadingStartDate.Value = Bill.MeterReadingStartDate
                        DtpMeterReadingEndDate.Value = Bill.MeterReadingEndDate
                        TxtBillingDays.Text = Bill.BillingDays
                        TxtCounterReadingStart.Text = Bill.CounterReadingStart
                        TxtCounterReadingEnd.Text = Bill.CounterReadingEnd
                        TxtTotalHCF.Text = Bill.TotalHCF
                        TxtTotalGallons.Text = Bill.TotalGallons
                        TxtFirstTierConsumption.Text = FormatNumber(Bill.FirstTierConsumption)
                        TxtSecondTierConsumption.Text = FormatNumber(Bill.SecondTierConsumption)
                        TxtLastTierConsumption.Text = FormatNumber(Bill.LastTierConsumption)
                        TxtWaterCharges.Text = FormatNumber(Bill.WaterCharges)
                        TxtSewerCharges.Text = FormatNumber(Bill.SewerCharges)
                        TxtEnvironmentCharges.Text = FormatNumber(Bill.EnvironmentCharges)
                        TxtServiceCharges.Text = FormatNumber(Bill.ServiceCharges)
                        TxtTotalCharges.Text = FormatNumber(Bill.TotalCharges)
                        TxtLocalTaxes.Text = FormatNumber(Bill.LocalTaxes)
                        TxtStateTaxes.Text = FormatNumber(Bill.StateTaxes)
                        DtpPaymentDueDate.Value = Bill.PaymentDueDate
                        TxtAmountDue.Text = FormatNumber(Bill.AmountDue)
                        DtpLatePaymentDueDate.Value = Bill.LatePaymentDueDate
                        TxtLateAmountDue.Text = FormatNumber(Bill.LateAmountDue)
                    Next
                End Using
            End If
    
            Dim StrCustomers = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            Dim StrMeterNumber = Nothing
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
    
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim Customers As IEnumerable(Of Customer) = From Consumer
                                                                In Clients
                                                                Where Consumer.AccountNumber = MtbAccountNumber.Text
                                                                Select Consumer
    
                    For Each Client As Customer In Customers
                        TxtAccountName.Text = Client.AccountName
                        StrMeterNumber = Client.MeterNumber
    
                        Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
                        StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                        AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                        For Each ActType As AccountType In AccountsTypes
                            If Client.AccountType = ActType.TypeCode Then
                                TxtAccountType.Text = String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription)
                            End If
                        Next
    
                        TxtAddress.Text = Client.Address
                        TxtCity.Text = Client.City
                        TxtCounty.Text = Client.County
                        TxtState.Text = Client.State
                        TxtZIPCode.Text = Client.ZIPCode
                    Next
                End Using
            End If
    
            Dim StrWaterMeters As String = Nothing
            Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If FiWaterMeters.Exists = True Then
                StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
    
                Dim Meters As IEnumerable(Of WaterMeter) = From Measure
                                                           In WaterMeters
                                                           Where Measure.MeterNumber = StrMeterNumber
                                                           Select Measure
    
                For Each Meter As WaterMeter In Meters
                    TxtMeterDetails.Text = Meter.WaterMeterId & " - " &
                                           Meter.Make & " " &
                                           Meter.Model &
                                           " (Meter Size: " & Meter.MeterSize & ")"
                Next
            End If
        End Sub
    
        Private Sub BtnFindCustomerAccount_Click(sender As Object, e As EventArgs) Handles BtnFindCustomerAccount.Click
            If String.IsNullOrEmpty(MtbAccountNumber.Text) Then
                MsgBox("You must type a valid account number of a customer, " &
                       "and then click the Find Customer Account button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrCustomers = Nothing
            Dim StrAccountsTypes = Nothing
            Dim AccountsTypes = New List(Of AccountType)
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            Dim StrMeterNumber = "Nothing"
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim customers As IEnumerable(Of Customer) = Clients.Where(Function(Client) Client.AccountNumber = MtbAccountNumber.Text)
    
                    For Each Client As Customer In customers
                        TxtAccountName.Text = Client.AccountName
                        StrMeterNumber = Client.MeterNumber
    
                        Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
                        StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                        AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                        For Each ActType As AccountType In AccountsTypes
                            If Client.AccountType = ActType.TypeCode Then
                                TxtAccountType.Text = String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription)
                            End If
                        Next
    
                        TxtAddress.Text = Client.Address
                        TxtCity.Text = Client.City
                        TxtCounty.Text = Client.County
                        TxtState.Text = Client.State
                        TxtZIPCode.Text = Client.ZIPCode
                    Next
                End Using
            End If
    
            Dim StrWaterMeters As String = Nothing
            Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
            Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
            Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
            If Len(StrMeterNumber) > 0 Then
    
                If FiWaterMeters.Exists = True Then
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
    
                    Dim Meters As IEnumerable(Of WaterMeter) = WaterMeters.Where(Function(Mtr) Mtr.MeterNumber = StrMeterNumber)
    
                    For Each Meter As WaterMeter In Meters
                        TxtMeterDetails.Text = Meter.WaterMeterId & " - " &
                                               Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    Next
                End If
            End If
        End Sub
    
        Private Sub DtpMeterReadingEndDate_ValueChanged(sender As Object, e As EventArgs) Handles DtpMeterReadingEndDate.ValueChanged
            TxtBillingDays.Text = DateDiff(DateInterval.Day, DtpMeterReadingStartDate.Value, DtpMeterReadingEndDate.Value) + 1
        End Sub
    
        Private Sub BtnEvaluateWaterBill_Click(sender As Object, e As EventArgs) Handles BtnEvaluateWaterBill.Click
            Dim CounterStart As Double = 0, CounterEnd = 0
    
            Try
                CounterStart = CDbl(TxtCounterReadingStart.Text)
            Catch FeCRStart As FormatException
                MsgBox("You must enter a valid value in the Counter Reading Start text box. " &
                       "The error produced is: " & FeCRStart.Message,
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
            End Try
    
            Try
                CounterEnd = CDbl(TxtCounterReadingEnd.Text)
            Catch FeCREnd As FormatException
                MsgBox("You must enter a valid value in the Counter Reading End text box. " &
                       "The error produced is: " & FeCREnd.Message,
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
            End Try
    
            Dim Consumption As Double = CounterEnd - CounterStart
            Dim Gallons As Double = Consumption * 748.05
            Dim StrAccountType As String = TxtAccountType.Text.Substring(1, 3)
    
            Dim Tiers As (first As Double, second As Double, last As Double) = WaterBillManager.CalculateTiers(StrAccountType, Gallons)
    
            Dim WaterCharges = Tiers.first + Tiers.second + Tiers.last
            Dim SewerCharges = WaterBillManager.CalculateSewerCharges(StrAccountType, WaterCharges)
            Dim EnvCharges = WaterBillManager.CalculateEnvironmentCharges(StrAccountType, WaterCharges)
            Dim SrvCharges = WaterBillManager.CalculateServiceCharges(StrAccountType, WaterCharges)
            Dim TotalCharges = WaterCharges + SewerCharges + EnvCharges + SrvCharges
            Dim LocalTaxes = WaterBillManager.CalculateLocalTaxes(StrAccountType, WaterCharges)
            Dim StateTaxes = WaterBillManager.CalculateStateTaxes(StrAccountType, WaterCharges)
            Dim AmtDue = TotalCharges + LocalTaxes + StateTaxes
    
            TxtTotalHCF.Text = Consumption
            TxtTotalGallons.Text = Math.Ceiling(Gallons)
            TxtFirstTierConsumption.Text = FormatNumber(Tiers.first, 2)
            TxtSecondTierConsumption.Text = FormatNumber(Tiers.second)
            TxtLastTierConsumption.Text = FormatNumber(Tiers.last)
            TxtWaterCharges.Text = FormatNumber(WaterCharges)
            TxtSewerCharges.Text = FormatNumber(SewerCharges)
            TxtEnvironmentCharges.Text = FormatNumber(EnvCharges)
            TxtServiceCharges.Text = FormatNumber(SrvCharges)
            TxtTotalCharges.Text = FormatNumber(TotalCharges)
            TxtLocalTaxes.Text = FormatNumber(LocalTaxes)
            TxtStateTaxes.Text = FormatNumber(StateTaxes)
            DtpPaymentDueDate.Value = WaterBillManager.SetPaymentDueDate(StrAccountType, DtpMeterReadingEndDate.Value)
            TxtAmountDue.Text = FormatNumber(AmtDue)
            DtpLatePaymentDueDate.Value = WaterBillManager.SetLatePaymentDueDate(StrAccountType, DtpMeterReadingEndDate.Value)
            TxtLateAmountDue.Text = FormatNumber(WaterBillManager.CalculateLateAmountDue(StrAccountType, AmtDue))
        End Sub
    
        Private Sub BtnUpdateWaterBill_Click(sender As Object, e As EventArgs) Handles BtnUpdateWaterBill.Click
            If IsNothing(TxtWaterBillNumber.Text) Then
                MsgBox("You must provide the bill number of the " &
                            "water bill you are trying to update.")
                Exit Sub
            End If
    
            If IsNothing(MtbAccountNumber.Text) Then
                MsgBox("Please make sure you provide the account number of the customer " &
                                "associated with the water bill you are trying to update.")
                Exit Sub
            End If
    
            Dim StrWaterBills As String = Nothing
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
    
            If FiWaterBills.Exists = True Then
                StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
                WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                Dim Bill As WaterBill = WaterBills.Find(Function(invoice) invoice.BillNumber = TxtWaterBillNumber.Text)
    
                If Not Bill Is Nothing Then
                    Bill.WaterBillId = TxtWaterBillId.Text
                    Bill.BillNumber = TxtWaterBillNumber.Text
                    Bill.AccountNumber = MtbAccountNumber.Text
                    Bill.MeterReadingStartDate = DtpMeterReadingStartDate.Value
                    Bill.MeterReadingEndDate = DtpMeterReadingEndDate.Value
                    Bill.BillingDays = TxtBillingDays.Text
                    Bill.CounterReadingStart = TxtCounterReadingStart.Text
                    Bill.CounterReadingEnd = TxtCounterReadingEnd.Text
                    Bill.TotalHCF = TxtTotalHCF.Text
                    Bill.TotalGallons = TxtTotalGallons.Text
                    Bill.FirstTierConsumption = TxtFirstTierConsumption.Text
                    Bill.SecondTierConsumption = TxtSecondTierConsumption.Text
                    Bill.LastTierConsumption = TxtLastTierConsumption.Text
                    Bill.WaterCharges = TxtWaterCharges.Text
                    Bill.SewerCharges = TxtSewerCharges.Text
                    Bill.EnvironmentCharges = TxtEnvironmentCharges.Text
                    Bill.ServiceCharges = TxtServiceCharges.Text
                    Bill.TotalCharges = TxtTotalCharges.Text
                    Bill.LocalTaxes = TxtLocalTaxes.Text
                    Bill.StateTaxes = TxtStateTaxes.Text
                    Bill.PaymentDueDate = DtpPaymentDueDate.Value
                    Bill.AmountDue = TxtAmountDue.Text
                    Bill.LatePaymentDueDate = DtpLatePaymentDueDate.Value
                    Bill.LateAmountDue = TxtLateAmountDue.Text
    
                    Dim Options = New JsonSerializerOptions()
                    Options.WriteIndented = True
    
                    Dim JsWaterBills = JsonSerializer.Serialize(WaterBills, GetType(List(Of WaterBill)), Options)
                    File.WriteAllText(FiWaterBills.FullName, JsWaterBills)
                End If
            End If
    
            Close()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  10. In the Solution Explorer, below the WaterBills folder, double-click Central.vb
  11. From the Toolbox, add a button to the form below the list view and on the right side of the View Water Bill button
  12. Change the characteristics of the button as follows:

    Stellar Water Point - Water Meters

    Control (Name) Text
    ListView List View LvwWaterBills  
    Button Button BtnNewWaterBill  
    Button Button BtnViewWaterBill  
    Button Button BtnEditWaterBill &Edit Water Bill...
  13. Double-click the Edit Water Bill button
  14. Implement the event as follows:
    Private Sub BtnWaterBillsEditor(ByVal sender As Object, e As EventArgs) Handles BtnWaterBillEditor.Click
        Dim Editor As WaterBillsEditor = New WaterBillsEditor
    
        Editor.ShowDialog()
    
        ShowWaterBills()
    End Sub
  15. To execute the application, on the main menu, click Debug -> Start Without Debugging

    Stellar Water Point

  16. On the main form of the application, click the Water Bills button:

    Stellar Water Point - Water Bills

  17. Click the Edit Water Bill button:

    Stellar Water Point - Water Bill Editor

  18. In the Water Bill # text, type 923633
  19. Click the Find Water Bill button

    Stellar Water Point - Water Bill Editor

  20. Change the following values:
    Account #:                9249-379-6848 and click Find Customer Account
    Meter Reading Start Date: 1/19/2010
    Meter Reading End Date:   4/17/2010
    Counter Reading Start:    256953
    Counter Reading End:      256966
  21. Click the Evaluate Water Bill button:

    Stellar Water Point - Water Bill Editor

  22. Click the Update Water Bill button and click OK on the message box:

    Stellar Water Point - Water Bills

  23. Close the forms and return to your programming environment

Water Bill Deletion

If a water bill is useless and must not be kept as a record in the system, an employee must be able to delete it. We will create a form that makes it possible to delete a water bill.

Practical LearningPractical Learning: Deleting a Water Bill Record

  1. To create a form, in the Solution Explorer, right-click the WaterBills folder -> Add -> Form (Windows Forms...)
  2. Change the file Name to Delete
  3. Click Add Resize the form to have the same size as the Water Bill Details form
  4. Select and copy everything in the Water Bill Details form
  5. Paste it in the new Water Bill Delete form
  6. Change the design of the form as follows (you will add only one button):

    Stellar Water Point - Water Bill Deletion

    Control (Name) Text
    Button Button BtnDeleteWaterBill &Delete Water Bill
  7. On the form, double-click the Find Water Bill button
  8. Change the document as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterBillsDelete
        Private Sub BtnFindWaterBill_Click(sender As Object, e As EventArgs) Handles BtnFindWaterBill.Click
            If String.IsNullOrEmpty(TxtWaterBillNumber.Text) Then
                MsgBox("You must provide a water bill number and then click the Find Water Bill button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                REM If the user didn't type a bill number but clicked Find Water Bill, don't do anything
                Exit Sub
            End If
    
            Dim StrWaterBills As String = Nothing
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
    
            Dim StrAccountsTypes As String = Nothing
            Dim AccountsTypes = New List(Of AccountType)
            Dim FileAccountsTypes As String = "C:\Stellar Water Point16\AccountsTypes.json"
    
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiWaterBills.Exists = True Then
                Using TrWaterBills As TextReader = New StreamReader(FiWaterBills.FullName)
                    StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
                    WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                    Dim Selected As IEnumerable(Of WaterBill) = WaterBills.Where(Function(Invoice) Invoice.BillNumber = TxtWaterBillNumber.Text)
    
                    For Each Bill In Selected
                        TxtWaterBillId.Text = Bill.WaterBillId
                        TxtAccountNumber.Text = Bill.AccountNumber
                        TxtMeterReadingStartDate.Text = FormatDateTime(Bill.MeterReadingStartDate, DateFormat.LongDate)
                        TxtMeterReadingEndDate.Text = FormatDateTime(Bill.MeterReadingEndDate, DateFormat.LongDate)
                        TxtBillingDays.Text = Bill.BillingDays
                        TxtCounterReadingStart.Text = Bill.CounterReadingStart
                        TxtCounterReadingEnd.Text = Bill.CounterReadingEnd
                        TxtTotalHCF.Text = Bill.TotalHCF
                        TxtTotalGallons.Text = Bill.TotalGallons
                        TxtFirstTierConsumption.Text = FormatNumber(Bill.FirstTierConsumption)
                        TxtSecondTierConsumption.Text = FormatNumber(Bill.SecondTierConsumption)
                        TxtLastTierConsumption.Text = FormatNumber(Bill.LastTierConsumption)
                        TxtWaterCharges.Text = FormatNumber(Bill.WaterCharges)
                        TxtSewerCharges.Text = FormatNumber(Bill.SewerCharges)
                        TxtEnvironmentCharges.Text = FormatNumber(Bill.EnvironmentCharges)
                        TxtServiceCharges.Text = FormatNumber(Bill.ServiceCharges)
                        TxtTotalCharges.Text = FormatNumber(Bill.TotalCharges)
                        TxtLocalTaxes.Text = FormatNumber(Bill.LocalTaxes)
                        TxtStateTaxes.Text = FormatNumber(Bill.StateTaxes)
                        TxtPaymentDueDate.Text = FormatDateTime(Bill.PaymentDueDate, DateFormat.LongDate)
                        TxtAmountDue.Text = FormatNumber(Bill.AmountDue)
                        TxtLatePaymentDueDate.Text = FormatDateTime(Bill.LatePaymentDueDate, DateFormat.LongDate)
                        TxtLateAmountDue.Text = FormatNumber(Bill.LateAmountDue)
                    Next
                End Using
            End If
    
            Dim StrCustomers = Nothing
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
    
            Dim StrMeterNumber = Nothing
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
    
                    Dim Customers As IEnumerable(Of Customer) = From Consumer
                                                                In Clients
                                                                Where Consumer.AccountNumber = TxtAccountNumber.Text
                                                                Select Consumer
    
                    For Each Client As Customer In Customers
                        TxtAccountName.Text = Client.AccountName
                        StrMeterNumber = Client.MeterNumber
    
                        Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
                        StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
                        AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
                        For Each ActType As AccountType In AccountsTypes
                            If Client.AccountType = ActType.TypeCode Then
                                TxtAccountType.Text = String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription)
                            End If
                        Next
    
                        TxtAddress.Text = Client.Address
                        TxtCity.Text = Client.City
                        TxtCounty.Text = Client.County
                        TxtState.Text = Client.State
                        TxtZIPCode.Text = Client.ZIPCode
                    Next
                End Using
            End If
    
            If Len(StrMeterNumber) > 0 Then
                Dim StrWaterMeters As String = Nothing
                Dim WaterMeters As List(Of WaterMeter) = New List(Of WaterMeter)
                Dim FileWaterMeters = "C:\Stellar Water Point16\WaterMeters.json"
    
                Dim FiWaterMeters As FileInfo = New FileInfo(FileWaterMeters)
    
                If FiWaterMeters.Exists = True Then
                    StrWaterMeters = File.ReadAllText(FiWaterMeters.FullName)
                    WaterMeters = JsonSerializer.Deserialize(StrWaterMeters, GetType(List(Of WaterMeter)))
    
                    Dim Meters As IEnumerable(Of WaterMeter) = From Measure
                                                               In WaterMeters
                                                               Where Measure.MeterNumber = StrMeterNumber
                                                               Select Measure
    
                    For Each Meter As WaterMeter In Meters
                        TxtMeterDetails.Text = Meter.WaterMeterId & " - " &
                                               Meter.MeterNumber & " - " &
                                               Meter.Make & " " &
                                               Meter.Model &
                                               " (Meter Size: " & Meter.MeterSize & ")"
                    Next
                End If
            End If
        End Sub
    
        Private Sub BtnDeleteWaterBill_Click(sender As Object, e As EventArgs) Handles BtnDeleteWaterBill.Click
            If String.IsNullOrEmpty(TxtWaterBillNumber.Text) Then
                MsgBox("Please provide the bill number of the water bill you want to delete, " &
                       "and then click the Find Water Bill button.",
                       MsgBoxStyle.OkOnly, "Stellar Water Point")
                Exit Sub
            End If
    
            Dim StrWaterBills As String = Nothing
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
    
            If FiWaterBills.Exists = True Then
                StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
                WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                Dim Bill As WaterBill = WaterBills.Find(Function(invoice) invoice.BillNumber = TxtWaterBillNumber.Text)
    
                Dim Answer As MsgBoxResult = MsgBox("Are you sure you want to delete (or remove) or cancel " &
                                                    "this water bill from the system (you cannot undo the action)?",
                                                    MsgBoxStyle.YesNoCancel, "Stellar Water Point")
                If Bill IsNot Nothing Then
                    REM If the user clicks Yes, save the updated water bill and close the form
                    If Answer = MsgBoxResult.Yes Then
                        WaterBills.Remove(Bill)
    
                        Dim Options As JsonSerializerOptions = New JsonSerializerOptions()
                        Options.WriteIndented = True
    
                        Dim JsWaterBills As String = JsonSerializer.Serialize(WaterBills, GetType(List(Of WaterBill)), Options)
                        File.WriteAllText(FiWaterBills.FullName, JsWaterBills)
    
                        MsgBox("The water bill has been deleted (or removed, or cancelled) from our system.",
                               MsgBoxStyle.OkOnly, "Stellar Water Point")
    
                        Close()
                    ElseIf Answer = MsgBoxResult.No Then
                        REM If the user clicks No, leave the form displaying
                        BtnFindWaterBill_Click(sender, e)
                    Else
                        REM If the user clicks Cancel, close the Delete form
                        REM and return to the list of water bills
                        Close()
                    End If
                End If
            End If
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  9. In the Solution Explorer, below the WaterBills folder, double-click Central.vb to open its form
  10. From the Toolbox, add two buttons to the form below the list view and to the right of the Edit Water Bill button
  11. Change the form design as follows:

    Stellar Water Point - Water Bills

    Control (Name) Text Other Properties
    ListView List View LvwWaterBills   Anchor: Bottom, Top, Bottom, Left, Right
    Button Button BtnProcessWaterBill &Process Water Bill... Anchor: Bottom, Right
    Button Button BtnViewWaterBill &View Water Bill... Anchor: Bottom, Right
    Button Button BtnEditWaterBill &Edit Water Bill... Anchor: Bottom, Right
    Button Button BtnDeleteWaterBill &Delete Water Bill... Anchor: Bottom, Right
    Button Button BtnClose &Close Anchor: Bottom, Right
  12. Right-click any area of the form and click View Code
  13. Create two events as follows:
    Imports System.IO
    Imports System.Text.Json
    
    Public Class WaterBillsCentral
        Private Sub ShowWaterBills()
            Dim StrCustomers = Nothing
            Dim StrWaterBills = Nothing
            Dim StrAccountsTypes = Nothing
    
            Dim AccountsTypes = New List(Of AccountType)
            Dim Clients As List(Of Customer) = New List(Of Customer)
            Dim WaterBills As List(Of WaterBill) = New List(Of WaterBill)
    
            Dim FileCustomers = "C:\Stellar Water Point16\Customers.json"
            Dim FileAccountsTypes = "C:\Stellar Water Point16\AccountsTypes.json"
            Dim FileWaterBills As String = "C:\Stellar Water Point16\WaterBills.json"
    
            Dim FiCustomers As FileInfo = New FileInfo(FileCustomers)
            Dim FiWaterBills As FileInfo = New FileInfo(FileWaterBills)
            Dim FiAccountsTypes As FileInfo = New FileInfo(FileAccountsTypes)
    
            If FiCustomers.Exists = True Then
                Using TrCustomers As TextReader = New StreamReader(FiCustomers.FullName)
                    StrCustomers = File.ReadAllText(FiCustomers.FullName)
    
                    Clients = JsonSerializer.Deserialize(StrCustomers, GetType(List(Of Customer)))
                End Using
            End If
    
            Dim TrAccountsTypess As TextReader = New StreamReader(FiAccountsTypes.FullName)
            StrAccountsTypes = File.ReadAllText(FiAccountsTypes.FullName)
            AccountsTypes = JsonSerializer.Deserialize(StrAccountsTypes, GetType(List(Of AccountType)))
    
            Dim StrAccountSummary As String
    
            If FiWaterBills.Exists = True Then
                Using TrWaterBills As TextReader = New StreamReader(FiWaterBills.FullName)
                    StrWaterBills = File.ReadAllText(FiWaterBills.FullName)
    
                    WaterBills = JsonSerializer.Deserialize(StrWaterBills, GetType(List(Of WaterBill)))
    
                    LvwWaterBills.Items.Clear()
    
                    For Each Invoice As WaterBill In WaterBills
                        Dim LviWaterBill As ListViewItem = New ListViewItem(Invoice.WaterBillId)
    
                        LviWaterBill.SubItems.Add(Invoice.BillNumber)
    
                        Dim Client As IEnumerable(Of Customer) = Clients.Where(Function(Cust) Cust.AccountNumber = Invoice.AccountNumber)
    
                        StrAccountSummary = Invoice.AccountNumber
    
                        For Each Cust In Clients
                            If Cust.AccountNumber = Invoice.AccountNumber Then
    
                                For Each ActType As AccountType In AccountsTypes
                                    If Cust.AccountType = ActType.TypeCode Then
                                        StrAccountSummary = StrAccountSummary & " - " &
                                                            Cust.AccountName & ", Acnt Type: " & String.Concat(ActType.TypeCode, " - ", ActType.TypeDecription) &
                                                            ", (Mtr #: " & Cust.MeterNumber & ")"
                                    End If
                                Next
                            End If
                        Next
    
                        For Each Cust As Customer In Clients
                            LviWaterBill.SubItems.Add(StrAccountSummary)
    
                            LviWaterBill.SubItems.Add(Invoice.MeterReadingStartDate.ToShortDateString())
                            LviWaterBill.SubItems.Add(Invoice.MeterReadingEndDate.ToShortDateString())
                            LviWaterBill.SubItems.Add(Invoice.BillingDays)
                            LviWaterBill.SubItems.Add(Invoice.CounterReadingStart)
                            LviWaterBill.SubItems.Add(Invoice.CounterReadingEnd)
                            LviWaterBill.SubItems.Add(Invoice.TotalHCF)
                            LviWaterBill.SubItems.Add(Invoice.TotalGallons)
                            LviWaterBill.SubItems.Add(Invoice.PaymentDueDate.ToShortDateString())
                            LviWaterBill.SubItems.Add(Invoice.AmountDue)
                        Next
    
                        LvwWaterBills.Items.Add(LviWaterBill)
                    Next
                End Using
            End If
        End Sub
    
        Private Sub WaterBillsCentral_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ShowWaterBills()
        End Sub
    
        Private Sub BtnProcessWaterBill_Click(sender As Object, e As EventArgs) Handles BtnProcessWaterBill.Click
            Dim Create As WaterBillsCreate = New WaterBillsCreate
    
            Create.ShowDialog()
    
            ShowWaterBills()
        End Sub
    
        Private Sub BtnWaterBillsDetails(ByVal sender As Object, e As EventArgs) Handles BtnWaterBillDetails.Click
            Dim Details As WaterBillsDetails = New WaterBillsDetails
    
            Details.ShowDialog()
    
            ShowWaterBills()
        End Sub
    
        Private Sub BtnWaterBillsEditor(ByVal sender As Object, e As EventArgs) Handles BtnWaterBillEditor.Click
            Dim Editor As WaterBillsEditor = New WaterBillsEditor
    
            Editor.ShowDialog()
    
            ShowWaterBills()
        End Sub
    
        Private Sub BtnDeleteWaterBill_Click(sender As Object, e As EventArgs) Handles BtnDeleteWaterBill.Click
            Dim Delete As WaterBillsDelete = New WaterBillsDelete
    
            Delete.ShowDialog()
    
            ShowWaterBills()
        End Sub
    
        Private Sub BtnClose_Click(sender As Object, e As EventArgs) Handles BtnClose.Click
            Close()
        End Sub
    End Class
  14. To execute, on the main menu, click Debug -> Start Without Debugging:

  15. On the Stellar Water Point form, click the Water Bills button

    Stellar Water Point - Water Bills

  16. On the Water Bills form, click the Delete Water Bill button

    Stellar Water Point - Water Bill Deletion

  17. In the Water Bill # text box, type 917829:

    Stellar Water Point - Water Bill Deletion

  18. Click Find Water Bill

    Stellar Water Point - Water Bill Deletion

  19. Click Delete Water Bill:

    Stellar Water Point - Water Bill Deletion

  20. Read the message in the message box and click Yes:

    Stellar Water Point - Water Bill Deletion

  21. Read the message in the message box and click OK:

    Stellar Water Point - Water Bills

  22. Close the forms and return to your programming environment
  23. Close Microsoft Visual Studio

Home Copyright © 2010-2026, FunctionX Tuesday 07 April 2026, 23:31 Home