C# XML Application: Watts' A Loan
C# XML Application: Watts' A Loan
Introduction
XML is technology used to create text-based databases. This means that the records are saved in regular documents using normal text. For better management, the document must be appropriately formatted.
To apply some techniques for an XML-based application, we are going to create a graphical WinForms application in Microsoft Visual C#. The exercise is for a fictitious compamy named Watts' A Loan. The company issues financial loans for people and small companies.
Practical Learning: Creating the Application
Control | (Name) | Text |
Button | btnLoansContracts | Loans Contracts... |
Button | btnPayments | Payments... |
Button | btnEmployees | Employees... |
Button | btnClose | Close |
using System; using System.IO; using System.Windows.Forms; namespace WattsALoan1 { public partial class WattsALoan : Form { string strDrive; string strPrimaryFolder; public static DirectoryInfo diWattsALoan; public WattsALoan() { InitializeComponent(); } private void WattsALoan_Load(object sender, EventArgs e) { /* The files for this project will reside in a directory we will create. * By default, we will create a directory in a C: drive. If you are planning * to use a different directory, change the value of the following variable. * In the same way, if you are working on an operating system other than * Microsoft Windows, make the necessary changes. */ strDrive = @"C:\"; /* This is the main directory where the files of the project will reside. * If necessary, make the appropriate changes. */ strPrimaryFolder = strDrive + "Watts A Loan"; // Prepare the directory diWattsALoan = new DirectoryInfo(strPrimaryFolder); // Create the directory for this project diWattsALoan.Create(); } private void btnLoansContracts_Click(object sender, EventArgs e) { new LoansContracts().Show(); } private void btnPayments_Click(object sender, EventArgs e) { new Payments().Show(); } private void btnEmployees_Click(object sender, EventArgs e) { new Employees().Show(); } private void btnClose_Click(object sender, EventArgs e) { this.Close(); } } }
Employees
Since a company processes all types or records, it needs employees. Therefore, we will create the necessary objects for staff members.
Practical Learning: Introducing Employees
Control | (Name) | Text | Modifiers | Other Properties | |
Label | Employee #: | ||||
TextBox | txtEmployeeNumber | Public | |||
Label | First Name | ||||
TextBox | txtFirstName | Public | |||
Label | Last Name | ||||
TextBox | txtLastName | Public | |||
Label | Employee Title: | ||||
TextBox | txtEmployeeTitle | Public | |||
Button | btnOK | OK | DialogResult: OK | ||
Button | btnCancel | Cancel | DialogResult: Cancel |
Form Properties/p>
FormBorderStyle: | FixedDialog |
Text | Watts' A Loan - Employee Editor |
StartPosition | CenterScreen |
AcceptButton | btnOK |
CancelButton | btnCancel |
MaximizeBox | False |
MinimizeBox | False |
Control | (Name) | Text | Other Properties |
ListView | lvwEmployees |
FullRowSelect: True GridLines: True View: Details Anchor: Top, Bottom, Left, Right |
|
Button | btnClose | Close | Anchor: Bottom, Right |
List View Columns
(Name) | Text | TextAlign | Width |
colCounter | # | 20 | |
colEmployeeNumber | Employee # | Center | 75 |
colFirstName | First Name | 75 | |
colLastName | Last Name | 75 | |
colEmployeeTitle | Employee Title | 185 |
Form Properties/p>
FormBorderStyle: | FixedDialog |
Text | Watts' A Loan - Employees |
StartPosition | CenterScreen |
MaximizeBox | False |
using System.Xml; namespace WattsALoan1 { public partial class Employees : Form { public Employees() { InitializeComponent(); } void Display() { FileInfo[] fiEmployees = WattsALoan.diWattsALoan.GetFiles(); /* When we display records in a list view, we will keep a count of those records. * To do that, we will use the following intergral variable. */ int i = 1; // Before displaying the records in a list view, we first remove all records from it. lvwEmployees.Items.Clear(); /* The record of each employee is create in its own file. * Therefore, to access the record of an employee, we open its file... */ foreach (FileInfo file in fiEmployees) { XmlDocument xdEmployee = new XmlDocument(); // Since we will open the record as a stream, we declare a FileStream variable FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); xdEmployee.Load(fsEmployees); XmlNode xnEmployee = xdEmployee.DocumentElement; /* As we are preparingto display the display, we need a list view item. * we will display a counter in the first column. * Therefore, we store the counter in the first column. */ ListViewItem lviEmployee = new ListViewItem(i.ToString()); // We then locate the value of each column and add it to the list view item lviEmployee.SubItems.Add(xnEmployee.FirstChild.FirstChild.InnerText); lviEmployee.SubItems.Add(xnEmployee.FirstChild.FirstChild.NextSibling.InnerText); lviEmployee.SubItems.Add(xnEmployee.FirstChild.FirstChild.NextSibling.NextSibling.InnerText); lviEmployee.SubItems.Add(xnEmployee.FirstChild.FirstChild.NextSibling.NextSibling.NextSibling.InnerText); // After preparing the list view item, we add it to the list view that will display the record(s). lvwEmployees.Items.Add(lviEmployee); // Before moving to the next record, we increment the counter i++; // We close the file stream that we had created fsEmployees.Close(); } } private void Employees_Load(object sender, EventArgs e) { Display(); } private void btnEmployee_Click(object sender, EventArgs e) { // We have a dialog box that can be used to create a new employee record or to edit one EmployeeEditor ee = new EmployeeEditor(); /* Because one dialog box can be used to both create a new record or to edit * an existing record, when displaying that dialog box, we should specify * its caption to indicate the dialog box's purpose. */ ee.Text = "Watts' A Loan - New Employee"; /* Now display the dialog box. Eventually, find out whether * the user had clicked the OK button when closing the dialog box. */ if (ee.ShowDialog() == DialogResult.OK) { // If the user had clicked OK (or pressed Enter), ... if (string.IsNullOrEmpty(ee.txtEmployeeNumber.Text)) { // ... make sure the user provided the employee number... MessageBox.Show("You must provide a (unique) employee number for each staff member.", "Watts' A Loan - Employees", MessageBoxButtons.OK); // ... if not, don't do nothing return; } if (string.IsNullOrEmpty(ee.txtLastName.Text)) { // In the same way, make sure that the user can identify the new employee with at least a last name MessageBox.Show("We need a name for the new employee. Please provide at least a last name.", "Watts' A Loan - Employees", MessageBoxButtons.OK); return; } XmlDocument xdEmployees = new XmlDocument(); string strEmployee = WattsALoan.diWattsALoan.FullName + @"\" + ee.txtEmployeeNumber.Text + ".xml"; XmlElement xeEmployee = xdEmployees.CreateElement("employee"); xdEmployees.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<employees><employee><employee-number>" + ee.txtEmployeeNumber.Text + "</employee-number>" + "<first-name>" + ee.txtFirstName.Text + "</first-name>" + "<last-name>" + ee.txtLastName.Text + "</last-name>" + "<employee-title>" + ee.txtEmployeeTitle.Text + "</employee-title></employee></employees>"); using (FileStream fsStudies = new FileStream(strEmployee, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdEmployees.Save(fsStudies); } } // After whatever operation occurred, refresh the list view Display(); } private void lvwEmployees_DoubleClick(object sender, EventArgs e) { bool found = false; string strEmployeeNumber = string.Empty; // We will need to be able to open dialog box of employees EmployeeEditor ee = new EmployeeEditor(); // Prepare an XML DOM object /* 1. A record must exist in the list view. * 2. We want to be able to work on only one record. * 3. A record, and only one record, must have been selected; otherwise, don't do nothing. */ if ((lvwEmployees.SelectedItems.Count == 0) || (lvwEmployees.SelectedItems.Count > 1)) return; // Create a FileInfo object to to get a collection of the files in the target folder FileInfo[] fiEmployees = WattsALoan.diWattsALoan.GetFiles(); // Get a reference (a ListViewItem object) to the record that was double-clicked ListViewItem lviEmployee = lvwEmployees.SelectedItems[0]; // Check each file in the collection foreach (FileInfo file in fiEmployees) { // If the file name is the same as the employee number, ... if (file.Name.Substring(0, 7) == lviEmployee.SubItems[1].Text) { //... make a note found = true; // Create a file stream that will be used to open the file using (FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { XmlDocument xdEmployee = new XmlDocument(); xdEmployee.Load(fsEmployees); XmlNode xnEmployee = xdEmployee.DocumentElement; // Display the values of that record in the dialog box ee.txtEmployeeNumber.Text = xnEmployee.FirstChild.FirstChild.InnerText; ee.txtFirstName.Text = xnEmployee.FirstChild.FirstChild.NextSibling.InnerText; ee.txtLastName.Text = xnEmployee.FirstChild.FirstChild.NextSibling.NextSibling.InnerText; ee.txtEmployeeTitle.Text = xnEmployee.FirstChild.FirstChild.NextSibling.NextSibling.NextSibling.InnerText; // When the dialog box displays, we don't want to allow the user to change the employee number ee.txtEmployeeNumber.Enabled = false; // Make a note on the employee number strEmployeeNumber = ee.txtEmployeeNumber.Text; } } } if (found == true) { // Display the dialog box if (ee.ShowDialog() == DialogResult.OK) { // Make sure the user provides a (or doesn't change the) last name of the employee if (string.IsNullOrEmpty(ee.txtLastName.Text)) { MessageBox.Show("We need a name for the new employee. Please provide at least a last name.", "Watts' A Loan - Employees", MessageBoxButtons.OK); return; } foreach (FileInfo file in fiEmployees) { if (file.Name.Substring(0, 7) == ee.txtEmployeeNumber.Text) { XmlDocument xdEmployees = new XmlDocument(); string strEmployee = WattsALoan.diWattsALoan.FullName + @"\" + ee.txtEmployeeNumber.Text + ".xml"; XmlElement xeEmployee = xdEmployees.CreateElement("employee"); xdEmployees.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<employees><employee><employee-number>" + ee.txtEmployeeNumber.Text + "</employee-number>" + "<first-name>" + ee.txtFirstName.Text + "</first-name>" + "<last-name>" + ee.txtLastName.Text + "</last-name>" + "<employee-title>" + ee.txtEmployeeTitle.Text + "</employee-title></employee></employees>"); using (FileStream fsStudies = new FileStream(strEmployee, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdEmployees.Save(fsStudies); } } } } } Display(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Loans Contracts
Probably the primary business operation of our type of application is to process a loan. To support this, we will create a form for loan applications and a form to display the loans contracts.
Control | (Name) | Text | TextAlign | Modifiers | Other Properties |
Label | Loan #: | ||||
TextBox | txtLoanNumber | Public | |||
Label | Date Allocated: | ||||
DateTimePicker | dtpDateAllocated | Public | |||
GroupBox | Loan Processed By (Employee) | ||||
Label | Employee #: | ||||
TextBox | txtEmployeeNumber | Public | |||
TextBox | txtEmployeeDetails | Public | |||
GroupBox | Loan Applicant (Customer Information) | ||||
Label | First Name: | ||||
TextBox | txtFirstName | Public | |||
Label | Last Name: | ||||
TextBox | txtLastName | Public | |||
GroupBox | Loan Setup Details | ||||
Label | Loan Type: | ||||
ComboBox | cbxLoansTypes | Public | Items:
Other Personal Cash Car Financing Boat Financing Furniture Purchase Musical Instrument |
||
Label | Loan Amount: | ||||
TextBox | txtLoanAmount | TextAlign: Right | Public | ||
Label | Interest Rate: | ||||
TextBox | txtInterestRate | TextAlign: Right | Public | ||
Label | % | ||||
Label | Periods: | ||||
TextBox | txtPeriods | TextAlign: Right | Public | ||
Label | Months | ||||
GroupBox | Loan Summary | ||||
Label | Interest Amount: | ||||
TextBox | txtInterestAmount | TextAlign: Right | Public | ||
Label | Future Value: | ||||
TextBox | txtFutureValue | TextAlign: Right | Public | ||
Label | Monthly Payment: | ||||
TextBox | txtMonthlyPayment | TextAlign: Right | Public | ||
Label | Current Balance: | ||||
TextBox | txtCurrentBalance | TextAlign: Right | Public | ||
Label | Payment Start Date: | ||||
DateTimePicker | dtpPaymentStartDate | Public | |||
Button | btnOK | OK | DialogResult: OK | ||
Button | btnCancel | Cancel | DialogResult: Cancel |
Form Properties
FormBorderStyle: | FixedDialog |
Text | Watts' A Loan - Loan Application |
StartPosition | CenterScreen |
MaximizeBox | False |
MinimizeBox | False |
using System; using System.IO; using System.Xml; using System.Windows.Forms; namespace WattsALoan1 { public partial class LoanApplication : Form { public LoanApplication() { InitializeComponent(); } private void txtEmployeeNumber_Leave(object sender, EventArgs e) { /* If the user doesn't provide an employee number, don't do nothing. */ if (string.IsNullOrEmpty(txtEmployeeNumber.Text)) return; /* Because each Employee record is created in its own file, get the collection * of files from that folder. */ FileInfo[] fiEmployees = WattsALoan.diWattsALoan.GetFiles(); // Visit each file in the folder foreach (FileInfo file in fiEmployees) { /* Get the six digits and symbol that make up the name of a file: 000-000. * Compare that name with the employee number that the user typed.*/ if (file.Name.Substring(0, 7) == txtEmployeeNumber.Text) { // Create a file stream that will be used to open the file using (FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { XmlDocument xdEmployee = new XmlDocument(); xdEmployee.Load(fsEmployees); /* Create a string as a combination of the last and first name of * the employee. Display that string in the Employee Details text box:*/ txtEmployeeDetails.Text = xdEmployee.DocumentElement.FirstChild.FirstChild.NextSibling.InnerText + ", " + xdEmployee.DocumentElement.FirstChild.FirstChild.NextSibling.NextSibling.InnerText; } // Since you found an employee whose file matches the employee number, stop searching return; } else txtEmployeeDetails.Text = ""; } } } }
Control | (Name) | Text | Other Properties |
ListView | lvwLoansContracts |
FullRowSelect: True GridLines: True View: Details Anchor: Top, Bottom, Left, Right |
|
Button | btnLoanApplication | Loan Application... | Bottom, Right |
Button | btnPayments | Payments... | Bottom, Right |
Button | btnEmployee | Employees... | Bottom, Right |
Button | btnClose | Close | Anchor: Bottom, Right |
List View Columns
(Name) | Text | TextAlign | Width |
colCounter | # | 20 | |
colLoanNumber | Loan # | Center | 55 |
colDateAllocated | Date Allocated | Right | 85 |
colEmployeeDetails | Processed By | 270 | |
colCustomer | Customer | 95 | |
colLoanType | Loan Type | 110 | |
colLoanAmount | Loan Amt | Right | |
colInterestRate | Intrst Rate | Right | 65 |
colPeriods | Periods | 65 | |
colInterestAmount | Interest Amt # | Right | 75 |
colFutureValue | Future Value | Right | 75 |
colMonthlyPayment | Monthly Pmt | Right | 70 |
colPaymentStartDate | Pmt Start Date | Center | 85 |
colBalance | Balance | Right | 65 |
Form Properties
Text | Watts' A Loan - Loans Contracts |
StartPosition | CenterScreen |
MaximizeBox | False |
using System; using System.IO; using System.Xml; using System.Windows.Forms; namespace WattsALoan1 { public partial class LoansContracts : Form { public LoansContracts() { InitializeComponent(); } void Display() { string strEmployee = string.Empty; FileInfo[] fiWattsALoan = WattsALoan.diWattsALoan.GetFiles(); int i = 1; lvwLoansContracts.Items.Clear(); string strFileName = WattsALoan.diWattsALoan.FullName + @"\LoansContracts.xml"; if (File.Exists(strFileName) == true) { using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) { XmlDocument xdContracts = new XmlDocument(); xdContracts.Load(fsLoansContracts); XmlNodeList xnlContracts = xdContracts.GetElementsByTagName("loan-number"); foreach (XmlNode xnContract in xnlContracts) { ListViewItem lviLoanContract = new ListViewItem(i.ToString()); // # lviLoanContract.SubItems.Add(xnContract.InnerText); // Loan # lviLoanContract.SubItems.Add(xnContract.NextSibling.InnerText); // Date Allocated foreach (FileInfo fileEmployee in fiWattsALoan) { if (fileEmployee.Name.Substring(0, 7) == xnContract.NextSibling.NextSibling.InnerText) { XmlDocument xdEmployees = new XmlDocument(); using (FileStream fsEmployees = new FileStream(fileEmployee.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdEmployees.Load(fsEmployees); strEmployee = xdEmployees.DocumentElement.FirstChild.FirstChild.InnerText + " - " + xdEmployees.DocumentElement.FirstChild.FirstChild.NextSibling.InnerText + ", " + xdEmployees.DocumentElement.FirstChild.FirstChild.NextSibling.NextSibling.InnerText; } } } lviLoanContract.SubItems.Add(strEmployee); // Processed By lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.InnerText + ", " + xnContract.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); // Customer last name, first name lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); // loan type lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); // Loan Amount lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); // Interest Rate lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText + " months"); lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); lviLoanContract.SubItems.Add(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); lvwLoansContracts.Items.Add(lviLoanContract); i++; } } } } private void LoansContracts_Load(object sender, EventArgs e) { Display(); } private void btnLoanApplication_Click(object sender, EventArgs e) { bool fileFound = false; LoanApplication la = new LoanApplication(); XmlDocument xdLoansContracts = new XmlDocument(); FileInfo[] fiLoansContracts = WattsALoan.diWattsALoan.GetFiles(); string strFileName = WattsALoan.diWattsALoan.FullName + @"\LoansContracts.xml"; foreach (FileInfo file in fiLoansContracts) { if (file.Name == "LoansContracts.xml") { fileFound = true; } } if( fileFound == true ) { using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdLoansContracts.Load(fsLoansContracts); } } else { xdLoansContracts.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<loans-contracts></loans-contracts>"); } using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdLoansContracts.Save(fsLoansContracts); } if (la.ShowDialog() == DialogResult.OK) { if (string.IsNullOrEmpty(la.txtLoanNumber.Text)) { MessageBox.Show("You must provide a (unique) code for the loan number.", "Watts' A Loan - Loan Application", MessageBoxButtons.OK); return; } if (string.IsNullOrEmpty(la.txtEmployeeDetails.Text)) { /* If the Employee Details text box is empty, it is an indication that the * user did not provide a (valid) employee number. Here, we will * consider that the user failed to provide an employee number. */ MessageBox.Show("You must provide the employee number of the staff member who processed the loan.", "Watts' A Loan - Loan Application", MessageBoxButtons.OK); return; } if (string.IsNullOrEmpty(la.txtLoanAmount.Text)) { MessageBox.Show("You must specify the amount of the loan. Please provide also all the values related to the loan.", "Watts' A Loan - Loan Application", MessageBoxButtons.OK); return; } XmlElement xeLoanContract = xdLoansContracts.CreateElement("loan-contract"); xeLoanContract.InnerXml = "<loan-number>" + la.txtLoanNumber.Text + "</loan-number>" + "<date-allocated>" + la.dtpDateAllocated.Value.ToShortDateString() + "</date-allocated>" + "<employee-number>" + la.txtEmployeeNumber.Text + "</employee-number>" + "<customer-first-name>" + la.txtFirstName.Text + "</customer-first-name>" + "<customer-last-name>" + la.txtLastName.Text + "</customer-last-name>" + "<loan-type>" + la.cbxLoanTypes.Text + "</loan-type>" + "<loan-amount>" + la.txtLoanAmount.Text + "</loan-amount>" + "<interest-rate>" + la.txtInterestRate.Text + "</interest-rate>" + "<periods>" + la.txtPeriods.Text + "</periods>" + "<interest-amount>" + la.txtInterestAmount.Text + "</interest-amount>" + "<future-value>" + la.txtFutureValue.Text + "</future-value>" + "<monthly-payment>" + la.txtMonthlyPayment.Text + "</monthly-payment>" + "<payment-start-date>" + la.dtpPaymentStartDate.Value.ToShortDateString() + "</payment-start-date>" + "<current-balance>" + la.txtFutureValue.Text + "</current-balance>"; xdLoansContracts.DocumentElement.AppendChild(xeLoanContract); using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdLoansContracts.Save(fsLoansContracts); } } Display(); } private void lvwLoansContracts_DoubleClick(object sender, EventArgs e) { bool found = false; string strEmployeeNumber = string.Empty; LoanApplication la = new LoanApplication(); XmlDocument xdLoansContracts = new XmlDocument(); string strFileName = WattsALoan.diWattsALoan.FullName + @"\LoansContracts.xml"; FileInfo[] fiWattsALoan = WattsALoan.diWattsALoan.GetFiles(); if ((lvwLoansContracts.SelectedItems.Count == 0) || (lvwLoansContracts.SelectedItems.Count > 1)) return; ListViewItem lviLoanContract = lvwLoansContracts.SelectedItems[0]; if (File.Exists(strFileName) == true) { using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdLoansContracts.Load(fsLoansContracts); XmlNodeList xnlContracts = xdLoansContracts.GetElementsByTagName("loan-number"); foreach (XmlNode xnContract in xnlContracts) { if (xnContract.InnerText == lviLoanContract.SubItems[1].Text) { found = true; la.txtLoanNumber.Text = xnContract.InnerText; // Loan # la.dtpDateAllocated.Value = DateTime.Parse(xnContract.NextSibling.InnerText); // Date Allocated strEmployeeNumber = xnContract.NextSibling.NextSibling.InnerText; // Processed By la.txtEmployeeNumber.Text = xnContract.NextSibling.NextSibling.InnerText; la.txtFirstName.Text = xnContract.NextSibling.NextSibling.NextSibling.InnerText; // Customer first name la.txtLastName.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Customer last name la.cbxLoanTypes.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // loan type la.txtLoanAmount.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Loan Amount la.txtInterestRate.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Interest Rate la.txtPeriods.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Periods la.txtInterestAmount.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Interest Amount la.txtFutureValue.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Future Value la.txtMonthlyPayment.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Monthly Payment la.dtpPaymentStartDate.Value = DateTime.Parse(xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); // Payment Start Date la.txtCurrentBalance.Text = xnContract.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; // Current Balance foreach (FileInfo fileEmployee in fiWattsALoan) { if (fileEmployee.Name.Substring(0, 7) == strEmployeeNumber) { XmlDocument xdEmployees = new XmlDocument(); using (FileStream fsEmployees = new FileStream(fileEmployee.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdEmployees.Load(fsEmployees); la.txtEmployeeDetails.Text = xdEmployees.DocumentElement.FirstChild.FirstChild.InnerText + " - " + xdEmployees.DocumentElement.FirstChild.FirstChild.NextSibling.InnerText + ", " + xdEmployees.DocumentElement.FirstChild.FirstChild.NextSibling.NextSibling.InnerText; } found = true; } } } } } } if (found == true) { if (la.ShowDialog() == DialogResult.OK) { using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) { xdLoansContracts.Load(fsLoansContracts); } XmlNodeList xnlContracts = xdLoansContracts.GetElementsByTagName("loan-number"); foreach (XmlNode xnContract in xnlContracts) { if (xnContract.InnerText == lviLoanContract.SubItems[1].Text) { xnContract.ParentNode.InnerXml = "<loan-number>" + la.txtLoanNumber.Text + "</loan-number>" + "<date-allocated>" + la.dtpDateAllocated.Value.ToShortDateString() + "</date-allocated>" + "<employee-number>" + la.txtEmployeeNumber.Text + "</employee-number>" + "<customer-first-name>" + la.txtFirstName.Text + "</customer-first-name>" + "<customer-last-name>" + la.txtLastName.Text + "</customer-last-name>" + "<loan-type>" + la.cbxLoanTypes.Text + "</loan-type>" + "<loan-amount>" + la.txtLoanAmount.Text + "</loan-amount>" + "<interest-rate>" + la.txtInterestRate.Text + "</interest-rate>" + "<periods>" + la.txtPeriods.Text + "</periods>" + "<interest-amount>" + la.txtInterestAmount.Text + "</interest-amount>" + "<future-value>" + la.txtFutureValue.Text + "</future-value>" + "<monthly-payment>" + la.txtMonthlyPayment.Text + "</monthly-payment>" + "<payment-start-date>" + la.dtpPaymentStartDate.Value.ToShortDateString() + "</payment-start-date>" + "<current-balance>" + la.txtFutureValue.Text + "</current-balance>"; using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdLoansContracts.Save(fsLoansContracts); } break; } } } } Display(); } private void btnPayments_Click(object sender, EventArgs e) { new Payments().Show(); } private void btnEmployees_Click(object sender, EventArgs e) { new Employees().Show(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Payments on a Loan
Loans have to be paid. To support this, we first created a form that can display a list of payments made on loads. Now we will create a form that that can be used to process a payment.
Practical Learning: Making Loans Payments
Control | (Name) | Text | Modifiers | Other Properties |
Label | Payment #: | |||
TextBox | txtPaymentNumber | Public | ||
Label | Payment Date: | |||
DateTimePicker | dtpPaymentDate | Public | ||
GroupBox | Payment Processed By | |||
Label | Employee #: | |||
TextBox | txtEmployeeNumber | Public | ||
TextBox | txtEmployeeDetails | Public | ||
GroupBox | Payment Details | |||
Label | Loan #: | |||
TextBox | txtLoanNumber | Public | ||
TextBox | txtLoanDetails | Public | ScrollBars: Horizontal Multiline: True |
|
Label | Amount Paid: | |||
TextBox | txtAmountPaid | Public | TextAlign: Right | |
Label | Current Balance: | |||
TextBox | txtCurrentBalance | Public | TextAlign: Right | |
Button | btnOK | OK | ||
Button | btnCancel | Cancel |
Form Properties
Text: | Watts' A Loan - Payment Editor |
FormBorderStyle: | FixedDialog |
StartDisposition: | CenterScreen |
MaximizeBox | False |
MinimizeBox | False |
FormBorderStyle: | FixedDialog |
using System; using System.IO; using System.Xml; using System.Windows.Forms; namespace WattsALoan1 { public partial class PaymentEditor : Form { public PaymentEditor() { InitializeComponent(); } private void txtEmployeeNumber_Leave(object sender, EventArgs e) { /* If the user doesn't provide an employee number, don't do nothing. */ if (string.IsNullOrEmpty(txtEmployeeNumber.Text)) return; /* Because each Employee record is created in its own file, get the collection * of files from that folder. */ FileInfo[] fiEmployees = WattsALoan.diWattsALoan.GetFiles(); // Visit each file in the folder foreach (FileInfo file in fiEmployees) { /* Get the six digits and symbol that make up the name of a file: 000-000. * Compare that name with the employee number that the user typed.*/ if (file.Name.Substring(0, 7) == txtEmployeeNumber.Text) { // Create a file stream that will be used to open the file using (FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { XmlDocument xdEmployee = new XmlDocument(); xdEmployee.Load(fsEmployees); /* Create a string as a combination of the last and first name of * the employee. Display that string in the Employee Details text box:*/ txtEmployeeDetails.Text = xdEmployee.DocumentElement.FirstChild.FirstChild.NextSibling.InnerText + ", " + xdEmployee.DocumentElement.FirstChild.FirstChild.NextSibling.NextSibling.InnerText; } // Since you found an employee whose file matches the employee number, stop searching return; } else txtEmployeeDetails.Text = ""; } } private void txtLoanNumber_Leave(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtLoanNumber.Text)) return; double balance = 0.00; string emplHolder = string.Empty; string strLoanSummary1 = string.Empty, strLoanSummary2 = string.Empty; string strEmployeeNumber = string.Empty; string strLoanProcessor = string.Empty; FileInfo[] fiContracts = WattsALoan.diWattsALoan.GetFiles(); string strFileName = WattsALoan.diWattsALoan.FullName + @"\LoansContracts.xml"; if( File.Exists(strFileName) == true ) { using( FileStream fsLoans = new FileStream(strFileName, FileMode.Open, FileAccess.Read) ) { XmlDocument xdLoansContracts = new XmlDocument(); xdLoansContracts.Load(fsLoans); XmlNodeList xnlLoans = xdLoansContracts.GetElementsByTagName("loan-number"); foreach (XmlNode xnLoan in xnlLoans) { if( xnLoan.InnerText == txtLoanNumber.Text) { strLoanSummary1 = xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText + " loan processed by "; strEmployeeNumber = xnLoan.NextSibling.NextSibling.InnerText; strLoanSummary2 = " on " + xnLoan.NextSibling.InnerText + " for " + xnLoan.NextSibling.NextSibling.NextSibling.InnerText + " " + xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.InnerText + " for the amount of $" + xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText + " for " + xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText + " months, paid $" + xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText + "/month. " + "Current Balance: $" + xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; txtAmountPaid.Text = xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; balance = (double.Parse(xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) - double.Parse(xnLoan.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText)); break; } } } foreach (FileInfo file in fiContracts) { if (file.Name.Substring(0, 7) == strEmployeeNumber) { using (FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { XmlDocument xdEmployee = new XmlDocument(); xdEmployee.Load(fsEmployees); strLoanProcessor = xdEmployee.DocumentElement.FirstChild.FirstChild.NextSibling.InnerText + " " + xdEmployee.DocumentElement.FirstChild.FirstChild.NextSibling.NextSibling.InnerText + " (" + strEmployeeNumber + ")"; } } } txtLoanDetails.Text = strLoanSummary1 + strLoanProcessor + strLoanSummary2; txtCurrentBalance.Text = balance.ToString("F"); } } } }
Control | (Name) | Text | Other Properties |
ListView | lvwLoansPayments |
FullRowSelect: True GridLines: True View: Details Anchor: Top, Bottom, Left, Right |
|
Button | btnPaymentEditor | New Payment... | Anchor: Bottom, Right |
Button | btnLoanApplication | Loan Application... | Anchor: Bottom, Right |
Button | btnEmployees | Employees... | Anchor: Bottom, Right |
Button | btnClose | Close | Anchor: Bottom, Right |
List View Columns
(Name) | Text | TextAlign | Width |
colCounter | # | 20 | |
colPaymentNumber | Payment # | Center | 75 |
colPaymentDate | Payment Date | Right | 90 |
colEmployeeDetails | Processed By | 165 | |
colLoanNumber | Loan # | 80 | |
colAmountPaid | Amt Paid | Right |
using System; using System.IO; using System.Xml; using System.Windows.Forms; namespace WattsALoan1 { public partial class Payments : Form { public Payments() { InitializeComponent(); } void Display() { FileInfo[] fiWattsALoan = WattsALoan.diWattsALoan.GetFiles(); string strEmployee = string.Empty, strContract = string.Empty; int i = 1; lvwLoansPayments.Items.Clear(); string strFileName = WattsALoan.diWattsALoan.FullName + @"\Payments.xml"; if (File.Exists(strFileName) == true) { using (FileStream fsPayments = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) { XmlDocument xdPayments = new XmlDocument(); xdPayments.Load(fsPayments); XmlNodeList xnlPayments = xdPayments.GetElementsByTagName("payment-number"); foreach (XmlNode xnPayment in xnlPayments) { ListViewItem lviPayment = new ListViewItem(i.ToString()); // # lviPayment.SubItems.Add(xnPayment.InnerText); // Loan # lviPayment.SubItems.Add(xnPayment.NextSibling.InnerText); // Date Allocated foreach (FileInfo fileEmployee in fiWattsALoan) { if (fileEmployee.Name.Substring(0, 7) == xnPayment.NextSibling.NextSibling.InnerText) { XmlDocument xdEmployees = new XmlDocument(); using (FileStream fsEmployees = new FileStream(fileEmployee.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdEmployees.Load(fsEmployees); strEmployee = xdEmployees.DocumentElement.FirstChild.FirstChild.InnerText + " - " + xdEmployees.DocumentElement.FirstChild.FirstChild.NextSibling.InnerText + ", " + xdEmployees.DocumentElement.FirstChild.FirstChild.NextSibling.NextSibling.InnerText; } } } lviPayment.SubItems.Add(strEmployee); // Processed By lviPayment.SubItems.Add(xnPayment.NextSibling.NextSibling.NextSibling.InnerText); // Customer last name, first name lviPayment.SubItems.Add(xnPayment.NextSibling.NextSibling.NextSibling.NextSibling.InnerText); // Customer last name, first name lvwLoansPayments.Items.Add(lviPayment); i++; } } } } private void Payments_Load(object sender, EventArgs e) { Display(); } private void btnPaymentEditor_Click(object sender, EventArgs e) { PaymentEditor pe = new PaymentEditor(); XmlDocument xdPayments = new XmlDocument(); FileInfo[] fiPayments = WattsALoan.diWattsALoan.GetFiles(); string strFileName = WattsALoan.diWattsALoan.FullName + @"\Payments.xml"; if( File.Exists(strFileName) ) { using (FileStream fsLoansContracts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdPayments.Load(fsLoansContracts); } } else { xdPayments.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<loans-payments></loans-payments>"); } using (FileStream fsPayments = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdPayments.Save(fsPayments); } if (pe.ShowDialog() == DialogResult.OK) { if (string.IsNullOrEmpty(pe.txtPaymentNumber.Text)) { MessageBox.Show("You must provide a (unique) payment number.", "Watts' A Loan - Loan Payment", MessageBoxButtons.OK); return; } if (string.IsNullOrEmpty(pe.txtLoanNumber.Text)) { MessageBox.Show("You must specify the loan number of the loan for which the payment is being made.", "Watts' A Loan - Loan Payment", MessageBoxButtons.OK); return; } if (string.IsNullOrEmpty(pe.txtEmployeeDetails.Text)) { /* If the Employee Details text box is empty, it is an indication that the * user did not provide a (valid) employee number. Here, we will * consider that the user failed to provide an employee number. */ MessageBox.Show("You must provide the employee number of the staff member who processed the loan.", "Watts' A Loan - Loan Application", MessageBoxButtons.OK); return; } XmlElement xePayment = xdPayments.CreateElement("payment"); xePayment.InnerXml = "<payment-number>" + pe.txtPaymentNumber.Text + "</payment-number>" + "<payment-date>" + pe.dtpPaymentDate.Value.ToShortDateString() + "</payment-date>" + "<employee-number>" + pe.txtEmployeeNumber.Text + "</employee-number>" + "<loan-number>" + pe.txtLoanNumber.Text + "</loan-number>" + "<amount-paid>" + pe.txtAmountPaid.Text + "</amount-paid>"; xdPayments.DocumentElement.AppendChild(xePayment); using (FileStream fsPayments = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdPayments.Save(fsPayments); } } Display(); } private void btnLoanApplication_Click(object sender, EventArgs e) { new LoanApplication().ShowDialog(); } private void btnEmployees_Click(object sender, EventArgs e) { new Employees().Show(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Application Testing
To make sure an application is behaving as intended, you should test it.
Practical Learning: Testing the Application
Employee # | First Name | Last Name | Employee Title |
293-747 | Catherine | Watts | Owner - General Manager |
836-486 | Thomas | Felton | Accounts Representative |
492-947 | Caroline | Wernick | Assistant Manager |
240-750 | Catherine | Donato | Accounts Representative |
804-685 | Melissa | Browns | Customer Accounts Representative |
429-374 | Denise | Leighton | Accounts Manager |
Loan Number: 100001 Date Allocated: January 18, 2021 Employee #: 429-374 First Name: Joanne Last Name: Kennan Loan Type: Personal Cash Loan Amount: 2500 Interest Rate: 14.65 Periods: 36 Interest Amount: 1,483.51 Future Value: 3,983.51 Monthly Payment: 87.44 Current Balance: 3,983.51 Payment Start Date: March 1st, 2021
Loan Number: 100002 Date Allocated: February 22, 2021 Employee #: 492-947 First Name: Stephen Last Name: Haller Loan Type: Boat Financing Loan Amount: 46500 Interest Rate: 4.95 Periods: 60 Interest Amount: 13,027.79 Future Value: 59,527.79 Monthly Payment: 876.45 Payment Start Date: March 1st, 2021 Current Balance: 59,527.79
Loan Number: 100003 Date Allocated: March 12, 2021 Employee #: 429-374 First Name: Annette Last Name: Vargas Loan Type: Furniture Purchase Loan Amount: 2258.75 Interest Rate: 17.35 Periods: 36 Interest Amount: 1,528.29 Future Value: 3,787.04 Monthly Payment: 80.92 Payment Start Date: May 1st, 2021 Current Balance: 3,787.04
Loan Number: 100004 Date Allocated: March 12, 2021 Employee #: 836-486 First Name: Gérard Last Name: Haloney Loan Type: Car Financing Loan Amount: 22748 Interest Rate: 10.25 Periods: 60 Interest Amount: 15,146.30 Future Value: 37,894.30 Monthly Payment: 486.13 Payment Start Date: May 1st, 2021 Current Balance: 37,894.30
Payment Number: 385970 Payment Date: March 03, 2021 Employee #: 429-374 Loan #: 100001
Payment Number: 953746 Payment Date: March 30, 2021 Employee #: 492-947 Loan #: 100002
Payment Number: 503940 Payment Date: April 30, 2021 Employee #: 836-486 Loan #: 100002
|
|||
Previous | Copyright © 2001-2022, C# Key | Saturday 07 May 2022 | Next |
|