diff --git a/InventoryTraker.Web/App_Start/SeedData.cs b/InventoryTraker.Web/App_Start/SeedData.cs index ec5a185..d8e7aea 100644 --- a/InventoryTraker.Web/App_Start/SeedData.cs +++ b/InventoryTraker.Web/App_Start/SeedData.cs @@ -74,97 +74,213 @@ namespace InventoryTraker.Web { var r = new Random(1); var inventoryTypes = context.InventoryTypes.ToList(); - var cityNames = new List {"Maryville", "Wartburg", "Clinton", "Oak Ridge", "Alcoa", "Jellico"}; - var colorNames = new List {"Red", "Purple", "Blue", "Yellow", "White"}; + var counties = new List {"Blount County", "Morgan County", "Knox County", "Anderson County", "Claiborne County", "Campbell County"}; + var colors = new List {"Red", "Purple", "Blue", "Yellow", "White"}; - for (int i = 0; i < 200; i++) + for (var dd = DateTime.Today.AddYears(-4); dd < DateTime.Today.AddMonths(-2); dd = dd.AddMonths(3)) { - var inventoryType = inventoryTypes.ElementAt(r.Next(0, context.InventoryTypes.Count())); - var addedDate = DateTime.Today.AddMonths(-r.Next(1, 24)); - var expiration = addedDate.AddMonths(r.Next(2, 48)); - var memo = - r.Next(0,3) > 0 - ? colorNames.ElementAt(r.Next(0, colorNames.Count)) + $" {inventoryType.ContainerType}" - : string.Empty; - var quantity = r.Next(5, 112); - - var previousTransaction = new Transaction + // add some inventory + for (int i = 0; i < r.Next(5,10); i++) { - TransactionType = TransactionType.Added, - AddedQuantity = quantity, - Memo = "Arrival", - CurrentQuantity = quantity, - TransactionDate = addedDate, - Timestamp = addedDate - }; - var inventory = new Inventory - { - InventoryType = inventoryType, - ExpirationDate = expiration, - AddedDate = addedDate, - Memo = memo, - Quantity = quantity, - Transactions = new List { previousTransaction} - }; - context.Inventories.Add(inventory); + var inventoryType = inventoryTypes.ElementAt(r.Next(0, context.InventoryTypes.Count())); + var addedDate = dd.AddDays(r.Next(-10, 10)); + var expiration = addedDate.AddMonths(r.Next(2, 48)); + var memo = + r.Next(0, 3) > 0 + ? colors.ElementAt(r.Next(0, colors.Count)) + $" {inventoryType.ContainerType}" + : string.Empty; + var quantity = r.Next(5, 112); - for (int j = 0; j < 5 && previousTransaction.CurrentQuantity > 0; j++) - { - var transactionDate = previousTransaction.TransactionDate.AddDays(r.Next(1, 100)); - if (transactionDate >= DateTime.Today) - break; - - Transaction transaction; - if (transactionDate >= expiration) + var addedTransaction = new Transaction { - if (r.Next(1, 3) == 1) - break; + TransactionType = TransactionType.Added, + AddedQuantity = quantity, + Memo = "Arrival", + CurrentQuantity = quantity, + TransactionDate = addedDate, + Timestamp = addedDate + }; + var inventory = new Inventory + { + InventoryType = inventoryType, + ExpirationDate = expiration, + AddedDate = addedDate, + Memo = memo, + Quantity = quantity, + Transactions = new List {addedTransaction} + }; + context.Inventories.Add(inventory); + } + dd = dd.AddDays(14); + // expire/loss some inventory + var availableInventories = + context.Inventories.Local.Where(i => i.Quantity > 0).ToList(); - transaction = new Transaction + foreach (var inventory in availableInventories) + { + if (inventory.ExpirationDate <= dd && r.Next(0, 3) > 0) + { + var expiredTransaction = new Transaction { TransactionType = TransactionType.Expired, - RemovedQuantity = previousTransaction.CurrentQuantity, + RemovedQuantity = inventory.Quantity, CurrentQuantity = 0, Inventory = inventory, - Memo = $"Expired on {expiration.ToShortDateString()}", - TransactionDate = transactionDate, - Timestamp = transactionDate + Memo = $"Expired on {inventory.ExpirationDate.ToShortDateString()}", + TransactionDate = dd, + Timestamp = dd }; + inventory.Quantity = expiredTransaction.CurrentQuantity; + inventory.Transactions.Add(expiredTransaction); } - else + else if (r.Next(0, 20) == 0) { - var quantityRemoved = r.Next(1, 100); - if (quantityRemoved > previousTransaction.CurrentQuantity) - quantityRemoved = previousTransaction.CurrentQuantity; + var lossQty = r.Next(1, inventory.Quantity + 1); + var lossTransaction = new Transaction + { + TransactionType = TransactionType.Loss, + RemovedQuantity = lossQty, + CurrentQuantity = inventory.Quantity - lossQty, + Inventory = inventory, + Memo = $"Missing", + TransactionDate = dd, + Timestamp = dd + }; + inventory.Quantity = lossTransaction.CurrentQuantity; + inventory.Transactions.Add(lossTransaction); + } + } - var transMemo = $"Distributed to {cityNames.ElementAt(r.Next(0, cityNames.Count))}"; + + dd = dd.AddDays(14); + // distribute some inventory + foreach (var destination in counties) + { + availableInventories = + context.Inventories.Local.Where(i => i.Quantity > 0).ToList(); + + for ( + var i = r.Next(0, availableInventories.Count); + i < availableInventories.Count; + i += r.Next(1, availableInventories.Count / 2)) + { + var inventory = availableInventories.ElementAt(i); + if (inventory.ExpirationDate <= dd) + continue; + + var quantityRemoved = r.Next(1, inventory.Quantity + 1); + + var transMemo = $"Distributed to {destination}"; var transType = TransactionType.Distributed; - if (r.Next(1, 15) == 1) - { - transMemo = "Loss"; - transType = TransactionType.Loss; - } - - transaction = new Transaction + var distributeTransaction = new Transaction { TransactionType = transType, RemovedQuantity = quantityRemoved, - CurrentQuantity = previousTransaction.CurrentQuantity - quantityRemoved, + CurrentQuantity = inventory.Quantity - quantityRemoved, Inventory = inventory, Memo = transMemo, - TransactionDate = transactionDate, - Timestamp = transactionDate + TransactionDate = dd, + Timestamp = dd, + Destination = destination }; + inventory.Quantity = distributeTransaction.CurrentQuantity; + + inventory.Transactions.Add(distributeTransaction); } - - inventory.Quantity = transaction.CurrentQuantity; - - inventory.Transactions.Add(transaction); - - previousTransaction = transaction; } } + + //for (int i = 0; i < 200; i++) + //{ + // var inventoryType = inventoryTypes.ElementAt(r.Next(0, context.InventoryTypes.Count())); + // var addedDate = DateTime.Today.AddMonths(-r.Next(1, 24)); + // var expiration = addedDate.AddMonths(r.Next(2, 48)); + // var memo = + // r.Next(0,3) > 0 + // ? colors.ElementAt(r.Next(0, colors.Count)) + $" {inventoryType.ContainerType}" + // : string.Empty; + // var quantity = r.Next(5, 112); + + // var previousTransaction = new Transaction + // { + // TransactionType = TransactionType.Added, + // AddedQuantity = quantity, + // Memo = "Arrival", + // CurrentQuantity = quantity, + // TransactionDate = addedDate, + // Timestamp = addedDate + // }; + // var inventory = new Inventory + // { + // InventoryType = inventoryType, + // ExpirationDate = expiration, + // AddedDate = addedDate, + // Memo = memo, + // Quantity = quantity, + // Transactions = new List { previousTransaction} + // }; + // context.Inventories.Add(inventory); + + // for (int j = 0; j < 5 && previousTransaction.CurrentQuantity > 0; j++) + // { + // var transactionDate = previousTransaction.TransactionDate.AddDays(r.Next(1, 100)); + // if (transactionDate >= DateTime.Today) + // break; + + // Transaction transaction; + // if (transactionDate >= expiration) + // { + // if (r.Next(1, 3) == 1) + // break; + + //transaction = new Transaction + //{ + // TransactionType = TransactionType.Expired, + // RemovedQuantity = previousTransaction.CurrentQuantity, + // CurrentQuantity = 0, + // Inventory = inventory, + // Memo = $"Expired on {expiration.ToShortDateString()}", + // TransactionDate = transactionDate, + // Timestamp = transactionDate + //}; + // } + // else + // { + // var quantityRemoved = r.Next(1, 100); + // if (quantityRemoved > previousTransaction.CurrentQuantity) + // quantityRemoved = previousTransaction.CurrentQuantity; + + // var destination = counties.ElementAt(r.Next(0, counties.Count)); + // var transMemo = $"Distributed to {destination}"; + // var transType = TransactionType.Distributed; + + // if (r.Next(1, 15) == 1) + // { + // transMemo = "Loss"; + // transType = TransactionType.Loss; + // } + + // transaction = new Transaction + // { + // TransactionType = transType, + // RemovedQuantity = quantityRemoved, + // CurrentQuantity = previousTransaction.CurrentQuantity - quantityRemoved, + // Inventory = inventory, + // Memo = transMemo, + // TransactionDate = transactionDate, + // Timestamp = transactionDate, + // Destination = destination + // }; + // } + + // inventory.Quantity = transaction.CurrentQuantity; + + // inventory.Transactions.Add(transaction); + + // previousTransaction = transaction; + // } + //} } } } \ No newline at end of file diff --git a/InventoryTraker.Web/Controllers/InventoryController.cs b/InventoryTraker.Web/Controllers/InventoryController.cs index 2c772f9..91692e6 100644 --- a/InventoryTraker.Web/Controllers/InventoryController.cs +++ b/InventoryTraker.Web/Controllers/InventoryController.cs @@ -119,11 +119,8 @@ namespace InventoryTraker.Web.Controllers TransactionType = TransactionType.Distributed, RemovedQuantity = quantityForm.Quantity, CurrentQuantity = inventory.Quantity, - Memo = - string.IsNullOrEmpty(form.Memo) - ? $"{form.Memo} | " - : "" - + $"Distributed to {form.Destination}", + Destination = form.Destination, + Memo = form.Memo, Timestamp = DateTime.Now, TransactionDate = form.DistributedDate }); diff --git a/InventoryTraker.Web/Controllers/ReportController.cs b/InventoryTraker.Web/Controllers/ReportController.cs new file mode 100644 index 0000000..8d247ba --- /dev/null +++ b/InventoryTraker.Web/Controllers/ReportController.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Mvc; +using AutoMapper; +using AutoMapper.QueryableExtensions; +using InventoryTraker.Web.Core; +using InventoryTraker.Web.Data; +using InventoryTraker.Web.Models; + +namespace InventoryTraker.Web.Controllers +{ + public class ReportController : ControllerBase + { + private readonly AppDbContext _context; + + public ReportController(AppDbContext context) + { + _context = context; + } + + [HttpGet] + public ActionResult Distribution() + { + return View(); + } + + public ActionResult Distribution(DateTime startDate, DateTime endDate) + { + var query = + from t in _context.Transactions + where + t.TransactionType == TransactionType.Distributed + && t.TransactionDate >= startDate + && t.TransactionDate < endDate + group t by new { t.TransactionDate, t.Destination } + into g + select new + { + Date = g.Key.TransactionDate, + Destination = g.Key.Destination, + Transactions = g.ToList() + //(from transaction in g + //select Mapper.Map(transaction)).ToArray() + }; + + var report = + from item in query.ToArray() + select new DistributionReport + { + Date = item.Date, + Destination = item.Destination, + Transactions = + Mapper.Map, IList> + (item.Transactions).ToArray() + }; + + return BetterJson(report.ToArray()); + } + } +} \ No newline at end of file diff --git a/InventoryTraker.Web/Controllers/TransactionController.cs b/InventoryTraker.Web/Controllers/TransactionController.cs index c541f3d..ade20f9 100644 --- a/InventoryTraker.Web/Controllers/TransactionController.cs +++ b/InventoryTraker.Web/Controllers/TransactionController.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections; +using System.Linq; using System.Web.Mvc; using AutoMapper.QueryableExtensions; using InventoryTraker.Web.Attributes; diff --git a/InventoryTraker.Web/Core/Transaction.cs b/InventoryTraker.Web/Core/Transaction.cs index fbf9de0..dfb7572 100644 --- a/InventoryTraker.Web/Core/Transaction.cs +++ b/InventoryTraker.Web/Core/Transaction.cs @@ -25,6 +25,11 @@ namespace InventoryTraker.Web.Core public string Memo { get; set; } + /// + /// Used only when inventory was distributed + /// + public string Destination { get; set; } + [Required] public DateTime Timestamp { get; set; } } diff --git a/InventoryTraker.Web/InventoryTraker.Web.csproj b/InventoryTraker.Web/InventoryTraker.Web.csproj index e9da99c..ceca3f0 100644 --- a/InventoryTraker.Web/InventoryTraker.Web.csproj +++ b/InventoryTraker.Web/InventoryTraker.Web.csproj @@ -246,9 +246,15 @@ + + + + + + @@ -293,6 +299,10 @@ Always + + + + Designer @@ -319,6 +329,7 @@ + @@ -345,6 +356,8 @@ + + @@ -381,6 +394,7 @@ + Web.config diff --git a/InventoryTraker.Web/Models/DateRangeQuery.cs b/InventoryTraker.Web/Models/DateRangeQuery.cs new file mode 100644 index 0000000..c3f8f83 --- /dev/null +++ b/InventoryTraker.Web/Models/DateRangeQuery.cs @@ -0,0 +1,11 @@ +using System; + +namespace InventoryTraker.Web.Models +{ + public class DateRangeQuery + { + public DateTime StartDate { get; set; } + + public DateTime EndDate { get; set; } + } +} \ No newline at end of file diff --git a/InventoryTraker.Web/Models/DistributionReport.cs b/InventoryTraker.Web/Models/DistributionReport.cs new file mode 100644 index 0000000..7eb067a --- /dev/null +++ b/InventoryTraker.Web/Models/DistributionReport.cs @@ -0,0 +1,13 @@ +using System; + +namespace InventoryTraker.Web.Models +{ + public class DistributionReport + { + public TransactionViewModel[] Transactions; + + public string Destination { get; set; } + + public DateTime Date { get; set; } + } +} \ No newline at end of file diff --git a/InventoryTraker.Web/Models/TransactionViewModel.cs b/InventoryTraker.Web/Models/TransactionViewModel.cs index 7b1af06..eaf4015 100644 --- a/InventoryTraker.Web/Models/TransactionViewModel.cs +++ b/InventoryTraker.Web/Models/TransactionViewModel.cs @@ -17,6 +17,7 @@ namespace InventoryTraker.Web.Models public string ContainerType { get; set; } public DateTime ExpirationDate { get; set; } public DateTime AddedDate { get; set; } + public double WeightPerCase { get; set; } public string TransactionType { get; set; } @@ -32,6 +33,8 @@ namespace InventoryTraker.Web.Models public string Memo { get; set; } + public string Destination { get; set; } + public DateTime Timestamp { get; set; } public void CreateMappings(IMapperConfiguration configuration) @@ -49,6 +52,8 @@ namespace InventoryTraker.Web.Models opt => opt.MapFrom(s => s.Inventory.InventoryType.UnitsPerCase)) .ForMember(d => d.ContainerType, opt => opt.MapFrom(s => s.Inventory.InventoryType.ContainerType)) + .ForMember(d => d.WeightPerCase, + opt => opt.MapFrom(s => s.Inventory.InventoryType.WeightPerCase)) .ForMember(d => d.TransactionType, opt => opt.MapFrom(s => s.TransactionType.ToString())) .ForMember(d => d.PreviousQuantity, diff --git a/InventoryTraker.Web/Views/Report/Distribution.cshtml b/InventoryTraker.Web/Views/Report/Distribution.cshtml new file mode 100644 index 0000000..54887e4 --- /dev/null +++ b/InventoryTraker.Web/Views/Report/Distribution.cshtml @@ -0,0 +1,24 @@ +@using Microsoft.Web.Mvc.Html +@{ + ViewBag.Title = "Inventory Distribution Report"; +} + +
+

+ @ViewBag.Title +

+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
diff --git a/InventoryTraker.Web/Views/Report/MonthlyInventory.cshtml b/InventoryTraker.Web/Views/Report/MonthlyInventory.cshtml new file mode 100644 index 0000000..3d09ae2 --- /dev/null +++ b/InventoryTraker.Web/Views/Report/MonthlyInventory.cshtml @@ -0,0 +1,24 @@ +@using Microsoft.Web.Mvc.Html +@{ + ViewBag.Title = "Monthly Inventory Report"; +} + +
+

+ @ViewBag.Title +

+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
diff --git a/InventoryTraker.Web/Views/Shared/_Navigation.cshtml b/InventoryTraker.Web/Views/Shared/_Navigation.cshtml index c3e2ece..191e644 100644 --- a/InventoryTraker.Web/Views/Shared/_Navigation.cshtml +++ b/InventoryTraker.Web/Views/Shared/_Navigation.cshtml @@ -29,9 +29,20 @@
  • Inventory
  • -
  • - Transaction History -
  • +
  • + Transaction History +
  • +
  • + Reports + +
  • diff --git a/InventoryTraker.Web/js/inventory/InventoryAddDirective.js b/InventoryTraker.Web/js/inventory/InventoryAddDirective.js index fd80dc4..3dbc7db 100644 --- a/InventoryTraker.Web/js/inventory/InventoryAddDirective.js +++ b/InventoryTraker.Web/js/inventory/InventoryAddDirective.js @@ -17,9 +17,11 @@ var vm = this; vm.add = add; - vm.saving = false; vm.inventory = { }; vm.inventoryTypes = inventoryTypeSvc.inventoryTypes; + + vm.saving = false; + vm.statusMessage = "Enter details for the inventory arrival below."; vm.errorMessages = []; vm.quantity = quantity; @@ -43,6 +45,7 @@ }); function add() { + vm.statusMessage = null; vm.saving = true; inventorySvc.add(vm.inventory) .success(function () { diff --git a/InventoryTraker.Web/js/inventory/InventoryDistributeDirective.js b/InventoryTraker.Web/js/inventory/InventoryDistributeDirective.js index 4eff0d1..415d79e 100644 --- a/InventoryTraker.Web/js/inventory/InventoryDistributeDirective.js +++ b/InventoryTraker.Web/js/inventory/InventoryDistributeDirective.js @@ -16,9 +16,11 @@ var vm = this; vm.save = save; - vm.saving = false; vm.quantities = angular.copy(inventorySvc.inventories); vm.distribution = {}; + + vm.saving = false; + vm.statusMessage = "Enter details for the inventory distribution below."; vm.errorMessages = []; function getInventoryDistributeQuantities(inventory) { @@ -31,6 +33,7 @@ } function save() { + vm.statusMessage = null; vm.saving = true; vm.distribution.inventoryQuantities = getInventoryDistributeQuantities(vm.quantities); inventorySvc.distribute(vm.distribution) diff --git a/InventoryTraker.Web/js/inventory/inventoryRemoveDirective.js b/InventoryTraker.Web/js/inventory/inventoryRemoveDirective.js index d4779bc..9ea94e6 100644 --- a/InventoryTraker.Web/js/inventory/inventoryRemoveDirective.js +++ b/InventoryTraker.Web/js/inventory/inventoryRemoveDirective.js @@ -25,9 +25,11 @@ transactionType: vm.inventory.isExpired ? "Expired" : null }; + vm.statusMessage = "Enter details for the inventory removal below."; vm.errorMessages = []; function save() { + vm.statusMessage = null; vm.saving = true; inventorySvc.remove(vm.removeForm) .success(function (data) { diff --git a/InventoryTraker.Web/js/inventory/templates/inventoryAdd.tmpl.cshtml b/InventoryTraker.Web/js/inventory/templates/inventoryAdd.tmpl.cshtml index df38bb0..582fc39 100644 --- a/InventoryTraker.Web/js/inventory/templates/inventoryAdd.tmpl.cshtml +++ b/InventoryTraker.Web/js/inventory/templates/inventoryAdd.tmpl.cshtml @@ -14,15 +14,8 @@