diff --git a/C968Project/Helpers.cs b/C968Project/Helpers.cs new file mode 100644 index 0000000..1e1d062 --- /dev/null +++ b/C968Project/Helpers.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace C968Project +{ + static class Helpers + { + public static void SetTextBoxValidationState(TextBox textBox, bool isValid) + { + if (isValid) + { + textBox.BackColor = Color.White; + } + else + { + textBox.BackColor = Color.Red; + } + } + + public static bool ConfirmDelete() + { + var result = MessageBox.Show("Are you sure you want to delete this item?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + return true; + } + + return false; + } + } +} diff --git a/C968Project/Inventory.cs b/C968Project/Inventory.cs index b590598..c766e91 100644 --- a/C968Project/Inventory.cs +++ b/C968Project/Inventory.cs @@ -90,5 +90,17 @@ public class Inventory Parts[index] = newPart; } + + public void PropogatePartModificationToAssociatedProducts(Part oldPart, Part newPart) + { + foreach (var product in Products) + { + if (product.AssociatedParts.Contains(oldPart)) + { + product.RemoveAssociatedPart(product.AssociatedParts.IndexOf(oldPart)); + product.AddAssociatedPart(newPart); + } + } + } } \ No newline at end of file diff --git a/C968Project/Product.cs b/C968Project/Product.cs index 5bb79e4..eb79a0a 100644 --- a/C968Project/Product.cs +++ b/C968Project/Product.cs @@ -4,7 +4,7 @@ namespace C968Project; public class Product { - public BindingList AssociatedParts { get; set; } + public BindingList AssociatedParts { get; set; } = new(); public int ProductId { get; set; } public string Name { get; set; } public float Price { get; set; } @@ -12,15 +12,39 @@ public class Product public int Min { get; set; } public int Max { get; set; } - public void AddAssociatedPart(Part part){} + public void AddAssociatedPart(Part part) + { + if (AssociatedParts.Contains(part)) + { + MessageBox.Show($"Product {Name} already has an association with part {part.Name}", "", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + AssociatedParts.Add(part); + } public bool RemoveAssociatedPart(int partIndex) { - return false; + var part = LookupAssociatedPart(partIndex); + + if (part is null) + { + MessageBox.Show($"An error occured while trying to locate the part at index {partIndex}.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + + AssociatedParts.Remove(part); + return true; } - public Part LookupAssociatedPart(int partIndex) + public Part? LookupAssociatedPart(int partIndex) { - return null; + if (partIndex > AssociatedParts.Count) + { + MessageBox.Show($"Error trying to locate part at index {partIndex}. Out of bounds.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); + return null; + } + + return AssociatedParts[partIndex]; } } \ No newline at end of file diff --git a/C968Project/Program.cs b/C968Project/Program.cs index fa80987..1bcaff6 100644 --- a/C968Project/Program.cs +++ b/C968Project/Program.cs @@ -34,7 +34,6 @@ static class Program private static Product _testProduct = new Product() { Name = "Product", - AssociatedParts = new(){_testInhousePart, _testOutsourcedPart}, InStock = 500, Max = 4000, Min = 2, @@ -51,6 +50,7 @@ static class Program Inventory.AddPart(_testOutsourcedPart); Inventory.AddPart(_testInhousePart); Inventory.AddProduct(_testProduct); + Inventory.Products[0].AddAssociatedPart(Inventory.Parts[0]); // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. diff --git a/C968Project/Views/AddModifyPartScreen.cs b/C968Project/Views/AddModifyPartScreen.cs index 5f7f079..a603d0d 100644 --- a/C968Project/Views/AddModifyPartScreen.cs +++ b/C968Project/Views/AddModifyPartScreen.cs @@ -82,13 +82,15 @@ namespace C968Project.Views } else { - MessageBox.Show("Error modifying part: Could not find part index", "Error", MessageBoxButtons.OK); + MessageBox.Show("Error modifying part: Could not find part index", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } - var part = Program.Inventory.Parts[partIndex]; - var partId = part.PartID; - Program.Inventory.Parts[partIndex] = CreatePart(partId); + var oldPart = Program.Inventory.Parts[partIndex]; + var oldPartId = oldPart.PartID; + var modifiedPart = CreatePart(oldPartId); + Program.Inventory.Parts[partIndex] = modifiedPart; + Program.Inventory.PropogatePartModificationToAssociatedProducts(oldPart, modifiedPart); } private void AddPart() @@ -205,18 +207,6 @@ namespace C968Project.Views return _isNameValid && _isInventoryValid && _isPriceValid && _isMaxValid && _isMinValid && _isMachineOrCompanyValid; } - private void SetTextBoxValidationState(TextBox textBox, bool isValid) - { - if (isValid) - { - textBox.BackColor = Color.White; - } - else - { - textBox.BackColor = Color.Red; - } - } - private void ValidateName() { if (nameTextBox.Text == string.Empty) @@ -230,7 +220,7 @@ namespace C968Project.Views _isNameValid = true; } - SetTextBoxValidationState(nameTextBox, _isNameValid); + Helpers.SetTextBoxValidationState(nameTextBox, _isNameValid); } private void nameTextBox_Validating(object sender, CancelEventArgs e) @@ -274,7 +264,7 @@ namespace C968Project.Views errorProvider1.SetError(inventoryTextBox, "Field must contain an integer value"); } - SetTextBoxValidationState(inventoryTextBox, _isInventoryValid); + Helpers.SetTextBoxValidationState(inventoryTextBox, _isInventoryValid); } private void inventoryTextBox_Validating(object sender, CancelEventArgs e) @@ -297,7 +287,7 @@ namespace C968Project.Views errorProvider1.SetError(priceCostTextBox, "Field must contain a floating point number"); } - SetTextBoxValidationState(priceCostTextBox, _isPriceValid); + Helpers.SetTextBoxValidationState(priceCostTextBox, _isPriceValid); } private void priceCostTextBox_Validating(object sender, CancelEventArgs e) @@ -321,7 +311,7 @@ namespace C968Project.Views } ValidateInventory(); - SetTextBoxValidationState(maxTextBox, _isMaxValid); + Helpers.SetTextBoxValidationState(maxTextBox, _isMaxValid); } private void maxTextBox_Validating(object sender, CancelEventArgs e) @@ -345,7 +335,7 @@ namespace C968Project.Views } ValidateInventory(); - SetTextBoxValidationState(minTextBox, _isMinValid); + Helpers.SetTextBoxValidationState(minTextBox, _isMinValid); } private void minTextBox_Validating(object sender, CancelEventArgs e) @@ -396,7 +386,7 @@ namespace C968Project.Views } } - SetTextBoxValidationState(machineCompanyTextBox, _isMachineOrCompanyValid); + Helpers.SetTextBoxValidationState(machineCompanyTextBox, _isMachineOrCompanyValid); } private void machineCompanyTextBox_Validating(object sender, CancelEventArgs e) diff --git a/C968Project/Views/AddModifyProductScreen.cs b/C968Project/Views/AddModifyProductScreen.cs index 620be9a..bf5f390 100644 --- a/C968Project/Views/AddModifyProductScreen.cs +++ b/C968Project/Views/AddModifyProductScreen.cs @@ -12,9 +12,14 @@ namespace C968Project.Views { public partial class AddModifyProductScreen : Form { - public AddModifyProductScreen() + private ScreenOption screenOption; + private Product? _product; + + public AddModifyProductScreen(ScreenOption screenOption, Product? product) { InitializeComponent(); + this.screenOption = screenOption; + _product = product; } } } diff --git a/C968Project/Views/MainScreen.cs b/C968Project/Views/MainScreen.cs index a900f6f..6d29f3f 100644 --- a/C968Project/Views/MainScreen.cs +++ b/C968Project/Views/MainScreen.cs @@ -24,7 +24,11 @@ public partial class MainScreen : Form private void partsModifyButton_Click(object sender, EventArgs e) { - if (partsDataGridView.CurrentCell is null) return; + if (partsDataGridView.CurrentCell is null) + { + MessageBox.Show("No part selected", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } Part part = Program.Inventory.LookupPart(partsDataGridView.CurrentCell.RowIndex); if (part is null) return; AddModifyPartScreen partScreen = new AddModifyPartScreen(ScreenOption.MODIFY, part); @@ -33,8 +37,29 @@ public partial class MainScreen : Form private void partsDeleteButton_Click(object sender, EventArgs e) { + if (partsDataGridView.CurrentCell is null) + { + MessageBox.Show("No part selected", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } Part part = Program.Inventory.LookupPart(partsDataGridView.CurrentCell.RowIndex); - Program.Inventory.DeletePart(part); + if (part is null) return; + if (CheckPartForProductAssociation(part)) return; + if (Helpers.ConfirmDelete()) Program.Inventory.DeletePart(part); + } + + private bool CheckPartForProductAssociation(Part part) + { + foreach (var product in Program.Inventory.Products) + { + if (product.AssociatedParts.Contains(part)) + { + MessageBox.Show($"Cannot delete part as it is associated with product: {product.Name}", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return true; + } + } + + return false; } private void partsSearchButton_Click(object sender, EventArgs e) @@ -45,23 +70,54 @@ public partial class MainScreen : Form // --- Products private void productsAddButton_Click(object sender, EventArgs e) { - AddModifyProductScreen productScreen = new AddModifyProductScreen(); - productScreen.Show(); + //AddModifyProductScreen productScreen = new AddModifyProductScreen(); + //productScreen.Show(); } private void productsModifyButton_Click(object sender, EventArgs e) { - AddModifyProductScreen productScreen = new AddModifyProductScreen(); - productScreen.Show(); + if (productsDataGridView.CurrentCell is null) + { + MessageBox.Show("No product selected", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + //AddModifyProductScreen productScreen = new AddModifyProductScreen(); + //productScreen.Show(); } private void productsDeleteButton_Click(object sender, EventArgs e) { + if (productsDataGridView.CurrentCell is null) + { + MessageBox.Show("No product selected", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + Product product = Program.Inventory.LookupProduct(productsDataGridView.CurrentCell.RowIndex); + if (product is null) return; + if (CheckProductForPartAssociations(product)) return; + if (Helpers.ConfirmDelete()) Program.Inventory.RemoveProduct(Program.Inventory.Products.IndexOf(product)); + } + private bool CheckProductForPartAssociations(Product product) + { + if (product.AssociatedParts.Count == 0) return false; + + string associatedParts = ""; + + foreach (var part in product.AssociatedParts) + { + associatedParts += part.Name + "\n"; + } + + MessageBox.Show($"Cannot delete product as it has association with parts:\n{associatedParts}", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); + + return true; } private void productsSearchButton_Click(object sender, EventArgs e) { // TODO: Search functionality } + + } \ No newline at end of file