diff --git a/AdvertsingProfitControl/APCDatabase.accdb b/AdvertsingProfitControl/APCDatabase.accdb index 661ffc5..33a1f0b 100644 Binary files a/AdvertsingProfitControl/APCDatabase.accdb and b/AdvertsingProfitControl/APCDatabase.accdb differ diff --git a/AdvertsingProfitControl/AdvertisingProfitControlTableHelper.cs b/AdvertsingProfitControl/AdvertisingProfitControlTableHelper.cs index b5dfdd2..0db9c03 100644 --- a/AdvertsingProfitControl/AdvertisingProfitControlTableHelper.cs +++ b/AdvertsingProfitControl/AdvertisingProfitControlTableHelper.cs @@ -299,12 +299,15 @@ namespace AdvertsingProfitControl InvoiceNote = 6, IsDirty = 7 } - + /// + /// TODO: Push into a stand alone object. + /// public enum TrimmingOperationResult { FailedToTrim = 0, CreatedNewInsertionTable = 1, CreatedUpdateTable = 2, - CreatedNewInsertionAndUpdateTables = 3 + CreatedNewInsertionAndUpdateTables = 3, + NoChangesRequired = 4 } } diff --git a/AdvertsingProfitControl/AdvertsingProfitControl.csproj b/AdvertsingProfitControl/AdvertsingProfitControl.csproj index 519b8b5..be561f0 100644 --- a/AdvertsingProfitControl/AdvertsingProfitControl.csproj +++ b/AdvertsingProfitControl/AdvertsingProfitControl.csproj @@ -106,6 +106,7 @@ + diff --git a/AdvertsingProfitControl/DatabaseWriter.cs b/AdvertsingProfitControl/DatabaseWriter.cs index c6aa4bb..1463fa8 100644 --- a/AdvertsingProfitControl/DatabaseWriter.cs +++ b/AdvertsingProfitControl/DatabaseWriter.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.Data; using System.Data.OleDb; -using System.Transactions; -using System.Windows.Forms; namespace AdvertsingProfitControl { @@ -14,8 +12,16 @@ namespace AdvertsingProfitControl { _oleDbConnection.ConnectionString = connectionString; } + #region New Code + public OleDbCommand GetOleDbCommand(string connectionString) + { + var oleDbCommand = new OleDbCommand(); + + return oleDbCommand; + } + /// /// Inserts new records into the specified sales table. /// Supports rolling back the database to prevent corruption. @@ -23,10 +29,10 @@ namespace AdvertsingProfitControl /// The data table that contains the data to be inserted. /// /// - public Dictionary InsertIntoSalesTable(DataTable salesTable, string connectionString) + public DbWriterStatus InsertIntoSalesTable(DataTable salesTable, string connectionString) { var rowIndex = 0; - var rows = new Dictionary(); + var writerStatus = new DbWriterStatus(); var oleDbConnection = new OleDbConnection(connectionString); //IDs from the database can not be zero (0), so this will be the default value (no group). var oleDbCommand = new OleDbCommand @@ -69,21 +75,29 @@ namespace AdvertsingProfitControl if (int.Parse(row[8].ToString()) != 0) { //Account for the ad special row. - rows.Add(int.Parse(row[9].ToString()) + 1, rowId); + //Index 8 of the row indicates that this row is an ad special member row + //so we must add one to the row position to offset the fact that a row + //is "missing" from this DataTable. + //Row[9] is its row position, which is not zero index based. + writerStatus.AddRowId(int.Parse(row[9].ToString()) + 1, rowId); } else { - rows.Add(int.Parse(row[9].ToString()), rowId); - } + //The ad special row doesn't exist so no need to offset it. + writerStatus.AddRowId(int.Parse(row[9].ToString()), rowId); + } } + writerStatus.SetStatus(WritingOperationStatus.InsertionSuccessful); } catch (OleDbException ex) { + writerStatus.SetStatus(WritingOperationStatus.Failed); _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to write to database: " + ex.Message); if (rowIndex <= 0) { _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to begin parsing data rows, var dump of erroneous row unavailable."); + writerStatus.SetErrorMessage("Failed to begin parsing rows."); } else { @@ -98,7 +112,8 @@ namespace AdvertsingProfitControl "Cost: \"" + salesTable.Rows[rowIndex][3] + "\" Profit Return: \"" + salesTable.Rows[rowIndex][4] + "\""); _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Total Profit Return: \"" + - salesTable.Rows[rowIndex][5] + "\" Ad Special Group: \"" + salesTable.Rows[rowIndex][8] + "\""); + salesTable.Rows[rowIndex][5] + "\" Ad Special Group: \"" + salesTable.Rows[rowIndex][8] + "\""); + writerStatus.SetErrorMessage("Failed to write to the database on row " + (rowIndex + 1) + "."); } oleDbTransaction?.Rollback(); _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Rollback completed successfully, " + salesTable.TableName+ " table failed on insertion."); @@ -107,12 +122,12 @@ namespace AdvertsingProfitControl { _oleDbConnection.Close(); } - return rows; + return writerStatus; } - public bool UpdateSalesTable(DataTable salesTable, string connectionString) + public DbWriterStatus UpdateSalesTable(DataTable salesTable, string connectionString) { - var wasSuccessful = false; + var updateStatus = new DbWriterStatus(); var rowIndex = 0; var oleDbConnection = new OleDbConnection(connectionString); //IDs from the database can not be zero (0), so this will be the default value (no group). @@ -129,7 +144,7 @@ namespace AdvertsingProfitControl for (var i = 0; i < salesTable.Rows.Count; i++) { oleDbCommand.CommandText = - "UPDATE " + salesTable.TableName + " SET Sold = ?, SalePrice = ?, TotalSales = ?, Cost = ?, ProfitReturn = ?, TotalProfitReturn = ?, RowAttribute = ?, FK_AdSpecialGroupName = ?, RowPosition = ? WHERE ID = ?"; + "UPDATE " + salesTable.TableName + " SET Sold = ?, SalePrice = ?, TotalSales = ?, Cost = ?, ProfitReturn = ?, TotalProfitReturn = ?, FK_AdItemID = ?, RowAttribute = ?, FK_AdSpecialGroupName = ?, RowPosition = ? WHERE ID = ?"; //Update Sales Table Layout (Based on the Database's Physical Layout) //0:ID 1:Sold 2:SalePrice 3:TotalSales 4:cost 5:ProfitReturn 6:TotalProfitReturn //7:FK_AdItemID 8:RowAttribute 9:FK_AdSpecialGroupName (ID) 10:RowPosition (not index based) @@ -140,24 +155,28 @@ namespace AdvertsingProfitControl oleDbCommand.Parameters.AddWithValue("Cost", salesTable.Rows[i][4]); oleDbCommand.Parameters.AddWithValue("ProfitReturn", salesTable.Rows[i][5]); oleDbCommand.Parameters.AddWithValue("TotalProfitReturn", salesTable.Rows[i][6]); + oleDbCommand.Parameters.AddWithValue("FK_AdItemID", salesTable.Rows[i][7]); oleDbCommand.Parameters.AddWithValue("RowAttribute", salesTable.Rows[i][8]); oleDbCommand.Parameters.AddWithValue("adSpecialID", salesTable.Rows[i][9]); oleDbCommand.Parameters.AddWithValue("RowPosition", salesTable.Rows[i][10]); oleDbCommand.Parameters.AddWithValue("ID", salesTable.Rows[i][0]); oleDbCommand.ExecuteNonQuery(); oleDbCommand.Parameters.Clear(); + //Row index is only used to keep track of what row failed to update. rowIndex++; } oleDbTransaction.Commit(); - wasSuccessful = true; + updateStatus.SetStatus(WritingOperationStatus.UpdateSuccessful); } catch (OleDbException ex) { + updateStatus.SetStatus(WritingOperationStatus.Failed); _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to update the database for " + salesTable.TableName + ": " + ex.Message); if (rowIndex <= 0) { _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to begin parsing data rows, var dump of erroneous row unavailable."); + updateStatus.SetErrorMessage("Failed to begin parsing rows."); } else { @@ -173,6 +192,7 @@ namespace AdvertsingProfitControl _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Total Profit Return: \"" + salesTable.Rows[rowIndex][6] + "\" Ad Special Group: \"" + salesTable.Rows[rowIndex][9] + "\""); + updateStatus.SetErrorMessage("Failed to write to the database on row " + (rowIndex + 1) + "."); } oleDbTransaction?.Rollback(); _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Rollback completed successfully, " + salesTable.TableName + " table failed on update."); @@ -182,7 +202,7 @@ namespace AdvertsingProfitControl _oleDbConnection.Close(); } - return wasSuccessful; + return updateStatus; } /// @@ -315,6 +335,7 @@ namespace AdvertsingProfitControl _oleDbConnection.Close(); return id; } + #endregion //10 to 1 ratio of tries to code diff --git a/AdvertsingProfitControl/DbWriterStatus.cs b/AdvertsingProfitControl/DbWriterStatus.cs new file mode 100644 index 0000000..0801a04 --- /dev/null +++ b/AdvertsingProfitControl/DbWriterStatus.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; + +namespace AdvertsingProfitControl +{ + internal class DbWriterStatus + { + //Initialize the _status to failed just to have it not be null. + private WritingOperationStatus _status = WritingOperationStatus.Failed; + private readonly Dictionary _rowIds; + private string _errorMessage; + + public DbWriterStatus() + { + _rowIds = new Dictionary(); + } + + public void SetStatus(WritingOperationStatus status) + { + _status = status; + } + /// + /// Gets the status from the operation. + /// + /// A status indicating whether or not it was successful, default is failed. + public WritingOperationStatus GetWritingOperationStatus() + { + return _status; + } + /// + /// Adds a row to the Rows Dictionary that keeps track of what rows have been + /// added to the database including their IDs. + /// + /// The index of the row that was added to the database. + /// The ID number of the row as represented in the database. + public void AddRowId(int key, int rowIdNumber) + { + _rowIds.Add(key, rowIdNumber); + } + /// + /// Removes a row from the Rows collection. + /// + /// The row's index that is to be deleted. + public void DeleteRow(int key) + { + _rowIds.Remove(key); + } + + public void ClearRowCollection() + { + _rowIds.Clear(); + } + /// + /// Gets the Dictionary containing rows that have been added to the database. + /// The keys are the row's index and the value is the row's ID as represented + /// in the database. + /// Returns an empty Dictionary if no rows have been added. + /// + /// The rows that have been added to the database. + public Dictionary GetRowCollection() + { + return _rowIds ?? new Dictionary(); + } + /// + /// Sets an error message. + /// + /// The error message to be set. + public void SetErrorMessage(string message) + { + _errorMessage = message; + } + /// + /// Gets any error message set by the Insertion/Update operation function. + /// If none are set returns an empty string. + /// + /// The error message. + public string GetErrorMessage() + { + //If the error message is null then return string.Empty. + //Otherwise return the error message. + return _errorMessage ?? string.Empty; + } + } + + /// + /// Operation status emus to keep things consistent. + /// + public enum WritingOperationStatus + { + Failed = 0, + InsertionSuccessful = 1, + UpdateSuccessful = 2 + } +} diff --git a/AdvertsingProfitControl/NewAddRecord.cs b/AdvertsingProfitControl/NewAddRecord.cs index 7b20a0c..9692812 100644 --- a/AdvertsingProfitControl/NewAddRecord.cs +++ b/AdvertsingProfitControl/NewAddRecord.cs @@ -1838,23 +1838,22 @@ namespace AdvertsingProfitControl } //Run the row parsing engine on all the APC tables. //Create the cleaned table objects that will be sent to the database. - //var trimmed = new DataTable(); - //var update = new DataTable(); - //var trimmedProjectionsTable = ConstructCleanedProjectionsTable(dateId, out trimmed, out update); - //var trimmedInventoryTable = ConstructCleanedInventoryTable(dateId); - //var trimmedActualSalesTable = ConstructCleanedActualSalesTable(dateId); + var trimmedTable = new DataTable(); + var updateTable = new DataTable(); + //var operationStatus = ConstructCleanedProjectionsTable(dateId, out trimmed, out update); + //operationStatus = ConstructCleanedInventoryTable(dateId); + //operationgStatus = ConstructCleanedActualSalesTable(dateId); //Create the transaction scope. //By default the TransactionScopeOption is "Required", so if an ambient transaction does not //exist then the new transaction that is made (in the first method) becomes the root transaction. //Transaction Scope: https://msdn.microsoft.com/en-us/library/ms172152.aspx - //var projectionsAdditions = dbW.InsertIntoSalesTable(trimmedProjectionsTable, dbT.DatabaseConnectionString); + //var projectionsAdditions = dbW.InsertIntoSalesTable(trimmedTable, dbT.DatabaseConnectionString); //foreach (var rowIndex in projectionsAdditions) //{ // projectionsDataGridView.Rows[rowIndex.Key - 1].Cells[(int) SalesTableColumns.Id].Value = rowIndex.Value; // projectionsDataGridView.Rows[rowIndex.Key - 1].Cells[(int)SalesTableColumns.IsDirty].Value = false; // projectionsDataGridView.Rows[rowIndex.Key - 1].Cells[(int)SalesTableColumns.IsInDatabase].Value = true; //} - //dbW.UpdateSalesTable(trimmedProjectionsTable.ElementAt(1), dbT.DatabaseConnectionString); } #region APC Table Trimming @@ -2125,6 +2124,18 @@ namespace AdvertsingProfitControl //LogConsole.WriteToLog(FrmLogConsole.Level.Verbose, "Row Position: " + row.Index + (_adSpecialIndex != -1 && row.Index > _adSpecialIndex ? 1 : 0) + " Date ID: " + dateId); } + if (insertNewTable.Rows.Count == 0 && updateExistingTable.Rows.Count == 0) + { + return TrimmingOperationResult.NoChangesRequired; + } + if (insertNewTable.Rows.Count > 0 && updateExistingTable.Rows.Count == 0) + { + return TrimmingOperationResult.CreatedNewInsertionTable; + } + if (insertNewTable.Rows.Count == 0 && updateExistingTable.Rows.Count > 0) + { + return TrimmingOperationResult.CreatedUpdateTable; + } return TrimmingOperationResult.CreatedNewInsertionAndUpdateTables; } @@ -2383,6 +2394,18 @@ namespace AdvertsingProfitControl } } + if (insertNewTable.Rows.Count == 0 && updateExistingTable.Rows.Count == 0) + { + return TrimmingOperationResult.NoChangesRequired; + } + if (insertNewTable.Rows.Count > 0 && updateExistingTable.Rows.Count == 0) + { + return TrimmingOperationResult.CreatedNewInsertionTable; + } + if (insertNewTable.Rows.Count == 0 && updateExistingTable.Rows.Count > 0) + { + return TrimmingOperationResult.CreatedUpdateTable; + } return TrimmingOperationResult.CreatedNewInsertionAndUpdateTables; } @@ -2644,6 +2667,19 @@ namespace AdvertsingProfitControl updateExistingTable.Rows.Add(newRow); } } + + if (insertNewTable.Rows.Count == 0 && updateExistingTable.Rows.Count == 0) + { + return TrimmingOperationResult.NoChangesRequired; + } + if (insertNewTable.Rows.Count > 0 && updateExistingTable.Rows.Count == 0) + { + return TrimmingOperationResult.CreatedNewInsertionTable; + } + if (insertNewTable.Rows.Count == 0 && updateExistingTable.Rows.Count > 0) + { + return TrimmingOperationResult.CreatedUpdateTable; + } return TrimmingOperationResult.CreatedNewInsertionAndUpdateTables; } diff --git a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.application b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.application index d1418b9..786f289 100644 --- a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.application +++ b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.application @@ -14,7 +14,7 @@ - LsVCFrHqz9eC+Xb4h5OB0HAtYPeUrflbVosVWeS6Y6M= + ZL5dwalV8JqCCLJbc11enpP7V0Ttl3QSWzyKFXpqQeA= diff --git a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.exe.manifest b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.exe.manifest index 50bd7bc..efcc546 100644 --- a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.exe.manifest +++ b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.exe.manifest @@ -50,7 +50,7 @@ - iKpPfS5yNYsJ6mqWS0c0RqAtEX1hyz5JzaK7T5nObHU= + Jb2/XD/xmkjSGdpdtKCMoj9SdjztlACxydkOCDCOUcU= diff --git a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application index d1418b9..786f289 100644 --- a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application +++ b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.application @@ -14,7 +14,7 @@ - LsVCFrHqz9eC+Xb4h5OB0HAtYPeUrflbVosVWeS6Y6M= + ZL5dwalV8JqCCLJbc11enpP7V0Ttl3QSWzyKFXpqQeA= diff --git a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest index 50bd7bc..efcc546 100644 --- a/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest +++ b/AdvertsingProfitControl/bin/Debug/AdvertsingProfitControl.vshost.exe.manifest @@ -50,7 +50,7 @@ - iKpPfS5yNYsJ6mqWS0c0RqAtEX1hyz5JzaK7T5nObHU= + Jb2/XD/xmkjSGdpdtKCMoj9SdjztlACxydkOCDCOUcU= diff --git a/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.application b/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.application index d1418b9..786f289 100644 --- a/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.application +++ b/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.application @@ -14,7 +14,7 @@ - LsVCFrHqz9eC+Xb4h5OB0HAtYPeUrflbVosVWeS6Y6M= + ZL5dwalV8JqCCLJbc11enpP7V0Ttl3QSWzyKFXpqQeA= diff --git a/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.exe.manifest b/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.exe.manifest index 50bd7bc..efcc546 100644 --- a/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.exe.manifest +++ b/AdvertsingProfitControl/obj/Debug/AdvertsingProfitControl.exe.manifest @@ -50,7 +50,7 @@ - iKpPfS5yNYsJ6mqWS0c0RqAtEX1hyz5JzaK7T5nObHU= + Jb2/XD/xmkjSGdpdtKCMoj9SdjztlACxydkOCDCOUcU=