示例#1
0
 /// <summary>
 /// Update the depot in the database
 /// </summary>
 /// <param name="depot"></param>
 public static void UpdateDepot(Depot depot)
 {
     using (IDbConnection cnn = new SQLiteConnection(LoadConnectionString()))
     {
         cnn.Execute("UPDATE 'Depots' SET \"Name\" = @Name, \"CSVName\" = @CSVName, \"OrderName\" = @OrderName WHERE \"Id\" = @Id", depot);
     }
 }
示例#2
0
        /// <summary>
        /// A function that will export the orders with provided order ID to a CSV file
        /// </summary>
        /// <param name="orderId">The orderID that is used to group orders together</param>
        public static void ExportOrdersToCSV(string orderId)
        {
            // Create a list of orders that we want to process and populate it
            ObservableCollection <Order> orders = IoC.Orders().GetAllOrdersWithID(orderId);

            // Make sure that list is not empty
            if (orders.Count == 0)
            {
                return;
            }

            // Create a list of strings which will represent lines on csv files
            List <string> lines = new List <string>();

            // Add the row of headings
            lines.Add("Customer,Branch,Required Date,Customer Reference,Product Code,Order Qty,Price,");

            // Iterate over the list of orders that need to be printed
            foreach (Order order in orders)
            {
                // Get customer and depot for each
                Customer cust  = IoC.Customers().GetCustomerByID(order.CustomerID);
                Depot    depot = cust.GetDepot(order.DepotID);

                foreach (OrderProduct product in order.Products)
                {
                    // Get the price of the current product
                    decimal price = cust.GetProduct(product.ProductID).Price;
                    // Convert the price into the correct format for exporting
                    string priceString = price == 0m ? "" : string.Format(CultureInfo.CreateSpecificCulture("en-GB"), "{0:F2}", price);
                    // Add the line with all required information into the list of lines
                    lines.Add($"{ cust.CSVName },{ depot.CSVName },{ order.Date.ToShortDateString() },{ order.OrderReference },{ cust.GetProduct(product.ProductID).CSVName },{ product.Quantity },{ priceString },");
                }
            }

            if (lines.Count > 0)
            {
                DateTime time     = DateTime.Now;
                string   pcName   = Environment.MachineName;
                string   fileName = $"order_{pcName}_{time.Year}_{time.Month}_{time.Day}_{time.Hour}_{time.Minute}_{time.Second}_{orderId}.csv";

                UserSettings settings = Settings.LoadSettings();

                // Before saving the file, make sure that the export path exists, if not then create it
                if (!Directory.Exists(settings.UserCSVExportPath))
                {
                    Directory.CreateDirectory(settings.UserCSVExportPath);
                }

                // Create the file
                File.WriteAllLines($"{ settings.UserCSVExportPath }\\{ fileName }", lines);
            }
        }
示例#3
0
        /// <summary>
        /// Add a new depot to the list of depots if it doesn't already exist
        /// </summary>
        /// <param name="depot">A <see cref="Depot"/> object</param>
        /// <returns><see cref="bool"/> false if the depot already exists</returns>
        public bool AddDepot(Depot depot)
        {
            // Make sure to check whether this depot exists first
            // We don't want duplicate depots
            if (!HasDepot(depot.Id))
            {
                Depots.Add(depot);
                return(true);
            }

            return(false);
        }
示例#4
0
        /// <summary>
        /// A function that checks if a depot with this CSVName and OrderName already exists for this customer
        /// </summary>
        /// <param name="depot">A <see cref="Depot"/> object to compare</param>
        /// <returns><see cref="bool"/> whether the depot already exists or not</returns>
        public bool SameDepotExists(Depot depot)
        {
            foreach (Depot ourDepot in Depots)
            {
                if (ourDepot.CSVName == depot.CSVName && ourDepot.OrderName == depot.OrderName)
                {
                    return(true);
                }
            }

            return(false);
        }
示例#5
0
        /// <summary>
        /// Add a new depot to the database
        /// </summary>
        /// <param name="depot">A <see cref="Depot"/> object to be added</param>
        public static Depot AddDepot(Depot depot)
        {
            Depot newDepot;

            using (IDbConnection cnn = new SQLiteConnection(LoadConnectionString()))
            {
                var result = cnn.Query <int>("INSERT INTO 'Depots' (CustomerId, Name, CSVName, OrderName) VALUES (@CustomerId, @Name, @CSVName, @OrderName); SELECT last_insert_rowid();", depot).ToList();
                newDepot = cnn.QuerySingle <Depot>($"SELECT * FROM 'Depots' WHERE \"Id\" = {result[0]}", new DynamicParameters());
            }

            return(newDepot);
        }
示例#6
0
        /// <summary>
        /// A function that reads the order and extracts all required information
        /// </summary>
        /// <param name="orderData">The data that we should read from</param>
        /// <param name="fileName">Name of the order file</param>
        /// <param name="customer">Customer associated with this order</param>
        public static async void ParseOrderAsync(DataSet orderData, string fileName, Customer customer)
        {
            foreach (DataTable table in orderData.Tables)
            {
                // TODO: Future improvement: consolidate errors of the same type together and display at once

                // Variables that will be required
                Dictionary <int, List <OrderWarning> > depotWarnings = new Dictionary <int, List <OrderWarning> >();
                List <string> readQtyErrors = new List <string>();

                // Required data to extract in string form
                string dateString     = null;
                string orderReference = null;
                Dictionary <int, string>  depotStrings    = new Dictionary <int, string>();
                Dictionary <int, string>  productStrings  = new Dictionary <int, string>();
                Dictionary <Cell, double> orderQuantities = new Dictionary <Cell, double>();

                // Required data
                List <Depot>   depots       = new List <Depot>();
                List <Product> products     = new List <Product>();
                DateTime       deliveryDate = DateTime.MinValue;

                // Data locations
                Cell dateCell        = new Cell("D1");
                int  productCol1     = 1;
                int  productCol2     = 3;
                int  productRowStart = 3;
                int  depotRow        = 2;
                int  depotColStart   = 5;
                int  depotColEnd     = table.Columns.Count - 1;
                int  refCol          = table.Columns.Count;

                // Extract the data
                dateString     = GetCell(dateCell, table);
                orderReference = GetCell(refCol, 1, table);

                // Get list of depots
                for (int c = depotColStart; c <= depotColEnd; c++)
                {
                    depotStrings.Add(c, GetCell(c, depotRow, table));
                }

                // Get list of products
                for (int r = productRowStart; r < productRowStart + 10; r++)
                {
                    string c1 = GetCell(productCol1, r, table);
                    string c2 = GetCell(productCol2, r, table);
                    if (c1 == null && c2 == null)
                    {
                        break;
                    }
                    productStrings.Add(r, $"{c1}{c2}");
                }

                // Get all cells wich contain ordered product
                for (int c = depotColStart; c <= depotColEnd; c++)
                {
                    for (int r = productRowStart; r <= productRowStart + productStrings.Count - 1; r++)
                    {
                        Cell   cell      = new Cell(c, r);
                        string cellValue = GetCell(cell, table);
                        if (cellValue != null)
                        {
                            if (double.TryParse(cellValue, out double quantity))
                            {
                                if (quantity > 0.0)
                                {
                                    orderQuantities.Add(cell, quantity);
                                }
                            }
                            else
                            {
                                readQtyErrors.Add($"Depot: {depotStrings[c]}, Product: {productStrings[r]}\n");
                            }
                        }
                    }
                }

                List <int> usedDepotColumns = new List <int>();

                // Get all the used depot information
                foreach (var orderQuantity in orderQuantities)
                {
                    foreach (var depotString in depotStrings)
                    {
                        if (orderQuantity.Key.column == depotString.Key)
                        {
                            if (customer.HasDepotOrderName(depotString.Value))
                            {
                                if (!usedDepotColumns.Contains(depotString.Key))
                                {
                                    usedDepotColumns.Add(depotString.Key);
                                }
                            }
                            else
                            {
                                string errorMessage = $"Unknown depot \"{depotString.Value}\" was found in file {fileName}.\n" +
                                                      "If this is a new depot, please add it to the list.\n" +
                                                      $"\nThis file will be processed without depot \"{depotString.Value}\". You will need to add order for that depot manually.";

                                // Display error message to the user
                                await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                                {
                                    Title      = "File Processing Error",
                                    Message    = errorMessage,
                                    ButtonText = "OK"
                                });
                            }
                        }
                    }
                }

                List <int> usedProductRows = new List <int>();

                // Get all the used product information
                foreach (var orderQuantity in orderQuantities)
                {
                    foreach (var productString in productStrings)
                    {
                        if (orderQuantity.Key.row == productString.Key)
                        {
                            if (customer.HasProductOrderName(productString.Value))
                            {
                                if (!usedProductRows.Contains(productString.Key))
                                {
                                    usedProductRows.Add(productString.Key);
                                }
                            }
                            else
                            {
                                string errorMessage = $"Unknown product \"{productString.Value}\" was found in file {fileName}.\n" +
                                                      "If this is a new product, please add it to the list.\n" +
                                                      $"\nThis file will be processed without product \"{productString.Value}\". You will need to add that product to order manually if required.";

                                // Display error message to the user
                                await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                                {
                                    Title      = "File Processing Error",
                                    Message    = errorMessage,
                                    ButtonText = "OK"
                                });
                            }
                        }
                    }
                }

                // Validation
                // Make sure that we have found all necessary data
                if (orderQuantities.Count == 0 || orderReference == null || dateString == null)
                {
                    string errorMessage = $"Following issues have been found in file {fileName}:\n";
                    if (orderQuantities.Count == 0)
                    {
                        errorMessage += "* No orders have been found\n";
                    }
                    if (orderReference == null)
                    {
                        errorMessage += "* PO reference number was not found\n";
                    }
                    if (dateString == null)
                    {
                        errorMessage += "* Delivery date was not found\n";
                    }
                    errorMessage += "\nThis file was not processed.\n";
                    errorMessage += "If you think this file has all the correct data, please contact Patryk Z.";

                    // Display error message to the user
                    await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                    {
                        Title      = "File Processing Error",
                        Message    = errorMessage,
                        ButtonText = "OK"
                    });
                }
                else
                {
                    // Process and validate delivery date
                    if (!DateTime.TryParse(dateString.Trim(), out deliveryDate))
                    {
                        string errorMessage = $"Could not read the date from file {fileName}.\n" +
                                              "Please check the date in Excel file. If the date format looks correct then please contact Patryk Z.\n" +
                                              "\nThis file was not processed.";

                        // Display error message to the user
                        await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                        {
                            Title      = "File Processing Error",
                            Message    = errorMessage,
                            ButtonText = "OK"
                        });
                    }
                    else if (deliveryDate != DateTime.Today.AddDays(1))
                    {
                        string errorMessage = $"Delivery date ({deliveryDate.ToShortDateString()}) in file {fileName} is not tomorrow.";

                        // Create a new warning object for this order
                        foreach (int col in usedDepotColumns)
                        {
                            if (!depotWarnings.ContainsKey(col))
                            {
                                depotWarnings.Add(col, new List <OrderWarning>());
                            }
                            depotWarnings[col].Add(new OrderWarning(OrderWarning.WarningType.UnusualDate, errorMessage));
                        }

                        // Display error message to the user
                        await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                        {
                            Title      = "Unusual Date Warning",
                            Message    = errorMessage,
                            ButtonText = "OK"
                        });
                    }

                    if (orderReference.EndsWith("01"))
                    {
                        string errorMessage = $"Order reference {orderReference} in file {fileName} indicates that this is a provisional order.\n\n" +
                                              "Provisional orders usually end with \"01\" while full orders usually end with \"02\".\n\n" +
                                              "Would you like to process this order anyway?";

                        // Display error message to the user
                        var result = await IoC.UI.ShowMessage(new YesNoBoxDialogViewModel
                        {
                            Title    = "Order Reference Warning",
                            Question = errorMessage
                        });

                        if (result == DialogResult.No)
                        {
                            return;
                        }
                    }

                    // Display all the cells that could not be read from
                    if (readQtyErrors.Count > 0)
                    {
                        string errorMessage = $"Not all data could be read from file {fileName}.\n" +
                                              "Please see below which orders could not be read:\n\n";
                        foreach (string error in readQtyErrors)
                        {
                            errorMessage += error;
                        }
                        errorMessage += "\nThis file was not processed.";

                        // Display error message to the user
                        await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                        {
                            Title      = "File Processing Error",
                            Message    = errorMessage,
                            ButtonText = "OK"
                        });
                    }

                    // Create the order objects
                    foreach (int col in usedDepotColumns)
                    {
                        Depot depot = customer.GetDepot(depotStrings[col]);
                        Order order = new Order(orderReference, deliveryDate, customer.Id, depot.Id);
                        // Add products
                        foreach (int row in usedProductRows)
                        {
                            Cell cell = new Cell(col, row);
                            foreach (var orderQuantity in orderQuantities)
                            {
                                if (orderQuantity.Key.IsSameAs(cell) && orderQuantity.Value > 0.0)
                                {
                                    Product product = customer.GetProduct(productStrings[row]);
                                    order.AddProduct(product.Id, orderQuantity.Value);
                                }
                            }
                        }
                        // Add warnings
                        if (depotWarnings.ContainsKey(col))
                        {
                            foreach (OrderWarning warning in depotWarnings[col])
                            {
                                order.AddWarning(warning);
                            }
                        }

                        if (order.Products.Count > 0)
                        {
                            // Check if the same order already exists
                            if (IoC.Orders().HasOrder(order))
                            {
                                string errorMessage = $"The order in file {fileName} for depot {order.DepotName} could not be processed. The same order already exists.";

                                // Display error message to the user
                                await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                                {
                                    Title      = "Order Processing Error",
                                    Message    = errorMessage,
                                    ButtonText = "OK"
                                });
                            }
                            else
                            {
                                // Add this order to the list
                                IoC.Orders().AddOrder(order);
                            }
                        }
                    }
                }
            }
        }
        public static async void ParseOrderAsync(string[] orderText, string fileName, Customer customer)
        {
            // Variables that will be required
            bool   isAllDataFound         = true;
            double unknownProductQuantity = 0.0;
            List <OrderWarning> warnings  = new List <OrderWarning>();

            // Required data to extract in string form
            string depotString      = null;
            string dateString       = null;
            string orderTotalString = null;
            string orderReference   = null;
            Dictionary <string, string> productStrings = new Dictionary <string, string>();

            // Required data
            Depot               depot        = null;
            DateTime            deliveryDate = DateTime.MinValue;
            double              orderTotal   = 0.0;
            List <OrderProduct> products     = new List <OrderProduct>();

            // Product code specification
            int productCodeMinLength = 7;

            // Iterate over the lines to find required data
            foreach (string line in orderText)
            {
                // Look for depot name if not already found
                if (depotString == null)
                {
                    if (customer.HasDepotOrderName(line))
                    {
                        depotString = line;
                    }
                }

                // Look for order reference if not already found
                if (orderReference == null)
                {
                    string orderReferenceTitle = "Customer PO Number: ";
                    if (line.StartsWith(orderReferenceTitle))
                    {
                        orderReference = line.Substring(orderReferenceTitle.Length);
                    }
                }

                // Look for delivery date if not already found
                if (dateString == null)
                {
                    string deliveryDateTitle = "Delivery Date: ";
                    if (line.StartsWith(deliveryDateTitle))
                    {
                        dateString = line.Substring(deliveryDateTitle.Length);
                    }
                }

                // Look for total boxes if not already found
                if (orderTotalString == null)
                {
                    string orderTotalTitle = "Total Boxes : ";
                    if (line.StartsWith(orderTotalTitle))
                    {
                        orderTotalString = line.Substring(orderTotalTitle.Length);
                    }
                }

                // Look for products
                if (line.Length > productCodeMinLength)
                {
                    int strLength = 0;
                    for (int c = 0; c < line.Length; c++)
                    {
                        if (char.IsWhiteSpace(line, c))
                        {
                            strLength = c;
                            break;
                        }
                    }

                    if (strLength >= productCodeMinLength && line.Substring(0, strLength).All(char.IsDigit))
                    {
                        int qtyAtIndex = 0;
                        for (int i = line.Length - 1; i > 0; i--)
                        {
                            if (char.IsWhiteSpace(line, i))
                            {
                                qtyAtIndex = i + 1;
                                break;
                            }
                        }

                        string productNumber   = line.Substring(0, strLength);
                        string productQuantity = line.Substring(qtyAtIndex, line.Length - qtyAtIndex);

                        productStrings.Add(productNumber, productQuantity);
                    }
                }
            }

            // Make sure that we have found all necessary data
            if (depotString == null || orderReference == null || dateString == null || orderTotalString == null || productStrings.Count == 0)
            {
                string errorMessage = $"Following issues have been found in file {fileName}:\n";
                if (depotString == null)
                {
                    errorMessage += "* Depot name was not found (that likely means that it's a new depot that Order Reader doesn't know about yet, please manually check and add a new depot if required)\n";
                }
                if (orderReference == null)
                {
                    errorMessage += "* PO reference number was not found\n";
                }
                if (dateString == null)
                {
                    errorMessage += "* Delivery date was not found\n";
                }
                if (orderTotalString == null)
                {
                    errorMessage += "* Total quantity was not found\n";
                }
                if (productStrings.Count == 0)
                {
                    errorMessage += "* No products were found\n";
                }
                errorMessage  += "\nThis file was not processed.\n";
                errorMessage  += "If you think this file has all the correct data, please contact Patryk Z.";
                isAllDataFound = false;

                // Display error message to the user
                await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                {
                    Title      = "File Processing Error",
                    Message    = errorMessage,
                    ButtonText = "OK"
                });
            }
            else
            {
                // Process and validate delivery date
                if (!DateTime.TryParse(dateString.Trim(), out deliveryDate))
                {
                    string errorMessage = $"Could not read the date from file {fileName}.\n" +
                                          "Please check the date in PDF file. If the date format looks correct then please contact Patryk Z.\n" +
                                          "\nThis file was not processed.";
                    isAllDataFound = false;

                    // Display error message to the user
                    await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                    {
                        Title      = "File Processing Error",
                        Message    = errorMessage,
                        ButtonText = "OK"
                    });
                }
                else if (deliveryDate != DateTime.Today.AddDays(1))
                {
                    string errorMessage = $"Delivery date ({deliveryDate.ToShortDateString()}) in file {fileName} is not tomorrow.";

                    // Create a new warning object for this order
                    warnings.Add(new OrderWarning(OrderWarning.WarningType.UnusualDate, errorMessage));

                    // Display error message to the user
                    await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                    {
                        Title      = "Unusual Date Warning",
                        Message    = errorMessage,
                        ButtonText = "OK"
                    });
                }

                // Process and validate all products
                foreach (var product in productStrings)
                {
                    // Make sure that this product exists
                    if (!customer.HasProductOrderName(product.Key))
                    {
                        // If the quantity of unknown product can be parsed then we can add this product and just display a warning
                        // Otherwise, we can not process this order
                        if (double.TryParse(product.Value, NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out double quantity))
                        {
                            string errorMessage = $"Unknown product ({product.Key}) in file {fileName}.\n" +
                                                  "You can process this order without that product if you intend to add it manually later or if you think it's been put on by mistake.";

                            // Add the quantity to unknown product quantity
                            unknownProductQuantity += quantity;

                            // Create a warning object
                            warnings.Add(new OrderWarning(OrderWarning.WarningType.UnknownProduct, errorMessage));

                            // Display error message to the user
                            await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                            {
                                Title      = "Unknown Product Warning",
                                Message    = errorMessage,
                                ButtonText = "OK"
                            });
                        }
                        else
                        {
                            string errorMessage = $"Unknown product ({product.Key}) in file {fileName}.\n" +
                                                  "If this is a new product that Order Reader doesn't know about yet, please add it to Order Reader and try processing this file again. Otherwise, please contact Patryk Z." +
                                                  "This file was not processed.";

                            isAllDataFound = false;

                            // Display error message to the user
                            await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                            {
                                Title      = "Unknown Product Error",
                                Message    = errorMessage,
                                ButtonText = "OK"
                            });
                        }
                    }
                    else
                    {
                        // Get the product quantity
                        if (double.TryParse(product.Value, NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out double quantity))
                        {
                            OrderProduct orderProduct = new OrderProduct(customer.Id, customer.GetProduct(product.Key).Id, quantity);
                            products.Add(orderProduct);
                        }
                        else
                        {
                            string errorMessage = $"Could not read product quantity ({product.Key}) from file {fileName}.\n" +
                                                  "Please check the product quantity in PDF file. If the quantity looks correct then please contact Patryk Z.\n" +
                                                  "This file was not processed.";

                            isAllDataFound = false;

                            // Display error message to the user
                            await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                            {
                                Title      = "Order Processing Error",
                                Message    = errorMessage,
                                ButtonText = "OK"
                            });
                        }
                    }
                }

                // Validate the total quantity from PDF file
                if (!double.TryParse(orderTotalString, NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out orderTotal))
                {
                    string errorMessage = $"Could not read the total quantity from file {fileName}.\n" +
                                          "Please check the total quantity in PDF file. If the quantity looks correct then please contact Patryk Z.\n" +
                                          "This file was not processed.";

                    isAllDataFound = false;

                    // Display error message to the user
                    await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                    {
                        Title      = "Order Processing Error",
                        Message    = errorMessage,
                        ButtonText = "OK"
                    });
                }

                // Make sure we have valid products to add
                if (products.Count == 0)
                {
                    string errorMessage = $"No valid products foud in file {fileName}.\n" +
                                          "This file was not processed.";

                    isAllDataFound = false;

                    // Display error message to the user
                    await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                    {
                        Title      = "Order Processing Error",
                        Message    = errorMessage,
                        ButtonText = "OK"
                    });
                }

                // Create the depot object
                depot = customer.GetDepot(depotString);

                // If we found all required data, create the order
                if (isAllDataFound)
                {
                    // Create a  new order object
                    Order order = new Order(orderReference, deliveryDate, customer.Id, depot.Id);

                    // Add products to this order
                    foreach (OrderProduct product in products)
                    {
                        order.AddProduct(product);
                    }

                    // Add warnings to this order
                    foreach (OrderWarning warning in warnings)
                    {
                        order.AddWarning(warning);
                    }

                    // Make sure that the total product quantity is correct
                    if (order.GetTotalProductQuantity() == orderTotal || order.GetTotalProductQuantity() == orderTotal - unknownProductQuantity)
                    {
                        // Check if the same order already exists
                        if (IoC.Orders().HasOrder(order) || IoC.Orders().HasOrderWithSameReference(order))
                        {
                            string errorMessage = $"The order in file {fileName} could not be processed. An order with the same reference number already exists.";

                            // Display error message to the user
                            await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                            {
                                Title      = "Order Processing Error",
                                Message    = errorMessage,
                                ButtonText = "OK"
                            });
                        }
                        else
                        {
                            // Add this order to the list
                            IoC.Orders().AddOrder(order);
                        }
                    }
                    else
                    {
                        string errorMessage = $"Total field not equal to sum of all product quantities in file {fileName}.\n" +
                                              "Please check the PDF file to see if all product quantities add up to the total amount. " +
                                              "If they do, please contact Patryk Z.\n" +
                                              "This file was not processed.";

                        // Display error message to the user
                        await IoC.UI.ShowMessage(new MessageBoxDialogViewModel
                        {
                            Title      = "Order Processing Error",
                            Message    = errorMessage,
                            ButtonText = "OK"
                        });
                    }
                }
            }
        }