diff --git a/AdvertsingProfitControl/APCDatabase Template Script.sql b/AdvertsingProfitControl/APCDatabase Template Script.sql new file mode 100644 index 0000000..5dac4cf --- /dev/null +++ b/AdvertsingProfitControl/APCDatabase Template Script.sql @@ -0,0 +1,172 @@ +--File Version: 1.0.0.0 for SQL Server +--Purpose: Creates an empty database template in SQL for the Advertising Profit Control software; master template. +--Notes: This version does not implement any table relationships, its just flat data tables. +-- Currency will be represented with DECIMAL(19,2) as the standard. From stackoverflow: +-- http://stackoverflow.com/questions/628637/best-data-type-for-storing-currency-values-in-a-mysql-database + +--Create the database called "AdvertisingProfitControl". +CREATE DATABASE AdvertisingProfitControl + +--Begin creating the tables for the database. +CREATE TABLE ActualSales +( +Id INTEGER NOT NULL PRIMARY KEY, +--Sold and sale price need to be stored as a string since they need to support # Bin(s) +--and $#.##/# formatting respectively. +Sold VARCHAR(128), +SalePrice VARCHAR(128), +--Might be over kill to store money like this but better safe then sorry. +TotalSales DECIMAL(19,2), +Cost DECIMAL(19,2), +ProfitReturn DECIMAL(19,2), +TotalProfitReturn DECIMAL(19,2), +--The attributes of the row can not be null, and neither can the foreign keys. +RowPosition INTEGER NOT NULL, +--A precision of two digits should be everything we need for the row attribute. +RowAttribute INTEGER NOT NULL, +--Now begin all the foreign keys. +FkAdItemId INTEGER NOT NULL, +FkAdSpecialGoupId INTEGER NOT NULL, +FkDateId INTEGER NOT NULL +) + +CREATE TABLE AdItem +( +Id INTEGER NOT NULL PRIMARY KEY, +AdItem VARCHAR(255) NOT NULL, +Description VARCHAR(255) --Optional field may be used later one. +) + +CREATE TABLE AdSpecial +( +Id INTEGER NOT NULL PRIMARY KEY, +AdSpecial VARCHAR(255) NOT NULL, +Description VARCHAR(255) --Optional field may be used later one, most likely in a tool tip. +) + +CREATE TABLE Note --Comment is a reserved word so the table and column had to be renamed to "Note" instead. +( +Id INTEGER NOT NULL PRIMARY KEY, +--The current version (1.0.0.0) only allows the user to enter a max of 256 characters into the comments box. +Note VARCHAR(256) NOT NULL, +FkDateId INTEGER NOT NULL +) + +CREATE TABLE CostAnalysis +( +Id INTEGER NOT NULL PRIMARY KEY, +SalesPerManHour DECIMAL(19,2), +--Allows percentages between %1000.00 (10,000 percent) and %0.12356. +SalaryPercentage DECIMAL(6,2), --The percentage of the manager's salary that was made on this week's sale items. +SalaryDollar DECIMAL(19,2), -- +Supplies DECIMAL(19,2) --Total of costs from invoices (?). +) + +CREATE TABLE Holiday +( +Id INTEGER NOT NULL PRIMARY KEY, +Holiday VARCHAR(64) NOT NULL +) + +CREATE TABLE Inventory +( +Id INTEGER NOT NULL PRIMARY KEY, +--All values minus the primary key and foreign keys are set as strings to allow +--specifying the number of bins of product are present. +BeginningInventory VARCHAR(255), +Recieved VARCHAR(255), +TotalInventory VARCHAR(255), +EndingInventory VARCHAR(255), +--The attributes of the row can not be null, and neither can the foreign keys. +RowPosition INTEGER NOT NULL, +--A precision of two digits should be everything we need for the row attribute. +RowAttribute INTEGER NOT NULL, +--Now begin all the foreign keys. +FkAdItemId INTEGER NOT NULL, +FkAdSpecialGoupId INTEGER NOT NULL, +FkDateId INTEGER NOT NULL +) + +CREATE TABLE Invoice +( +Id INTEGER NOT NULL PRIMARY KEY, +InvoiceDate DATE NOT NULL, +InvoiceNumber INTEGER NOT NULL, +InvoiceNetAmountAtCost DECIMAL(19,2), +InvoiceNetAmount DECIMAL(19,2), +InvoiceNote VARCHAR(255), +--Keys are never allowed to be null. +FkSupplierId INTEGER NOT NULL, +FkDateId INTEGER NOT NULL +) + +CREATE TABLE Projections +( +Id INTEGER NOT NULL PRIMARY KEY, +--Sold and sale price need to be stored as a string since they need to support # Bin(s) +--and $#.##/# formatting respectively. +Sold VARCHAR(128), +SalePrice VARCHAR(128), +--Might be over kill to store money like this but better safe then sorry. +TotalSales DECIMAL(19,2), +Cost DECIMAL(19,2), +ProfitReturn DECIMAL(19,2), +TotalProfitReturn DECIMAL(19,2), +--The attributes of the row can not be null, and neither can the foreign keys. +RowPosition INTEGER NOT NULL, +--A precision of two digits should be everything we need for the row attribute. +RowAttribute INTEGER NOT NULL, +--Now begin all the foreign keys. +FkAdItemId INTEGER NOT NULL, +FkAdSpecialGoupId INTEGER NOT NULL, +FkDateId INTEGER NOT NULL +) + +CREATE TABLE Supplier +( +Id INTEGER NOT NULL PRIMARY KEY, +Supplier VARCHAR(255), +Description VARCHAR(255) --Optional field may be used later one. +) + +CREATE TABLE Taxable +( +Id INTEGER NOT NULL PRIMARY KEY, +Sunday DECIMAL(19,2), +Monday DECIMAL(19,2), +Tuesday DECIMAL(19,2), +Wednesday DECIMAL(19,2), +Thursday DECIMAL(19,2), +Friday DECIMAL(19,2), +Saturday DECIMAL(19,2), +Total DECIMAL(19,2), +--Keys are never allowed to be null. +FkDateId INTEGER NOT NULL +) + +CREATE TABLE Version +( +Id INTEGER NOT NULL PRIMARY KEY, +VersionNumber VARCHAR(64) --64 characters should be more then enough to store a version number. +) + +CREATE TABLE WeekEndingDate +( +Id INTEGER NOT NULL PRIMARY KEY, +WeekEndingDate DATE NOT NULL --A date is required to be entered. +) + +CREATE TABLE WeeklySales +( +Id INTEGER NOT NULL PRIMARY KEY, +Sunday DECIMAL(19,2), +Monday DECIMAL(19,2), +Tuesday DECIMAL(19,2), +Wednesday DECIMAL(19,2), +Thursday DECIMAL(19,2), +Friday DECIMAL(19,2), +Saturday DECIMAL(19,2), +TotalSales DECIMAL(19,2), +--Keys are never allowed to be null. +FkDateId INTEGER NOT NULL +) \ No newline at end of file diff --git a/AdvertsingProfitControl/AdvertsingProfitControl.csproj b/AdvertsingProfitControl/AdvertsingProfitControl.csproj index dbf4cb2..06824c7 100644 --- a/AdvertsingProfitControl/AdvertsingProfitControl.csproj +++ b/AdvertsingProfitControl/AdvertsingProfitControl.csproj @@ -237,6 +237,7 @@ Always + diff --git a/AdvertsingProfitControl/DatabaseWriter.cs b/AdvertsingProfitControl/DatabaseWriter.cs index 289f6fb..a973730 100644 --- a/AdvertsingProfitControl/DatabaseWriter.cs +++ b/AdvertsingProfitControl/DatabaseWriter.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Data; using System.Data.OleDb; +using System.Runtime.InteropServices; using System.Windows.Forms; namespace AdvertsingProfitControl @@ -1066,6 +1067,118 @@ namespace AdvertsingProfitControl return id; } + /// + /// Deletes the row with the specified ID number from the provided table. + /// + /// The ID number of the row to be deleted. + /// The ID number of the row to be deleted. + /// The ID number of the row to be deleted. + /// True if the operation was successful; false if not. + public bool DeleteApcRow(int projectionsRowId, int inventoryRowId, int actualSalesRowId) + { + var result = false; + var tableName = "Projections"; //Starting point. + var oleDbCommand = new OleDbCommand + { + CommandText = "DELETE FROM Projections WHERE ID = ?", + Connection = _oleDbConnection + }; + oleDbCommand.Parameters.AddWithValue("ID", projectionsRowId); + OleDbTransaction oleDbTransaction = null; + try + { + _oleDbConnection.Open(); + oleDbTransaction = _oleDbConnection.BeginTransaction(); + oleDbCommand.Transaction = oleDbTransaction; + var rowsEffected = oleDbCommand.ExecuteNonQuery(); + if (rowsEffected == 1) + { + tableName = "Inventory"; + oleDbCommand.Parameters.Clear(); + oleDbCommand.CommandText = "DELETE FROM Inventory WHERE ID = ?"; + oleDbCommand.Parameters.AddWithValue("ID", inventoryRowId); + rowsEffected = oleDbCommand.ExecuteNonQuery(); + if (rowsEffected == 1) + { + tableName = "ActualSales"; + oleDbCommand.Parameters.Clear(); + oleDbCommand.CommandText = "DELETE FROM ActualSales WHERE ID = ?"; + oleDbCommand.Parameters.AddWithValue("ID", inventoryRowId); + rowsEffected = oleDbCommand.ExecuteNonQuery(); + if (rowsEffected == 1) + { + result = true; + } + } + } + if (!result) + { + oleDbTransaction?.Rollback(); + } + else + { + oleDbTransaction.Commit(); + } + } + catch (OleDbException e) + { + _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to delete row with the ID of " + inventoryRowId + " from " + tableName + "."); + _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message); + oleDbTransaction?.Rollback(); + } + finally + { + _oleDbConnection.Close(); + } + + return result; + } + + /// + /// Removes the invoice record with the specified internal ID number. + /// + /// The ID of the row to delete. + /// Whether or not the removal was a success or not. + public bool DeleteInvoiceRow(int rowId) + { + var result = false; + var oleDbCommand = new OleDbCommand + { + CommandText = "DELETE FROM Invoice WHERE ID = ?", + Connection = _oleDbConnection + }; + oleDbCommand.Parameters.AddWithValue("ID", rowId); + OleDbTransaction oleDbTransaction = null; + try + { + _oleDbConnection.Open(); + oleDbTransaction = _oleDbConnection.BeginTransaction(); + oleDbCommand.Transaction = oleDbTransaction; + var rowsEffected = oleDbCommand.ExecuteNonQuery(); + if (rowsEffected == 1) + { + result = true; + oleDbTransaction.Commit(); + } + else + { + oleDbTransaction?.Rollback(); + } + } + catch (OleDbException e) + { + _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to delete row with the ID of " + rowId + " from the Invoice table."); + _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message); + oleDbTransaction?.Rollback(); + } + finally + { + _oleDbConnection.Close(); + } + + return result; + } + #endregion //10 to 1 ratio of tries to code diff --git a/AdvertsingProfitControl/NewAddRecord.Designer.cs b/AdvertsingProfitControl/NewAddRecord.Designer.cs index 7752292..cb8442b 100644 --- a/AdvertsingProfitControl/NewAddRecord.Designer.cs +++ b/AdvertsingProfitControl/NewAddRecord.Designer.cs @@ -107,6 +107,7 @@ this.informationPanel = new System.Windows.Forms.Panel(); this.errorLabel = new System.Windows.Forms.Label(); this.addRecordButton = new System.Windows.Forms.Button(); + this.debugMainMenu = new System.Windows.Forms.ToolStripMenuItem(); this.commentsGroupBox.SuspendLayout(); this.mainTabControl.SuspendLayout(); this.projectionTabPage.SuspendLayout(); @@ -418,7 +419,8 @@ this.mainLayoutPanel.SetColumnSpan(this.mainMenuStrip, 4); this.mainMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24); this.mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FileMainMenu}); + this.FileMainMenu, + this.debugMainMenu}); this.mainMenuStrip.Location = new System.Drawing.Point(0, 0); this.mainMenuStrip.Name = "mainMenuStrip"; this.mainMenuStrip.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2); @@ -941,6 +943,13 @@ this.addRecordButton.UseVisualStyleBackColor = true; this.addRecordButton.Click += new System.EventHandler(this.AddRecordsButtonClick); // + // debugMainMenu + // + this.debugMainMenu.Name = "debugMainMenu"; + this.debugMainMenu.Size = new System.Drawing.Size(87, 31); + this.debugMainMenu.Text = "&Debug"; + this.debugMainMenu.Click += new System.EventHandler(this.debugMainMenu_Click); + // // NewAddRecord // this.AutoScaleDimensions = new System.Drawing.SizeF(168F, 168F); @@ -1067,5 +1076,6 @@ private System.Windows.Forms.Button generateCostAnalysisIdButton; private System.Windows.Forms.Button generateTaxableIdButton; private System.Windows.Forms.Button generateWeeklySalesIdButton; + private System.Windows.Forms.ToolStripMenuItem debugMainMenu; } } \ No newline at end of file diff --git a/AdvertsingProfitControl/NewAddRecord.cs b/AdvertsingProfitControl/NewAddRecord.cs index 05ddc16..7fbfb41 100644 --- a/AdvertsingProfitControl/NewAddRecord.cs +++ b/AdvertsingProfitControl/NewAddRecord.cs @@ -94,6 +94,8 @@ namespace AdvertsingProfitControl invoicesDataGridView.CellValidating += ValidateInvoicesCellContents; //Grab the underlying text box object in the ad item cell, and build an auto complete list for the user. invoicesDataGridView.EditingControlShowing += DisplaySupplierAutoComleteOnEditingShadowControl; + //Subscribe the method to allow the user to delete saved rows from the Invoices table. + invoicesDataGridView.UserDeletingRow += UpdateInvoicesOnRowDeleting; //Finally build the last DataGridView for the form. ConstructInvoicesDataGridView();//No weekly sales table is nice. //Subscribe the comments text box to check if changes have been made on leave. @@ -333,6 +335,45 @@ namespace AdvertsingProfitControl autoText.AutoCompleteCustomSource = _supplierCollection; } + /// + /// Checks to see if the row that the user is attempting to delete has been saved to the database. + /// If so, this method will try to delete the record, failing that it will cancel the row deletion. + /// + /// Invoice table. + /// + private void UpdateInvoicesOnRowDeleting(object sender, DataGridViewRowCancelEventArgs e) + { + var rowIndex = e.Row.Index; + //See if there is an ID number in the ID column. + if (invoicesDataGridView.Rows[rowIndex].Cells[(int) InvoiceTableColumns.Id].EditedFormattedValue.ToString() == "") return; + //Ask the user to make damn sure they want to remove this record. + var result = MessageBox.Show(@"Deleting this row will remove it from the database permanently. Do you wish to continue?", @"Remove Invoice Number " + invoicesDataGridView.Rows[rowIndex].Cells[(int)InvoiceTableColumns.InvoiceNumber].EditedFormattedValue, MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.Yes) + { + //If so create the database interaction objects. + var dbTracker = new DatabaseTracker(); + var dbWriter = new DatabaseWriter(dbTracker.DatabaseConnectionString); + var id = + int.Parse( + invoicesDataGridView.Rows[rowIndex].Cells[(int) InvoiceTableColumns.Id].EditedFormattedValue + .ToString()); + if (dbWriter.DeleteInvoiceRow(id)) + { + informationLabel.Text = @"Successfully removed row " + (rowIndex + 1) + @" from the database."; + } + else + { + //The operation failed. + errorLabel.Text = @"Failed to delete row " + (rowIndex + 1) + @" from invoices."; + e.Cancel = true; + } + } + else + { + e.Cancel = true; + } + } + #endregion #region APC DataGridView Events @@ -477,16 +518,67 @@ namespace AdvertsingProfitControl { //Create an object that represents the DataGridView that fired the event. var dataGridView = (DataGridView)sender; - if (dataGridView.CurrentRow == null) return; + if (dataGridView.CurrentRow == null) return; + //Create the database writer object so rows that are in the database can be deleted. + var dbTracker = new DatabaseTracker(); + var dbWriter = new DatabaseWriter(dbTracker.DatabaseConnectionString); var currentRowIndex = dataGridView.CurrentRow.Index; //Remove the ad item from the gUsedAdItem collection, if it exists. if (_adSpecialIndex == -1) { + //If the ID number is set, i.e. not equal to null then attempt to remove it from the database. + if (dataGridView.Rows[currentRowIndex].Cells[0].EditedFormattedValue.ToString() != "") + { + var result = MessageBox.Show(@"Removing this row will permanently delete this record from the database. Do you wish to continue?", @"Remove " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue, MessageBoxButtons.YesNo); + if (result == DialogResult.Yes) + { + //Attempt to delete the row from the database by its ID number. + var projectionsRowId = int.Parse(projectionsDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + var inventoryRowId = int.Parse(inventoryDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + var actualSalesRowId = int.Parse(actualSalesDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + if (dbWriter.DeleteApcRow(projectionsRowId, inventoryRowId, actualSalesRowId)) + { + informationLabel.Text = @"Successfully removed row " + (currentRowIndex + 1) + @" from the database."; + } + else + { + //If the removing failed cancel the row deletion in the DataGridView. + e.Cancel = true; + MessageBox.Show(@"Failed to delete " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue + + @" from the database.", @"Failed to Update Database"); + return; + } + } + } //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there. _usedAdItems[0].Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString()); } else if (currentRowIndex < _adSpecialIndex) { + //If the ID number is set, i.e. not equal to null then attempt to remove it from the database. + if (dataGridView.Rows[currentRowIndex].Cells[0].EditedFormattedValue.ToString() != "") + { + var result = MessageBox.Show(@"Removing this row will permanently delete this record from the database. Do you wish to continue?", @"Remove " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue, MessageBoxButtons.YesNo); + if (result == DialogResult.Yes) + { + //Attempt to delete the row from the database by its ID number. + var projectionsRowId = int.Parse(projectionsDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + var inventoryRowId = int.Parse(inventoryDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + var actualSalesRowId = int.Parse(actualSalesDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + if (dbWriter.DeleteApcRow(projectionsRowId, inventoryRowId, actualSalesRowId)) + { + informationLabel.Text = @"Successfully removed row " + (currentRowIndex + 1) + @" from the database."; + } + else + { + //If the removing failed cancel the row deletion in the DataGridView. + e.Cancel = true; + MessageBox.Show(@"Failed to delete " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue + + @" from the database.", @"Failed to Update Database"); + return; + } + } + } //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there. _usedAdItems[0].Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString()); //Also decrement the _adSpecialIndex so that it points to the correct row. @@ -494,12 +586,35 @@ namespace AdvertsingProfitControl } else if (currentRowIndex > _adSpecialIndex) { + //If the ID number is set, i.e. not equal to null then attempt to remove it from the database. + if (dataGridView.Rows[currentRowIndex].Cells[0].EditedFormattedValue.ToString() != "") + { + var result = MessageBox.Show(@"Removing this row will permanently delete this record from the database. Do you wish to continue?", @"Remove " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue, MessageBoxButtons.YesNo); + if (result == DialogResult.Yes) + { + //Attempt to delete the row from the database by its ID number. + var projectionsRowId = int.Parse(projectionsDataGridView.Rows[currentRowIndex].Cells[(int) SalesTableColumns.Id].EditedFormattedValue.ToString()); + var inventoryRowId = int.Parse(inventoryDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + var actualSalesRowId = int.Parse(actualSalesDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + if (dbWriter.DeleteApcRow(projectionsRowId, inventoryRowId, actualSalesRowId)) + { + informationLabel.Text = @"Successfully removed row " + (currentRowIndex + 1) + @" from the database."; + } + else + { + //If the removing failed cancel the row deletion in the DataGridView. + e.Cancel = true; + MessageBox.Show(@"Failed to delete " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue + + @" from the database.", @"Failed to Update Database"); + return; + } + } + } //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there. _usedAdItems[1].Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString()); } else if (currentRowIndex == _adSpecialIndex) - { - + { //Handle removing the AdSpecial row. var result = MessageBox.Show(@"Deleting the Ad Special row will remove all rows beneath it. Do you wish to continue?", @"Clear " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) @@ -514,12 +629,32 @@ namespace AdvertsingProfitControl //Actual Sales table actualSalesDataGridView.RowsRemoved -= ActualSalesRowRemoved; actualSalesDataGridView.UserDeletingRow -= UpdateUsedAdItemCollectionOnRowRemoving; - //Now for-each through each row that is underneath the Ad Special row. for (var rowIndex = dataGridView.RowCount; currentRowIndex != rowIndex; rowIndex--) { - //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there. - _usedAdItems[1].Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString()); + if (projectionsDataGridView.RowCount == inventoryDataGridView.RowCount && + projectionsDataGridView.RowCount == actualSalesDataGridView.RowCount) + { + if (dataGridView.Rows[currentRowIndex].Cells[(int) SalesTableColumns.Id].EditedFormattedValue.ToString() != "") + { + //Attempt to delete the row from the database by its ID number. + var projectionsRowId = int.Parse(projectionsDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + var inventoryRowId = int.Parse(inventoryDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + var actualSalesRowId = int.Parse(actualSalesDataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.Id].EditedFormattedValue.ToString()); + if (dbWriter.DeleteApcRow(projectionsRowId, inventoryRowId, actualSalesRowId)) + { + informationLabel.Text += @"Successfully removed row " + (currentRowIndex + 1) + @" from the database." + Environment.NewLine; + } + else + { + //If the removing failed cancel the row deletion in the DataGridView. + e.Cancel = true; + MessageBox.Show(@"Failed to delete " + dataGridView.Rows[currentRowIndex].Cells[1].EditedFormattedValue + + @" from the database.", @"Failed to Update Database"); + return; + } + } + } if (projectionsDataGridView.Rows[currentRowIndex].IsNewRow != true) { projectionsDataGridView.Rows.RemoveAt(currentRowIndex); @@ -532,6 +667,8 @@ namespace AdvertsingProfitControl { actualSalesDataGridView.Rows.RemoveAt(currentRowIndex); } + //If the ad item entered in the first cell is in the gUsedAdItems collection, then remove it from there. + _usedAdItems[1].Remove(dataGridView.Rows[currentRowIndex].Cells[(int)SalesTableColumns.AdItem].EditedFormattedValue.ToString()); } //Re-enable all row removal events on both tables. //Projections table @@ -668,16 +805,21 @@ namespace AdvertsingProfitControl //If there is text after all the whitespace has been cleared, clear the error text property regardless of whether or not it is set. if (!string.IsNullOrEmpty(Regex.Replace(userInput, @"\s+", ""))) { - var parser = new RowParsing(); - if (parser.CheckForGroupKeyWord(userInput) != "NoGroupFound") - { - _adSpecialIndex = e.RowIndex; - } //Clear the error text since there is in fact an item entered. dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = ""; //Send the ad item text through the formatting engine and assign the new value to the cell. dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = TextFormat.FormatAdItemText(userInput); - dataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + var parser = new RowParsing(); + if (parser.CheckForGroupKeyWord(userInput) == "NoGroupFound") + { + dataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + } + else + { + _adSpecialIndex = e.RowIndex; + //Since this is the ad special row don't give it any color coding. + dataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + } //Force a refresh so the cell's text updates and displays for the user. dataGridView.RefreshEdit(); return; @@ -723,7 +865,7 @@ namespace AdvertsingProfitControl //If the column is the "Sale Price" column try to parse the contents to a Double and apply number formatting to the contents. //Check for the cost column to see if there are any strings formatted like such: var regExpression = new Regex(@"^\d+( *)?/( *)?\${0,1}?\d+(\.\d+)?", RegexOptions.IgnoreCase); // [0-9]/($)?[0-9] - //IF the current cell is in the sale price column, check for the string format above, else move to the default method. + //IF the current cell is in the sale price column, check for the string format above, else move to the default method. if (regExpression.IsMatch(dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString())) { //Grab the input and split it at the forward slash (/) for formatting. @@ -923,8 +1065,16 @@ namespace AdvertsingProfitControl } inventoryDataGridView.Rows.Add(inventoryNewRow); //Set the row headers of the other tables to show up as pending; this row is valid without a doubt. - inventoryDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; - actualSalesDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + if (e.RowIndex != _adSpecialIndex) + { + inventoryDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + actualSalesDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + } + else + { + inventoryDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + actualSalesDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + } } private void ProjectionRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e) @@ -1071,16 +1221,21 @@ namespace AdvertsingProfitControl //If there is text after all the whitespace has been cleared, clear the error text property regardless of whether or not it is set. if (!string.IsNullOrEmpty(Regex.Replace(userInput, @"\s+", ""))) { - var parser = new RowParsing(); - if (parser.CheckForGroupKeyWord(userInput) != "NoGroupFound") - { - _adSpecialIndex = e.RowIndex; - } //Clear the error text since there is in fact an item entered. dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = ""; //Send the ad item text through the formatting engine and assign the new value to the cell. dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = TextFormat.FormatAdItemText(userInput); - dataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + var parser = new RowParsing(); + if (parser.CheckForGroupKeyWord(userInput) == "NoGroupFound") + { + dataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + } + else + { + _adSpecialIndex = e.RowIndex; + //Since this is the ad special row don't give it any color coding. + dataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + } //Force a refresh so the cell's text updates and displays for the user. dataGridView.RefreshEdit(); return; @@ -1205,9 +1360,18 @@ namespace AdvertsingProfitControl } projectionsDataGridView.Rows.Add(rowContents); actualSalesDataGridView.Rows.Add(rowContents); - //Apply color coding to the respective row headers on the other tables. - projectionsDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; - actualSalesDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + if (e.RowIndex != _adSpecialIndex) + { + //Apply color coding to the respective row headers on the other tables. + projectionsDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + actualSalesDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + } + else + { + //Apply color coding to the respective row headers on the other tables. + projectionsDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + actualSalesDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + } } private void InventoryRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e) @@ -1386,9 +1550,19 @@ namespace AdvertsingProfitControl } } inventoryDataGridView.Rows.Add(inventoryNewRow); - //Apply color coding to the respective row headers on the other tables. - projectionsDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; - inventoryDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + + if (e.RowIndex != _adSpecialIndex) + { + //Apply color coding to the respective row headers on the other tables. + projectionsDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + inventoryDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit; + } + else + { + //Apply color coding to the respective row headers on the other tables. + projectionsDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + inventoryDataGridView.Rows[e.RowIndex].HeaderCell.Style.BackColor = DefaultBackColor; + } } private void ActualSalesRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e) @@ -1618,7 +1792,6 @@ namespace AdvertsingProfitControl /// /// Allows the user to select all the text in the comments text box. - /// TODO: Fix error chime when using CNTRL+A. /// /// /// @@ -1627,6 +1800,8 @@ namespace AdvertsingProfitControl if (!e.Control || e.KeyCode != Keys.A) return; commentsTextBox.SelectionStart = 0; commentsTextBox.SelectionLength = commentsTextBox.Text.Length; + e.Handled = true; + e.SuppressKeyPress = true; } /// @@ -2834,7 +3009,6 @@ namespace AdvertsingProfitControl #region Debug Operations - private void idButton_Click(object sender, EventArgs e) { if (isCommentDirtyCheckBox.Tag == null) @@ -2894,7 +3068,14 @@ namespace AdvertsingProfitControl MessageBox.Show(@"ID cleared from Cost Analysis.", @"Clear ID Debug"); } } + private void debugMainMenu_Click(object sender, EventArgs e) + { + MessageBox.Show(TextFormat.CapitalizeFirstLetter(projectionsDataGridView.Name.Remove(projectionsDataGridView.Name.Length - 12))); + MessageBox.Show(TextFormat.CapitalizeFirstLetter(inventoryDataGridView.Name.Remove(inventoryDataGridView.Name.Length - 12))); + MessageBox.Show(TextFormat.CapitalizeFirstLetter(actualSalesDataGridView.Name.Remove(actualSalesDataGridView.Name.Length - 12))); + } #endregion + } } diff --git a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application index 3e737ce..f3e92cb 100644 --- a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application +++ b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application @@ -7,14 +7,14 @@ - + - awuF53zQVe9V3zUNL3d5T6YCMzmHhsse6PclfUp46TM= + VSIqTBM/2qcZ+QvdjsN5nrzGeyUkofXt8gkwA+ifCeM= diff --git a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest index b99ead8..43c2b0a 100644 --- a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest +++ b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest @@ -43,14 +43,14 @@ - + - UU8qwZxBBKymnYncKNbRY9vyIqD6hwiqMecESA476/8= + Twcy9tLeC7tLOMd3Kt+tpcRMhnW/2zLmImwOYH8DbJw= @@ -78,6 +78,15 @@ + + + + + + + e48EkTyChGHXYJETENSLw7RKQ1LZ5ZDUghEtiv5DmqY= + +