XML Serialization - Stellar Water Point
XML Serialization - Stellar Water Point
Introduction
A text-based database is an application used to create, keep, and manage records. You have many options. One way to store the records of a database is as text. Even then, you still have many option. One solution is to create and manage records using a collection class.
Besides using a collection class to create and manage records, you also have to decide in what format you would keep the record. For this example, we will save the records in XML.
Practical Learning: Introducing MDI Applications
Water Meters
A water meter is a mechanical device used to measure the amount of water that is consumed. To deal with it, we will create a class and forms.
Practical Learning: Starting Water Meters Issues
namespace StellarWaterPoint2.Models { internal readonly record struct WaterMeter { public readonly string? MeterNumber { get; init; } public readonly string? Make { get; init; } public readonly string? Model { get; init; } public readonly string? MeterSize { get; init; } } }
Control | (Name) | Text | Other Properties | |
Label | &Meter #: | |||
MaskedTextBox | mtbMeterNumber | Masked: 000-00-000 | ||
Label | M&ake: | |||
TextBox | txtMake | |||
Label | M&odel: | |||
TextBox | txtModel | Modifiers: Public | ||
Label | Me&ter Size: | |||
TextBox | txtMeterSize | |||
Button | btnSaveWateMeter | S&ave Water Meter |
Control | (Name) | Text | |
Button | btnFindWateMeter | &Find Water Meter | |
Button | btnUpdateWateMeter | &Update Water Meter |
Control | (Name) | Text | |
Button | btnDeleteWateMeter | &Delete Water Meter |
(Name) | Text | Width |
colWaterMeterId | Id | 40 |
colMeterNumber | Meter # | 150 |
colMake | Make | 225 |
colModel | Model | 100 |
colMeterSize | Meter Size | 150 |
Control | (Name) | Other Properties | |
ListView | lvwWaterMeters | FullRowSelect: True GridLines: True View: Details Anchor: Top, Bottom, Left, Right |
Customers
Customers are families or businesses that consume a product or service, which is the case for water consumption. To deal with these issues, we will create a class and forms.
Practical Learning: Preparing Customers Accounts
namespace StellarWaterPoint1.Models { internal readonly record struct Customer { public readonly string? AccountNumber { get; init; } public readonly string? MeterNumber { get; init; } public readonly string? FirstName { get; init; } public readonly string? LastName { get; init; } public readonly string? Address { get; init; } public readonly string? City { get; init; } public readonly string? County { get; init; } public readonly string? State { get; init; } public readonly string? ZIPCode { get; init; } } }
Control | (Name) | Text | Mask | |
Label | &Account #: | |||
MaskedTextBox | mtbAccountNumber | Masked: 0000-000-0000 | ||
Label | &Meter #: | |||
MaskedTextBox | mtbMeterNumber | Masked: 000-00-000 | ||
Button | btnFindWaterMeter | &Find Water Meter | ||
Label | Meter &Details: | |||
TextBox | txtMeterDetails | |||
Label | &First Name: | |||
TextBox | txtFirstName | |||
Label | &Last Name: | |||
TextBox | txtLastName | |||
Label | &Address: | |||
TextBox | txtAddress | |||
Label | C&ity: | |||
TextBox | txtCity | |||
Label | C&ounty: | |||
TextBox | txtCounty | |||
Label | &State: | |||
TextBox | txtState | |||
Label | &ZIP-Code: | |||
MaskedTextBox | mtbZIPCode | Masked: Zip-Code | ||
Button | btnSaveCustomerAccount | S&ave Customer Account |
Control | (Name) | Text | |
Button | btnFindCustomer | &Find Customer | |
Button | btnUpdateCustomerAccount | &Update Customer Account |
Control | (Name) | Text | |
Button | btnDeleteCustomerAccount | &Delete Customer Account |
(Name) | Text | TextAlign | Width |
colCustomerId | Id | 40 | |
colAccountNumber | Account # | Center | 175 |
colMeterNumber | Meter # | Center | 150 |
colFirstName | First Name | 125 | |
colLastName | Last Name | 125 | |
colAddress | Address | 250 | |
colCity | City | 125 | |
colCounty | County | 150 | |
colState | State | Center | |
colZIPCode | ZIP-Code | Center | 125 |
Control | (Name) | Text | Other Properties | |
ListView | lvwCustomers | FullRowSelect: True GridLines: True View: Details Anchor: Top, Bottom, Left, Right |
Water Bills
Bills are the natural results and benefits of services and products that people and businesses consume. To prepare them, we will create a class and forms.
Practical Learning: Preparing Bills
namespace StellarWaterPoint1.Models { internal readonly record struct WaterBill { public readonly int BillNumber { get; init; } public readonly string? AccountNumber { get; init; } public readonly string? MeterReadingStartDate { get; init; } public readonly string? MeterReadingEndDate { get; init; } public readonly int BillingDays { get; init; } public readonly double CounterReadingStart { get; init; } public readonly double CounterReadingEnd { get; init; } public readonly double TotalGallons { get; init; } public readonly double TotalCCF { get; init; } public readonly double FirstTierConsumption { get; init; } public readonly double SecondTierConsumption { get; init; } public readonly double LastTierConsumption { get; init; } public readonly double WaterCharges { get; init; } public readonly double SewerCharges { get; init; } public readonly double EnvironmentCharges { get; init; } public readonly double TotalCharges { get; init; } public readonly double LocalTaxes { get; init; } public readonly double StateTaxes { get; init; } public readonly double AmountDue { get; init; } public readonly string? PaymentDueDate { get; init; } public readonly double LateAmountDue { get; init; } public readonly string? LatePaymentDueDate { get; init; } } }
Control | (Name) | Text | Other Properties | |
Label | Water Bill #: | |||
TextBox | txtBillNumber | |||
GroupBox | Customer Information | |||
Label | Account #: | |||
MaskedTextBox | mtbAccountNumber | Masked: 0000-000-0000 | ||
Button | btnFindCustomerAccount | Find Customer Account | ||
Label | Customer Name: | |||
TextBox | txtCustomerName | |||
Label | Address: | |||
TextBox | txtAddress | |||
TextBox | txtCity | |||
TextBox | txtCounty | |||
TextBox | txtState | |||
MaskedTextBox | mtbZIPCode | Masked: Zip-Code | ||
Label | _______________________ | |||
Label | Meter Details: | |||
TextBox | txtMeterDetails | Modifiers: Public | ||
GroupBox | Meter Reading | |||
Label | Meter Reading Start Date: | |||
DateTimePicker | dtpMeterReadingStartDate | |||
Label | Meter Reading End Date: | |||
DateTimePicker | dtpMeterReadingEndDate | |||
Label | Counter Reading Start: | |||
TextBox | txtCounterReadingStart | |||
Label | Counter Reading End: | |||
TextBox | txtCounterReadingEnd | |||
Button | btnEvaluateWaterBill | Evaluate Water Bill | ||
GroupBox | Meter Result | |||
Label | Billing Days: | |||
TextBox | txtBillingDays | TextAlign: Right | ||
Label | Total Gallons: | |||
TextBox | txtTotalGallons | TextAlign: Right | ||
Label | Total CCF: | |||
TextBox | txtTotalCCF | TextAlign: Right | ||
Label | First Tier Consumption: | |||
TextBox | txtFirstTierConsumption | TextAlign: Right | ||
Label | Second Tier: | |||
TextBox | txtSecondTierConsumption | TextAlign: Right | ||
Label | Last Tier: | |||
TextBox | txtLastTierConsumption | TextAlign: Right | ||
GroupBox | Consumption Charges | |||
Label | Water Charges: | |||
TextBox | txtWaterCharges | TextAlign: Right | ||
Label | Sewer Charges: | |||
TextBox | txtSewerCharges | TextAlign: Right | ||
Label | Environment Charges: | |||
TextBox | txtEnvironmentCharges | TextAlign: Right | ||
Label | Total Charges: | |||
TextBox | txtTotalCharges | TextAlign: Right | ||
GroupBox | Taxes | |||
Label | Local Taxes: | |||
TextBox | txtLocalTaxes | TextAlign: Right | ||
Label | State Taxes: | |||
TextBox | txtStateTaxes | TextAlign: Right | ||
GroupBox | Water Bill Payment | |||
Label | Payment Due Date: | |||
DateTimePicker | dtpPaymentDueDate | |||
Label | Amount Due: | |||
TextBox | txtAmountDue | TextAlign: Right | ||
Label | Late Payment Due Date: | |||
DateTimePicker | dtpLatePaymentDueDate | |||
Label | Late Amount Due: | |||
TextBox | txtLateAmountDue | TextAlign: Right | ||
Button | btnSaveWaterBill | Save Water Bill | ||
Button | btnClose | Close |
using StellarWaterPoint2.Models; using System.Xml.Serialization; namespace StellarWaterPoint2.WaterBills { public partial class Create : Form { public Create() { InitializeComponent(); } private void btnFindCustomerAccount_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbAccountNumber.Text)) { MessageBox.Show("You must type an account number for a customer.", "Stellar Water Point", MessageBoxButtons.OK); return; } Customer? client = null; List<Customer> clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); if (fiCustomers.Exists == true) { using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; client = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!; } } if (client is null) { MessageBox.Show("There is no customer with that account number in our system.", "Stellar Water Point", MessageBoxButtons.OK); return; } string strMeterNumber = client.MeterNumber!; txtCustomerName.Text = client.FirstName + " " + client.LastName; txtAddress.Text = client.Address; txtCity.Text = client.City; txtCounty.Text = client.County; txtState.Text = client.State; mtbZIPCode.Text = client.ZIPCode; WaterMeter? meter = null; List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; meter = waterMeters.Find(m => m.MeterNumber == strMeterNumber)!; } } txtMeterDetails.Text = meter?.Make + " " + meter?.Model + " (Meter #: " + meter?.MeterSize + ")"; } private void dtpMeterReadingEndDate_ValueChanged(object sender, EventArgs e) { TimeSpan tsDays = dtpMeterReadingEndDate.Value - dtpMeterReadingStartDate.Value; txtBillingDays.Text = tsDays.Days.ToString(); } private void btnEvaluateWaterBill_Click(object sender, EventArgs e) { double counterStart = 0, counterEnd = 0; try { counterStart = double.Parse(txtCounterReadingStart.Text); } catch (FormatException feCRStart) { MessageBox.Show("There was a problem with the value of the " + "Counter Reading Start. The error produced is: " + feCRStart.Message, "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information); } try { counterEnd = double.Parse(txtCounterReadingEnd.Text); } catch (FormatException feCREnd) { MessageBox.Show("There was a problem with the value of the " + "Counter Reading End. The error produced is: " + feCREnd.Message, "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information); } double consumption = counterEnd - counterStart; double gallons = consumption * 748.05; double firstTier = gallons * (48.00 / 10000.00); double secondTier = gallons * (32.00 / 10000.00); double lastTier = gallons * (20.00 / 10000.00); double waterCharges = firstTier + secondTier + lastTier; double sewerCharges = waterCharges * 28.65 / 100; double envCharges = waterCharges * 0.22184; double totalCharges = waterCharges + sewerCharges + envCharges; double localTaxes = totalCharges * 0.06148; double stateTaxes = totalCharges * 0.01374; double amtDue = totalCharges + localTaxes + stateTaxes; TimeSpan tsPaymentDueDate = new TimeSpan(15, 0, 0, 0); txtTotalCCF.Text = consumption.ToString(); txtTotalGallons.Text = gallons.ToString("F"); txtFirstTierConsumption.Text = firstTier.ToString("F"); txtSecondTierConsumption.Text = secondTier.ToString("F"); txtLastTierConsumption.Text = lastTier.ToString("F"); txtWaterCharges.Text = waterCharges.ToString("F"); txtSewerCharges.Text = sewerCharges.ToString("F"); txtEnvironmentCharges.Text = envCharges.ToString("F"); txtTotalCharges.Text = totalCharges.ToString("F"); txtLocalTaxes.Text = localTaxes.ToString("F"); txtStateTaxes.Text = stateTaxes.ToString("F"); dtpPaymentDueDate.Value = dtpMeterReadingEndDate.Value + tsPaymentDueDate; txtAmountDue.Text = amtDue.ToString("F"); dtpLatePaymentDueDate.Value = dtpMeterReadingEndDate.Value + new TimeSpan(30, 0, 0, 0); txtLateAmountDue.Text = (amtDue + 8.95).ToString("F"); } private void btnSaveWaterBill_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtBillNumber.Text)) { MessageBox.Show("You must type a bill number." + "Otherwise, the account cannot be saved.", "Stellar Water Point", MessageBoxButtons.OK); return; } if (string.IsNullOrEmpty(txtCounterReadingStart.Text)) { MessageBox.Show("You must enter the start value of the water bill counter." + "Otherwise, the account cannot be saved.", "Stellar Water Point", MessageBoxButtons.OK); return; } if (string.IsNullOrEmpty(mtbAccountNumber.Text)) { MessageBox.Show("You must type an account number of a customer." + "Otherwise, the account cannot be saved.", "Stellar Water Point", MessageBoxButtons.OK); return; } List<WaterBill> bills = new List<WaterBill>(); string strWaterBills = @"E:\Stellar Water Point\WaterBills.xml"; XmlSerializer xsWaterBills = new XmlSerializer(typeof(List<WaterBill>)); FileInfo fiWaterBills = new FileInfo(strWaterBills); if (fiWaterBills.Exists == true) { using (TextReader trWaterBills = new StreamReader(fiWaterBills.FullName)) { bills = (List<WaterBill>)xsWaterBills.Deserialize(trWaterBills)!; } } WaterBill bill = new WaterBill() { BillNumber = int.Parse(txtBillNumber.Text), AccountNumber = mtbAccountNumber.Text, MeterReadingStartDate = dtpLatePaymentDueDate.Value.ToShortDateString(), MeterReadingEndDate = dtpMeterReadingEndDate.Value.ToShortDateString(), BillingDays = int.Parse(txtBillingDays.Text), CounterReadingStart = double.Parse(txtCounterReadingStart.Text), CounterReadingEnd = double.Parse(txtCounterReadingEnd.Text), TotalGallons = double.Parse(txtTotalGallons.Text), TotalCCF = double.Parse(txtTotalCCF.Text), FirstTierConsumption = double.Parse(txtFirstTierConsumption.Text), SecondTierConsumption = double.Parse(txtSecondTierConsumption.Text), LastTierConsumption = double.Parse(txtLastTierConsumption.Text), WaterCharges = double.Parse(txtWaterCharges.Text), SewerCharges = double.Parse(txtSewerCharges.Text), EnvironmentCharges = double.Parse(txtEnvironmentCharges.Text), TotalCharges = double.Parse(txtTotalCharges.Text), LocalTaxes = double.Parse(txtLocalTaxes.Text), StateTaxes = double.Parse(txtStateTaxes.Text), AmountDue = double.Parse(txtAmountDue.Text), PaymentDueDate = dtpPaymentDueDate.Value.ToShortDateString(), LateAmountDue = double.Parse(txtLateAmountDue.Text), LatePaymentDueDate = dtpLatePaymentDueDate.Value.ToShortDateString() }; bills.Add(bill); using (TextWriter twWaterBills = new StreamWriter(fiWaterBills.FullName)) { xsWaterBills.Serialize(twWaterBills, bills); } Close(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Control | (Name) | Text | |
Button | btnFindWaterBill | Find Water &Bill |
using StellarWaterPoint20.Models; using System.Xml.Serialization; namespace StellarWaterPoint20.WaterBills { public partial class Details : Form { public Details() { InitializeComponent(); } private void btnFindWaterBill_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtBillNumber.Text)) { MessageBox.Show("You must type a bill number.", "Stellar Water Point", MessageBoxButtons.OK); return; } WaterBill? bill = null; List<WaterBill> bills = new List<WaterBill>(); string strWaterBills = @"E:\Stellar Water Point\WaterBills.xml"; XmlSerializer xsWaterBills = new XmlSerializer(typeof(List<WaterBill>)); FileInfo fiWaterBills = new FileInfo(strWaterBills); if (fiWaterBills.Exists == true) { using (TextReader trWaterBills = new StreamReader(fiWaterBills.FullName)) { bills = (List<WaterBill>)xsWaterBills.Deserialize(trWaterBills)!; bill = bills.Find(pay => pay.BillNumber == int.Parse(txtBillNumber.Text))!; } } if (bill is null) { MessageBox.Show("There is no water bill with that number in our system.", "Stellar Water Point", MessageBoxButtons.OK); return; } mtbAccountNumber.Text = bill.AccountNumber; dtpLatePaymentDueDate.Value = DateTime.Parse(bill.MeterReadingStartDate!); dtpMeterReadingEndDate.Value = DateTime.Parse(bill.MeterReadingEndDate!); txtBillingDays.Text = bill.BillingDays.ToString(); txtCounterReadingStart.Text = bill.CounterReadingStart.ToString(); txtCounterReadingEnd.Text = bill.CounterReadingEnd.ToString(); txtTotalGallons.Text = bill.TotalGallons.ToString(); txtTotalCCF.Text = bill.TotalCCF.ToString(); txtFirstTierConsumption.Text = bill.FirstTierConsumption.ToString(); txtSecondTierConsumption.Text = bill.SecondTierConsumption.ToString(); txtLastTierConsumption.Text = bill.LastTierConsumption.ToString(); txtWaterCharges.Text = bill.WaterCharges.ToString(); txtSewerCharges.Text = bill.SewerCharges.ToString(); txtEnvironmentCharges.Text = bill.EnvironmentCharges.ToString(); txtTotalCharges.Text = bill.TotalCharges.ToString(); txtLocalTaxes.Text = bill.LocalTaxes.ToString(); txtStateTaxes.Text = bill.StateTaxes.ToString(); txtAmountDue.Text = bill.AmountDue.ToString(); dtpPaymentDueDate.Value = DateTime.Parse(bill.PaymentDueDate!); txtLateAmountDue.Text = bill.LateAmountDue.ToString(); dtpLatePaymentDueDate.Value = DateTime.Parse(bill.LatePaymentDueDate!); Customer? client = null; string? strMeterNumber = string.Empty; List<Customer> clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; client = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!; strMeterNumber = client.MeterNumber!; txtCustomerName.Text = client.FirstName + " " + client.LastName; txtAddress.Text = client.Address; txtCity.Text = client.City; txtCounty.Text = client.County; txtState.Text = client.State; mtbZIPCode.Text = client.ZIPCode; } WaterMeter? meter = null; List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; meter = waterMeters.Find(m => m.MeterNumber == strMeterNumber)!; txtMeterDetails.Text = meter?.Make + " " + meter?.Model + " (Meter #: " + meter?.MeterSize + ")"; } } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Finalizing the Application
An application must provide intuitive tools for the users. To make this happen, we will create a menu for the application.
Practical Learning: Laying Out the Documents
Text | (Name) |
&File | miFile |
Water &Bills | miWaterBills |
&Customers | miCustomers |
Water &Meters | miWaterMeters |
&Window | miWindow |
&Help | miHelp |
Text | (Name) | Shortcuts |
E&xit | miFileExit | Alt + F4 |
Text | (Name) | Shortcuts |
&Prepare Water Bill... | miWaterBillsCreate | Ctrl+Shift+B |
&View Water Bill... | miWaterBillsView | Ctrl+Shift+V |
Text | (Name) | Shortcuts |
&Create Customer Account... | miCustomersCreate | Ctrl+Shift+C |
&Edit Customer Account... | miCustomersEditor | Ctrl+Shift+E |
&Delete Customer Account... | miCustomersDelete | Ctrl+Shift+D |
tsCustomersSeparator | ||
&View All Accounts... | miCustomerViewAll | Ctrl+Shift+A |
Text | (Name) | Shortcuts |
&Setup Water Meter... | miWaterMetersCreate | Ctrl+Shift+W |
Edit &Water Meter... | miWaterMetersEditor | Ctrl+Shift+I |
De&lete Water Meter... | miWaterMetersCreate | Ctrl+Shift+R |
tsWaterMetersSeparator | ||
View All Wate&r Meters... | miWaterMeterViewAll | Ctrl+Shift+T |
Text | (Name) |
&Arrange | miWindowArrange |
&Cascade | miWindowCascade |
Tile &Horizontal | miWindowTileHorizontal |
Tile &Vertical | mnuWindowTileVertical |
Text | (Name) | Shortcuts |
&About Stellar Water Point... | miHelpAbout | Ctrl+F1 |
namespace StellarWaterPoint2 { public partial class WaterDistribution : Form { public static bool MetersDisplaying; public static bool MeterEditorDisplaying; public static bool MeterDeleteDisplaying; public static bool MeterCreateDisplaying; public static bool ClientsDisplaying; public static bool ClientEditorDisplaying; public static bool ClientDeleteDisplaying; public static bool ClientCreateDisplaying; private WaterMeters.Manage meters; private WaterMeters.Editor meterEditor; private WaterMeters.Create meterCreate; private WaterMeters.Delete meterDelete; private Customers.ViewAll clients; private Customers.Editor clientEditor; private Customers.Create clientCreate; private Customers.Delete clientDelete; public WaterDistribution() { InitializeComponent(); MetersDisplaying = false; MeterEditorDisplaying = false; MeterCreateDisplaying = false; MeterDeleteDisplaying = false; ClientsDisplaying = false; ClientEditorDisplaying = false; ClientCreateDisplaying = false; ClientDeleteDisplaying = false; meters = new WaterMeters.Manage(); meterEditor = new WaterMeters.Editor(); meterCreate = new WaterMeters.Create(); meterDelete = new WaterMeters.Delete(); clients = new Customers.ViewAll(); clientEditor = new Customers.Editor(); clientCreate = new Customers.Create(); clientDelete = new Customers.Delete(); } private void miWaterBillsCreate_Click(object sender, EventArgs e) { WaterBills.Create bill = new WaterBills.Create(); bill.ShowDialog(); } private void miWaterBillsDetails_Click(object sender, EventArgs e) { WaterBills.Details details = new WaterBills.Details(); details.ShowDialog(); } private void miCustomersCreate_Click(object sender, EventArgs e) { if (ClientCreateDisplaying == false) { clientCreate = new(); clientCreate.MdiParent = this; clientCreate.Show(); ClientCreateDisplaying = true; } else { clientCreate.BringToFront(); } } private void miCustomersEditor_Click(object sender, EventArgs e) { if (ClientEditorDisplaying == false) { clientEditor = new(); clientEditor.MdiParent = this; clientEditor.Show(); ClientEditorDisplaying = true; } else { clientEditor.BringToFront(); } } private void miCustomersDelete_Click(object sender, EventArgs e) { if (ClientDeleteDisplaying == false) { clientDelete = new(); clientDelete.MdiParent = this; clientDelete.Show(); ClientDeleteDisplaying = true; } else { clientDelete.BringToFront(); } } private void miCustomerViewAll_Click(object sender, EventArgs e) { if (ClientsDisplaying == false) { clients = new(); clients.MdiParent = this; clients.Show(); ClientsDisplaying = true; } else { clients.BringToFront(); } } private void miWaterMetersCreate_Click(object sender, EventArgs e) { if (MeterCreateDisplaying == false) { meterCreate = new(); meterCreate.MdiParent = this; meterCreate.Show(); MeterCreateDisplaying = true; } else { meterCreate.BringToFront(); } } private void miWaterMetersEditor_Click(object sender, EventArgs e) { if (MeterEditorDisplaying == false) { meterEditor = new(); meterEditor.MdiParent = this; meterEditor.Show(); MeterEditorDisplaying = true; } else { meterEditor.BringToFront(); } } private void miWaterMeterViewAll_Click(object sender, EventArgs e) { if (MetersDisplaying == false) { meters = new WaterMeters.Manage(); meters.MdiParent = this; meters.Show(); MetersDisplaying = true; } else { meters.BringToFront(); } } private void miWaterMetersDelete_Click(object sender, EventArgs e) { if (MeterDeleteDisplaying == false) { meterDelete = new(); meterDelete.MdiParent = this; meterDelete.Show(); MeterDeleteDisplaying = true; } else { meterDelete.BringToFront(); } } private void miWindowArrange_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.ArrangeIcons); } private void miWindowCascade_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.Cascade); } private void miWindowTileHorizontal_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.TileHorizontal); } private void miWindowTileVertical_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.TileVertical); } private void miHelpAbout_Click(object sender, EventArgs e) { AboutSWP about = new AboutSWP(); about.ShowDialog(); } private void miFileExit_Click(object sender, EventArgs e) { Close(); } } }
using System.Xml.Serialization; using StellarWaterPoint2.Models; namespace StellarWaterPoint2.Customers { public partial class Create : Form { public Create() { InitializeComponent(); } private void btnFindWaterMeter_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbMeterNumber.Text)) { MessageBox.Show("You must type a number for a water meter.", "Stellar Water Point", MessageBoxButtons.OK); return; } WaterMeter? meter = null; List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; meter = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!; } } if (meter is null) { MessageBox.Show("There is no water meter with that number in our system.", "Stellar Water Point", MessageBoxButtons.OK); return; } txtMeterDetails.Text = meter.Make + " " + meter.Model + " (Meter #: " + meter.MeterSize + ")"; } private void btnSaveCustomerAccount_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbAccountNumber.Text)) { MessageBox.Show("You must type an account number of a customer." + "Otherwise, the account cannot be saved.", "Stellar Water Point", MessageBoxButtons.OK); return; } List<Customer> clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); if (fiCustomers.Exists == true) { using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; } } Customer client = new Customer() { AccountNumber = mtbAccountNumber.Text, MeterNumber = mtbMeterNumber.Text, FirstName = txtFirstName.Text, LastName = txtLastName.Text, Address = txtAddress.Text, City = txtCity.Text, County = txtCounty.Text, State = txtState.Text, ZIPCode = mtbZIPCode.Text }; clients.Add(client); using (TextWriter twCustomers = new StreamWriter(fiCustomers.FullName)) { xsCustomers.Serialize(twCustomers, clients); } Close(); } private void Create_FormClosing(object sender, FormClosingEventArgs e) { if (WaterDistribution.ClientCreateDisplaying == true) { WaterDistribution.ClientCreateDisplaying = false; Close(); } } } }
using System.Xml.Serialization; using StellarWaterPoint20.Models; namespace StellarWaterPoint20.Customers { public partial class Delete : Form { public Delete() { InitializeComponent(); } private void btnFindCustomer_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbAccountNumber.Text)) { MessageBox.Show("You must type an account number for a customer.", "Stellar Water Point", MessageBoxButtons.OK); return; } Customer? client = null; List<Customer> clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); if (fiCustomers.Exists == true) { using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; client = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!; } } if (client is null) { MessageBox.Show("There is no customer with that account number in our system.", "Stellar Water Point", MessageBoxButtons.OK); return; } mtbMeterNumber.Text = client.MeterNumber!; txtFirstName.Text = client.FirstName; txtLastName.Text = client.LastName; txtAddress.Text = client.Address; txtCity.Text = client.City; txtCounty.Text = client.County; txtState.Text = client.State; mtbZIPCode.Text = client.ZIPCode; WaterMeter? meter = null; List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; meter = waterMeters.Find(m => m.MeterNumber == mtbAccountNumber.Text)!; } } txtMeterDetails.Text = meter?.Make + " " + meter?.Model + " (Meter #: " + meter?.MeterSize + ")"; } private void btnDeleteCustomerAccount_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbAccountNumber.Text)) { MessageBox.Show("You must type an account number held by a customer.", "Stellar Water Point", MessageBoxButtons.OK); return; } List<Customer>? clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); if (fiCustomers.Exists == true) { using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; foreach (Customer cust in clients) { if (cust.AccountNumber == mtbAccountNumber.Text) { clients.Remove(cust); MessageBox.Show("The customer account will be removed from the system.", "Stellar Water Point", MessageBoxButtons.OK); break; } } } } TextWriter twCustomers = new StreamWriter(fiCustomers.FullName); try { xsCustomers.Serialize(twCustomers, clients); } finally { twCustomers.Close(); Close(); } } private void Delete_FormClosing(object sender, FormClosingEventArgs e) { if (WaterDistribution.ClientDeleteDisplaying == true) { WaterDistribution.ClientDeleteDisplaying = false; Close(); } } } }
using System.Xml.Serialization; using StellarWaterPoint2.Models; namespace StellarWaterPoint2.Customers { public partial class Editor : Form { public Editor() { InitializeComponent(); } private void btnFindCustomer_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbAccountNumber.Text)) { MessageBox.Show("You must type an account number for a customer.", "Stellar Water Point", MessageBoxButtons.OK); return; } Customer? client = null; List<Customer> clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); if (fiCustomers.Exists == true) { using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; client = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!; } } if (client is null) { MessageBox.Show("There is no customer with that account number in our system.", "Stellar Water Point", MessageBoxButtons.OK); return; } mtbMeterNumber.Text = client.MeterNumber!; txtFirstName.Text = client.FirstName; txtLastName.Text = client.LastName; txtAddress.Text = client.Address; txtCity.Text = client.City; txtCounty.Text = client.County; txtState.Text = client.State; mtbZIPCode.Text = client.ZIPCode; WaterMeter? meter = null; List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; meter = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!; } } txtMeterDetails.Text = meter?.Make + " " + meter?.Model + " (Meter #: " + meter?.MeterSize + ")"; } private void btnFindWaterMeter_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbMeterNumber.Text)) { MessageBox.Show("You must type a number for a water meter.", "Stellar Water Point", MessageBoxButtons.OK); return; } WaterMeter? meter = null; List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; meter = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!; } } if (meter is null) { MessageBox.Show("There is no water meter with that number in our system.", "Stellar Water Point", MessageBoxButtons.OK); return; } txtMeterDetails.Text = meter.Make + " " + meter.Model + " (Meter #: " + meter.MeterSize + ")"; } private void btnUpdateCustomerAccount_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbAccountNumber.Text)) { MessageBox.Show("You must type a customer's account number.", "Stellar Water Point", MessageBoxButtons.OK); return; } List<Customer> clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); if (fiCustomers.Exists == true) { using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; clients.ForEach(client => { if (client.AccountNumber == mtbAccountNumber.Text) { client.MeterNumber = mtbMeterNumber.Text; client.FirstName = txtFirstName.Text; client.LastName = txtLastName.Text; client.Address = txtAddress.Text; client.City = txtCity.Text; client.County = txtCounty.Text; client.State = txtState.Text; client.ZIPCode = mtbZIPCode.Text; } }); } } using (TextWriter twCustomers = new StreamWriter(fiCustomers.FullName)) { xsCustomers.Serialize(twCustomers, clients); } Close(); } private void Editor_FormClosing(object sender, FormClosingEventArgs e) { if (WaterDistribution.ClientEditorDisplaying == true) { WaterDistribution.ClientEditorDisplaying = false; Close(); } } } }
using System.Xml.Serialization; using StellarWaterPoint2.Models; namespace StellarWaterPoint2.Customers { public partial class ViewAll : Form { public ViewAll() { InitializeComponent(); } private void ShowCustomers() { List<Customer> clients = new List<Customer>(); string strCustomers = @"E:\Stellar Water Point\Customers.xml"; XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>)); FileInfo fiCustomers = new FileInfo(strCustomers); if (fiCustomers.Exists == true) { using (TextReader trCustomers = new StreamReader(fiCustomers.FullName)) { clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!; int counter = 1; lvwCustomers.Items.Clear(); foreach (Customer client in clients) { ListViewItem lviCustomer = new ListViewItem(counter++.ToString()); lviCustomer.SubItems.Add(client.AccountNumber); lviCustomer.SubItems.Add(client.MeterNumber); lviCustomer.SubItems.Add(client.FirstName); lviCustomer.SubItems.Add(client.LastName); 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); } } } } private void ViewAll_Activated(object sender, EventArgs e) { ShowCustomers(); } private void ViewAll_FormClosing(object sender, FormClosingEventArgs e) { if (WaterDistribution.ClientsDisplaying == true) { WaterDistribution.ClientsDisplaying = false; Close(); } } } }
using StellarWaterPoint2.Models; using System.Xml.Serialization; namespace StellarWaterPoint2.WaterMeters { public partial class Create : Form { public Create() { InitializeComponent(); } private void btnSaveWaterMeter_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbMeterNumber.Text)) { MessageBox.Show("You must type a meter number. " + "Otherwise, the water meter cannot be set up.", "Stellar Water Point", MessageBoxButtons.OK); return; } List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; } } WaterMeter wm = new WaterMeter() { MeterNumber = mtbMeterNumber.Text, Make = txtMake.Text, Model = txtModel.Text, MeterSize = txtMeterSize.Text }; waterMeters.Add(wm); using (TextWriter twWaterMeters = new StreamWriter(fiWaterMeters.FullName)) { xsWaterMeters.Serialize(twWaterMeters, waterMeters); } Close(); } private void Create_FormClosing(object sender, FormClosingEventArgs e) { if (WaterDistribution.MeterCreateDisplaying == true) { WaterDistribution.MeterCreateDisplaying = false; Close(); } } } }
using StellarWaterPoint2.Models; using System.Xml.Serialization; namespace StellarWaterPoint2.WaterMeters { public partial class Editor : Form { public Editor() { InitializeComponent(); } private void btnFindWaterMeter_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbMeterNumber.Text)) { MessageBox.Show("You must type a number for a water meter.", "Stellar Water Point", MessageBoxButtons.OK); return; } WaterMeter? meter = null; List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; meter = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!; } } if (meter is null) { MessageBox.Show("There is no water meter with that number in our system.", "Stellar Water Point", MessageBoxButtons.OK); return; } txtMake.Text = meter.Make; txtModel.Text = meter.Model; txtMeterSize.Text = meter.MeterSize; } private void btnUpdateWaterMeter_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(mtbMeterNumber.Text)) { MessageBox.Show("You must type a number for a water meter.", "Stellar Water Point", MessageBoxButtons.OK); return; } List<WaterMeter> waterMeters = new List<WaterMeter>(); string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; waterMeters.ForEach(wm => { if (wm.MeterNumber == mtbMeterNumber.Text) { wm.Make = txtMake.Text; wm.Model = txtModel.Text; wm.MeterSize = txtMeterSize.Text; } }); } } using (TextWriter twWaterMeters = new StreamWriter(fiWaterMeters.FullName)) { xsWaterMeters.Serialize(twWaterMeters, waterMeters); } Close(); } private void Editor_FormClosing(object sender, FormClosingEventArgs e) { if (WaterDistribution.MeterEditorDisplaying == true) { WaterDistribution.MeterEditorDisplaying = false; Close(); } } } }
using System.Xml.Serialization; using StellarWaterPoint2.Models; namespace StellarWaterPoint2.WaterMeters { public partial class Manage : Form { public Manage() { InitializeComponent(); } private void ShowWaterMeters() { string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml"; List<WaterMeter> waterMeters = new List<WaterMeter>(); XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>)); FileInfo fiWaterMeters = new FileInfo(strWaterMeters); if (fiWaterMeters.Exists == true) { using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName)) { waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!; int counter = 1; lvwWaterMeters.Items.Clear(); foreach (WaterMeter wm in waterMeters) { ListViewItem lviWaterMeter = new ListViewItem(counter++.ToString()); lviWaterMeter.SubItems.Add(wm.MeterNumber); lviWaterMeter.SubItems.Add(wm.Make); lviWaterMeter.SubItems.Add(wm.Model); lviWaterMeter.SubItems.Add(wm.MeterSize); lvwWaterMeters.Items.Add(lviWaterMeter); } } } } private void Manage_Activated(object sender, EventArgs e) { ShowWaterMeters(); } private void Manage_FormClosing(object sender, FormClosingEventArgs e) { if (WaterDistribution.MetersDisplaying == true) { WaterDistribution.MetersDisplaying = false; Close(); } } } }
Testing the Application
After creating an application, you can test it. Of course, you must first execute it.
Practical Learning: Tesing the Application
Meter # | Make | Model | Meter Size | |
392-44-572 | Constance Technologies | TG-4822 | 5/8 Inches | |
938-75-869 | Stanford Trend | 266G | 1 1/2 Inches | |
588-29-663 | Estellano | NCF-226 | 3/4 Inches | |
186-92-805 | Lansome | 2800 | 1 1/2 Inches | |
799-28-461 | Kensa Sons | K-584-L | 3/4 Inches | |
386-48-057 | Estellano | NCF-226 | 3/4 Inches | |
837-06-836 | Lansome | 7400 | 5/8 Inches | |
207-94-835 | Constance Technologies | TG-6220 | 5/8 Inches | |
592-84-957 | Kensa Sons | D-497-H | 3/4 Inches | |
374-06-284 | Raynes Energica | i2022 | 3/4 Inches | |
186-99-757 | Kensa Sons | M-686-G | 1 1/2 Inches | |
630-07-055 | Lansome | 2800 | 3/4 Inches | |
827-50-248 | Standard | Trend | 428T | 3/4 Inches |
470-68-850 | Estellano | WRT-482 | 3/4 Inches | |
649-33-505 | Constance Technologies | BD-7000 | 5/8 Inches | |
306-82-497 | Lansome | 9000 | 3/4 Inches |
Account # | Meter # | First Name | Last Name | Address | City | County | State | ZIP-Code | |
9279-570-8394 | 799-28-461 | Thomas | Stones | 10252 Broward Ave #D4 | Frederick | Frederick | MD | 21703-6628 | |
2068-258-9486 | 186-92-805 | Ericka | Dellaney | 4819 East Munk Street | Whitehall | Fulton | PA | 17340-2277 | |
4820-375-2842 | 392-44-572 | Akhil | Koumari | 748 Red Hills Rd | Roanoke | VA | 24012-9726 | ||
6003-386-3955 | 374-06-284 | Mandiakandara | Marmoudi | 539 Avalon Court | Greenwood | Sussex | DE | 19950-2288 | |
9249-379-6848 | 588-29-663 | Richard | Eghert | 8280 Sligo North Way | Albright | Preston | WV | 26519-4626 | |
7518-302-6895 | 207-94-835 | Grace | Brenner | 4299 Peachtree Court | Rockville | Montgomery | MD | 20853-1512 | |
3028-502-9418 | 186-99-757 | Spencer | Kershaw | 338C Grayson Street | Gatchellville | York | PA | 17352-3808 | |
5293-957-3395 | 386-48-057 | Kelly | Davids | 10484 Greenway Avenue | Mt Storm | Grant | WV | 26739-6242 | |
2038-413-9680 | 938-75-869 | Amidou | Gomah | 2075 Rose Hills Avenue | Washington | DC | 20004-1818 | ||
7028-405-9381 | 306-82-497 | Jonathan | Simmings | 613 Meadowhill Road | Alonzaville | Shenandoah | VA | 22664-2662 | |
5938-074-5293 | 592-84-957 | Marie | Rath | 582G Dunhill Avenue | Lanham | Prince Georges | MD | 20706-4422 | |
1827-395-0203 | 470-68-850 | Sathyavanthara | Khooni | 10331 Chryswell Road | Washington | DC | 20008-5050 | ||
8027-304-6829 | 837-06-836 | Anthony | Clarcksons | 904 Augusta Drive | Blackbird | New Castle | DE | 19734-2606 | |
6699-396-2905 | 649-33-505 | Spencer | Reuter | 2850 Burnsweak Avenue | Silver Spring | Montgomery | MD | 20910-7272 | |
7080-583-5947 | 827-50-248 | Sandra | Moffat | 663 Sherry Wood East Street | Shimpstown | Franklin | PA | 17236-1116 |
Water Bill #: 847384 Account #: 3028-502-9418 Meter Reading Start Date: 10/03/2022 Meter Reading End Date: 01/06/2023 Counter Reading Start: 16 Counter Reading End: 21 Billing Days: 95 Payment Due Date: 01/21/2023 Late Payment Due Date: 02/05/2023
Water Bill # | Account # | Meter Reading Start Date | Meter Reading End Date | Counter Reading Start | Counter Reading End | Billing Days | Payment Due Date | Late Payment Due Date |
330820 | 7028-405-9381 | 10/03/2022 | 01/03/2023 | 9749 | 9906 | 92 | 01/18/2023 | 02/02/2023 |
468550 | 7518-302-6895 | 10/05/2022 | 01/09/2023 | 96 | 114 | 96 | 01/24/2023 | 02/08/2023 |
148274 | 9249-379-6848 | 10/05/2022 | 01/10/2023 | 260504 | 260555 | 97 | 01/25/2023 | 02/09/2023 |
326384 | 2068-258-9486 | 10/08/2022 | 01/10/2023 | 104837 | 104851 | 94 | 01/25/2023 | 02/09/2023 |
|
|||
Home | Copyright © 2010-2024, FunctionX, Inc. | Sunday 11 June 2023 | Home |
|