Initiate InventoyTypes from a xlxs

Arrival mostly working
This commit is contained in:
2016-08-22 11:03:00 -04:00
parent 7e4d8a6d2a
commit 53ed1b3af9
40 changed files with 798 additions and 208 deletions
@@ -1,5 +1,6 @@
using Heroic.AutoMapper;
using InventoryTraker.Web;
using InventoryTraker.Web.Controllers;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(AutoMapperConfig), "Configure")]
namespace InventoryTraker.Web
@@ -12,9 +13,9 @@ namespace InventoryTraker.Web
// You can customize this by passing in a lambda to filter the assemblies by name,
// like so:
//HeroicAutoMapperConfigurator.LoadMapsFromCallerAndReferencedAssemblies(x => x.Name.StartsWith("YourPrefix"));
HeroicAutoMapperConfigurator.LoadMapsFromCallerAndReferencedAssemblies();
//HeroicAutoMapperConfigurator.LoadMapsFromCallerAndReferencedAssemblies();
//If you run into issues with the maps not being located at runtime, try using this method instead:
//HeroicAutoMapperConfigurator.LoadMapsFromAssemblyContainingTypeAndReferencedAssemblies<SomeControllerOrTypeInYourWebProject>();
HeroicAutoMapperConfigurator.LoadMapsFromAssemblyContainingTypeAndReferencedAssemblies<ControllerBase>();
}
}
}
@@ -6,7 +6,7 @@ namespace InventoryTraker.Web
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new StyleBundle("~/Content/all.css")
bundles.Add(new StyleBundle("~/Content/all-styles")
.Include("~/Content/font-awesome.css")
.Include("~/Content/bootstrap.css")
.Include("~/Content/sb-admin.css")
@@ -14,7 +14,7 @@ namespace InventoryTraker.Web
.Include("~/Content/ui-grid.css")
);
bundles.Add(new ScriptBundle("~/js/all.js")
bundles.Add(new ScriptBundle("~/js/all-javascript")
.Include("~/Scripts/jquery-1.9.1.js")
.Include("~/Scripts/bootstrap.js")
.Include("~/Scripts/angular.js")
+52 -35
View File
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using Humanizer;
using InventoryTraker.Web.Core;
using InventoryTraker.Web.Data;
@@ -47,6 +49,10 @@ namespace InventoryTraker.Web
if (!context.Inventories.Any())
{
AddInventoryTypes(context);
context.SaveChanges();
AddInventory(context);
context.SaveChanges();
@@ -65,48 +71,59 @@ namespace InventoryTraker.Web
}
}
private static void AddInventoryTypes(AppDbContext context)
{
var folder = HttpContext.Current.Server.MapPath("~/App_Data");
var inventoryTypeFile = Path.Combine(folder, "InventoryTypeSeedData.xlsx");
var parser = new InventoryTypeParser(new FileInfo(inventoryTypeFile));
foreach (var inventoryType in parser.Parse())
{
context.InventoryTypes.Add(inventoryType);
}
}
private static void AddInventory(AppDbContext context)
{
var peanutButterSmooth = new InventoryType
{
ContainerType = "18 oz jars",
Name = "Peanut Butter Smth 18",
Id = "100395",
UnitsPerCase = 12,
PricePerCase = 14.55M,
WeightPerCase = 13.5
};
context.InventoryTypes.Add(peanutButterSmooth);
var beanInventoryType = new InventoryType
{
ContainerType = "#300 cans",
Name = "Beans, Veg 300",
Id = "100363",
UnitsPerCase = 24,
PricePerCase = 10.18M,
WeightPerCase = 24
};
context.InventoryTypes.Add(beanInventoryType);
var corn = new InventoryType
{
ContainerType = "#300 cans",
Name = "Corn Kernel 300",
Id = "100311",
UnitsPerCase = 24,
PricePerCase = 10.03M,
WeightPerCase = 22.9
};
context.InventoryTypes.Add(corn);
var pork = context.InventoryTypes.First(it => it.Identifier == "100139");
var beans = context.InventoryTypes.First(it => it.Identifier == "100363");
var pb = context.InventoryTypes.First(it => it.Identifier == "100395");
context.Inventories.Add(new Inventory
{
InventoryType = beanInventoryType,
InventoryType = pork,
ExpirationDate = DateTime.Now.AddYears(1).AtMidnight(),
Memo = "French cut",
AddedDate = DateTime.Now.AddDays(-1).AtMidnight(),
Memo = "Hormel",
Quantity = 10,
Transactions = new List<Transaction> { new Transaction { AddedQuantity = 10, Memo = "arrival", TransactionDate = DateTime.Now} }
Transactions = new List<Transaction> { new Transaction
{
AddedQuantity = 10, Memo = "arrival", TransactionDate = DateTime.Now.AddDays(-1).AtMidnight(), Timestamp = DateTime.Now
}}
});
context.Inventories.Add(new Inventory
{
InventoryType = beans,
ExpirationDate = DateTime.Now.AddMonths(4).AtMidnight(),
AddedDate = DateTime.Now.AddMonths(-2).AtMidnight(),
Memo = "Cut",
Quantity = 15,
Transactions = new List<Transaction> { new Transaction
{
AddedQuantity = 15, Memo = "arrival", TransactionDate = DateTime.Now.AddMonths(-2).AtMidnight(), Timestamp = DateTime.Now
}}
});
context.Inventories.Add(new Inventory
{
InventoryType = pb,
ExpirationDate = DateTime.Now.AddDays(300).AtMidnight(),
AddedDate = DateTime.Now.AddDays(-34).AtMidnight(),
Quantity = 700,
Transactions = new List<Transaction> { new Transaction
{
AddedQuantity = 700, Memo = "arrival", TransactionDate = DateTime.Now.AddDays(-34).AtMidnight(), Timestamp = DateTime.Now
}}
});
}
@@ -38,7 +38,7 @@ namespace InventoryTraker.Web.Controllers
var identity = _userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
_authManager.SignIn(new AuthenticationProperties { IsPersistent = false }, identity);
_authManager.SignIn(new AuthenticationProperties { IsPersistent = true }, identity);
return Json(true);
}
@@ -1,4 +1,5 @@
using System.Web.Mvc;
using System.Linq;
using System.Web.Mvc;
using InventoryTraker.Web.ActionResults;
namespace InventoryTraker.Web.Controllers
@@ -9,5 +10,16 @@ namespace InventoryTraker.Web.Controllers
{
return new BetterJsonResult<T>() {Data = model};
}
protected JsonResult PackageModelStateErrors()
{
var betterJsonResult = new BetterJsonResult();
foreach (var err in ModelState.Where(ms => ms.Value.Errors.Any()))
{
betterJsonResult.AddError(
err.Key + ": " + string.Join(", ", err.Value.Errors.Select(e => e.ErrorMessage)));
}
return betterJsonResult;
}
}
}
@@ -1,4 +1,6 @@
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using AutoMapper;
using AutoMapper.QueryableExtensions;
@@ -8,25 +10,6 @@ using InventoryTraker.Web.Models;
namespace InventoryTraker.Web.Controllers
{
public class InventoryTypeController : ControllerBase
{
private readonly AppDbContext _context;
public InventoryTypeController(AppDbContext context)
{
_context = context;
}
public JsonResult All()
{
var viewModels = _context.InventoryTypes
.OrderByDescending(x => x.Name)
.ProjectTo<InventoryTypeViewModel>();
return BetterJson(viewModels.ToArray());
}
}
public class InventoryController : ControllerBase
{
private readonly AppDbContext _context;
@@ -44,7 +27,7 @@ namespace InventoryTraker.Web.Controllers
public JsonResult All()
{
var viewModels = _context.Inventories
.OrderByDescending(x => x.InventoryType.Name)
.OrderBy(x => x.InventoryType.Name)
.ProjectTo<InventoryViewModel>()
.ToArray();
@@ -53,9 +36,20 @@ namespace InventoryTraker.Web.Controllers
public JsonResult Add(InventoryAddForm form)
{
if (!ModelState.IsValid)
return PackageModelStateErrors();
var inventory = Mapper.Map<Inventory>(form);
inventory.InventoryType = _context.InventoryTypes.Find(form.InventoryTypeId);
_context.Inventories.Add(inventory);
inventory.Transactions = new List<Transaction>();
inventory.Transactions.Add(new Transaction
{
AddedQuantity = inventory.Quantity,
Memo = "Arrival",
Timestamp = DateTime.Now,
TransactionDate = inventory.AddedDate
});
_context.SaveChanges();
var model = Mapper.Map<InventoryViewModel>(inventory);
@@ -0,0 +1,27 @@
using System.Linq;
using System.Web.Mvc;
using AutoMapper.QueryableExtensions;
using InventoryTraker.Web.Data;
using InventoryTraker.Web.Models;
namespace InventoryTraker.Web.Controllers
{
public class InventoryTypeController : ControllerBase
{
private readonly AppDbContext _context;
public InventoryTypeController(AppDbContext context)
{
_context = context;
}
public JsonResult All()
{
var viewModels = _context.InventoryTypes
.OrderByDescending(x => x.Name)
.ProjectTo<InventoryTypeViewModel>();
return BetterJson(viewModels.ToArray());
}
}
}
+4 -38
View File
@@ -1,61 +1,27 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace InventoryTraker.Web.Core
{
// AKA Commodity
public class InventoryType
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int UnitsPerCase { get; set; }
[Required]
public string ContainerType { get; set; }
public double WeightPerCase { get; set; }
public decimal PricePerCase { get; set; }
}
public class Inventory
{
public int Id { get; set; }
public virtual InventoryType InventoryType { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
[Required]
public DateTime ExpirationDate { get; set; }
[Required]
public DateTime AddedDate { get; set; }
[Required]
public int Quantity { get; set; }
public string Memo { get; set; }
}
public class Transaction
{
public int Id { get; set; }
public virtual Inventory Inventory { get; set; }
public int AddedQuantity { get; set; }
public int RemovedQuantity { get; set; }
public DateTime TransactionDate { get; set; }
public string Memo { get; set; }
}
}
+25
View File
@@ -0,0 +1,25 @@
using System.ComponentModel.DataAnnotations;
namespace InventoryTraker.Web.Core
{
public class InventoryType
{
public int Id { get; set; }
[Required]
public string Identifier { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int UnitsPerCase { get; set; }
[Required]
public string ContainerType { get; set; }
public double WeightPerCase { get; set; }
public decimal PricePerCase { get; set; }
}
}
+26
View File
@@ -0,0 +1,26 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace InventoryTraker.Web.Core
{
public class Transaction
{
public int Id { get; set; }
public virtual Inventory Inventory { get; set; }
[Required]
public int AddedQuantity { get; set; }
[Required]
public int RemovedQuantity { get; set; }
[Required]
public DateTime TransactionDate { get; set; }
public string Memo { get; set; }
[Required]
public DateTime Timestamp { get; set; }
}
}
@@ -35,9 +35,12 @@ namespace InventoryTraker.Web.Helpers
/// Converts a lambda expression into a camel-cased AngularJS binding expression, ie:
/// {{vm.model.parentProperty.childProperty}}
/// </summary>
public IHtmlString BindingFor<TProp>(Expression<Func<TModel, TProp>> property)
public IHtmlString BindingFor<TProp>(Expression<Func<TModel, TProp>> property, string filter = "")
{
return MvcHtmlString.Create("{{" + ExpressionForInternal(property) + "}}");
return MvcHtmlString.Create("{{"
+ ExpressionForInternal(property)
+ (!string.IsNullOrEmpty(filter) ? " | " + filter : string.Empty)
+ "}}");
}
/// <summary>
@@ -120,7 +123,7 @@ namespace InventoryTraker.Web.Helpers
{
//input.Attr("type", "date");
input.Attr("bs-datepicker");
input.Attr("data-date-format", "dd/MM/yyyy");
input.Attr("data-date-format", "d/M/yyyy");
}
if (metadata.DataTypeName == "PhoneNumber")
+34 -10
View File
@@ -47,6 +47,22 @@
<HintPath>..\packages\AutoMapper.4.2.0\lib\net45\AutoMapper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClosedXML, Version=0.76.0.0, Culture=neutral, PublicKeyToken=fd1eb21b62ae805b, processorArchitecture=MSIL">
<HintPath>..\packages\ClosedXML.0.76.0\lib\net40-client\ClosedXML.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="CsvHelper, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8c4959082be5c823, processorArchitecture=MSIL">
<HintPath>..\packages\CsvHelper.2.11.0\lib\net40-client\CsvHelper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="CsvHelper.Excel, Version=1.0.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\CsvHelper.Excel.1.0.5\lib\net40-client\CsvHelper.Excel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="DocumentFormat.OpenXml, Version=2.5.5631.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\DocumentFormat.OpenXml.2.5\lib\DocumentFormat.OpenXml.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
@@ -211,6 +227,7 @@
<Content Include="js\inventory\InventoryAddDirective.js" />
<Content Include="js\inventory\InventoryDetailsDirective.js" />
<Content Include="js\inventory\InventoryListController.js" />
<Content Include="js\inventory\inventoryTypeSvc.js" />
<Content Include="js\inventory\inventorySvc.js" />
<Content Include="js\inventory\InventoryEditDirective.js" />
<Content Include="js\customer\EditCustomerDirective.js" />
@@ -234,7 +251,6 @@
<Content Include="js\utility\FormGroupValidationDirective.js" />
<Content Include="js\utility\InputValidationIconsDirective.js" />
<Content Include="js\utility\MvcGridDirective.js" />
<Content Include="js\utility\DatePickerDirective.js" />
<Content Include="js\utility\ParseDateFilter.js" />
<Content Include="Scripts\angular-animate.js" />
<Content Include="Scripts\angular-animate.min.js" />
@@ -263,6 +279,10 @@
<Content Include="fonts\fontawesome-webfont.eot" />
<Content Include="Scripts\angular-strap.min.js.map" />
<Content Include="fonts\glyphicons-halflings-regular.woff2" />
<Content Include="App_Data\InventoryTypeSeedData.xlsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="Properties\PublishProfiles\ETHRA.pubxml" />
<None Include="Scripts\jquery-1.9.1.intellisense.js" />
<Content Include="Scripts\bootstrap.js" />
<Content Include="Scripts\bootstrap.min.js" />
@@ -289,6 +309,7 @@
<Compile Include="Controllers\CustomerController.cs" />
<Compile Include="Controllers\ControllerBase.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\InventoryTypeController.cs" />
<Compile Include="Controllers\OpportunityController.cs" />
<Compile Include="Controllers\ProfileController.cs" />
<Compile Include="Controllers\ReportController.cs" />
@@ -296,8 +317,10 @@
<Compile Include="Controllers\TemplateController.cs" />
<Compile Include="Core\Customer.cs" />
<Compile Include="Core\Inventory.cs" />
<Compile Include="Core\InventoryType.cs" />
<Compile Include="Core\Opportunity.cs" />
<Compile Include="Core\Risk.cs" />
<Compile Include="Core\Transaction.cs" />
<Compile Include="Core\User.cs" />
<Compile Include="Data\AppDbContext.cs" />
<Compile Include="Global.asax.cs">
@@ -329,6 +352,8 @@
<Compile Include="Models\ProfileForm.cs" />
<Compile Include="Models\RiskViewModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities\ExcelParserBase.cs" />
<Compile Include="Utilities\InventoryTypeParser.cs" />
<Compile Include="Utilities\DateExtensions.cs" />
<Compile Include="Utilities\JsonExtensions.cs" />
</ItemGroup>
@@ -343,17 +368,17 @@
<Content Include="Scripts\angular.min.js.map" />
<Content Include="Scripts\angular-animate.min.js.map" />
<Content Include="Scripts\jquery-1.9.1.min.map" />
<None Include="Views\Authentication\Login.cshtml" />
<None Include="Views\Customer\Index.cshtml" />
<None Include="Views\Home\Index.cshtml" />
<Content Include="Views\Authentication\Login.cshtml" />
<Content Include="Views\Customer\Index.cshtml" />
<Content Include="Views\Home\Index.cshtml" />
<Content Include="Views\Inventory\Index.cshtml" />
<None Include="Views\Opportunity\Index.cshtml" />
<None Include="Views\Profile\Index.cshtml" />
<None Include="Views\Report\Index.cshtml" />
<None Include="Views\Risk\Index.cshtml" />
<Content Include="Views\Opportunity\Index.cshtml" />
<Content Include="Views\Profile\Index.cshtml" />
<Content Include="Views\Report\Index.cshtml" />
<Content Include="Views\Risk\Index.cshtml" />
<Content Include="Views\Shared\_NavigationNoAuth.cshtml" />
<Content Include="Views\Shared\_NavigationHero.cshtml" />
<None Include="Views\Shared\_Navigation.cshtml" />
<Content Include="Views\Shared\_Navigation.cshtml" />
<Content Include="Views\_ViewStart.cshtml" />
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
@@ -363,7 +388,6 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
<Folder Include="js\app\" />
</ItemGroup>
<PropertyGroup>
@@ -9,12 +9,13 @@ namespace InventoryTraker.Web.Models
public class InventoryAddForm : IMapTo<Inventory>
{
[HiddenInput(DisplayValue = false)]
public string InventoryTypeId { get; set; }
[Required]
public int InventoryTypeId { get; set; }
[Required]
public DateTime ExpirationDate { get; set; }
[Required]
[Required, Range(1, int.MaxValue, ErrorMessage = "Quantity must be greater than 0")]
public int Quantity { get; set; }
[Required, Display(Name = "Arrival Date")]
@@ -5,7 +5,9 @@ namespace InventoryTraker.Web.Models
{
public class InventoryTypeViewModel : IMapFrom<InventoryType>
{
public string Id { get; set; }
public int Id { get; set; }
public string Identifier { get; set; }
public string Name { get; set; }
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using AutoMapper;
using Heroic.AutoMapper;
using InventoryTraker.Web.Core;
@@ -23,13 +24,19 @@ namespace InventoryTraker.Web.Models
public DateTime ExpirationDate { get; set; }
public DateTime AddedDate { get; set; }
public string Memo { get; set; }
public void CreateMappings(IMapperConfiguration configuration)
{
configuration.CreateMap<Inventory, InventoryViewModel>()
.ForMember(d => d.Name, opt => opt.MapFrom(s => s.InventoryType.Name))
.ForMember(d => d.UnitsPerCase, opt => opt.MapFrom(s => s.InventoryType.UnitsPerCase))
.ForMember(d => d.ContainerType, opt => opt.MapFrom(s => s.InventoryType.ContainerType))
.ForMember(d => d.WeightPerCase, opt => opt.MapFrom(s => s.InventoryType.WeightPerCase))
.ForMember(d => d.PricePerCase, opt => opt.MapFrom(s => s.InventoryType.PricePerCase));
.ForMember(d => d.PricePerCase, opt => opt.MapFrom(s => s.InventoryType.PricePerCase))
.ForMember(d => d.AddedDate, opt => opt.MapFrom(s => s.AddedDate));
}
}
}
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>Package</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<DesktopBuildPackageLocation>C:\Users\poprhythm\Documents\code\PublishPackages\InventoryTraker.Web.zip</DesktopBuildPackageLocation>
<PackageAsSingleFile>true</PackageAsSingleFile>
<DeployIisAppPath>Default Web Site</DeployIisAppPath>
<PublishDatabaseSettings>
<Objects xmlns="">
<ObjectGroup Name="DefaultConnection" Order="1" Enabled="True">
<Destination Path="Data Source=localhost;Initial Catalog=InventoryTraker;User ID=InventoryTrakerUser;Password=QcXxvpztGp1;Connect Timeout=60" Name="Data Source=localhost;Initial Catalog=InventoryTraker;User Id=InventoryTrakerUser;Password=QcXxvpztGp1;Connect Timeout=60" />
<Object Type="DbCodeFirst">
<Source Path="DBMigration" DbContext="InventoryTraker.Web.Data.AppDbContext, InventoryTraker.Web" MigrationConfiguration="InventoryTraker.Web.Migrations.Configuration, InventoryTraker.Web" Origin="Convention" />
</Object>
</ObjectGroup>
</Objects>
</PublishDatabaseSettings>
</PropertyGroup>
<ItemGroup>
<MSDeployParameterValue Include="$(DeployParameterPrefix)DefaultConnection-Web.config Connection String">
<ParameterValue>Data Source=localhost;Initial Catalog=InventoryTraker;User Id=InventoryTrakerUser;Password=QcXxvpztGp1;Connect Timeout=60</ParameterValue>
</MSDeployParameterValue>
</ItemGroup>
</Project>
@@ -0,0 +1,55 @@
using System;
using System.IO;
using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.Excel;
namespace InventoryTraker.Web.Utilities
{
public class ExcelParserBase : IDisposable
{
protected readonly CsvReader CsvReader;
protected ExcelParserBase(FileSystemInfo excelFile, CsvConfiguration csvConfiguration)
{
CsvReader = OpenExcel(excelFile, csvConfiguration);
}
protected ExcelParserBase(FileSystemInfo excelFile) :
this(excelFile,
new CsvConfiguration
{
HasHeaderRecord = false,
IgnoreBlankLines = false,
IgnoreReadingExceptions = true
})
{
}
internal static CsvReader OpenExcel(FileSystemInfo excelFile, CsvConfiguration csvConfiguration = null)
{
if (!excelFile.Exists)
throw new FileNotFoundException($"Cannot find file '{excelFile.Name}'");
var excelParser =
csvConfiguration != null
? new ExcelParser(excelFile.FullName, csvConfiguration)
: new ExcelParser(excelFile.FullName);
return new CsvReader(excelParser);
}
protected string[] GetNextCsvRowValues()
{
// get values from row
if (!CsvReader.Read())
return null;
return CsvReader.CurrentRecord;
}
public void Dispose()
{
CsvReader.Dispose();
}
}
}
@@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ClosedXML.Excel;
using CsvHelper.Configuration;
using InventoryTraker.Web.Core;
namespace InventoryTraker.Web.Utilities
{
public class InventoryTypeParser
{
private readonly FileSystemInfo _excelFile;
private sealed class InventoryTypeMap : CsvClassMap<InventoryType>
{
public InventoryTypeMap()
{
Map(m => m.Identifier);
Map(m => m.Name);
Map(m => m.UnitsPerCase);
Map(m => m.ContainerType);
Map(m => m.WeightPerCase);
Map(m => m.PricePerCase);
}
}
public InventoryTypeParser(FileSystemInfo excelFile)
{
_excelFile = excelFile;
}
public IList<InventoryType> Parse()
{
var csvConfiguration =
new CsvConfiguration { IsHeaderCaseSensitive = false, IgnoreReadingExceptions = true};
csvConfiguration.RegisterClassMap<InventoryTypeMap>();
using (var reader = ExcelParserBase.OpenExcel(_excelFile, csvConfiguration))
{
return reader.GetRecords<InventoryType>().ToList();
}
}
}
}
@@ -9,7 +9,5 @@
Inventory
<a class="pull-right" href="" ng-click="vm.add()"><i class="fa fa-plus-circle"></i></a>
</h1>
<div class="inventory-list">
<inventory-details ng-repeat="inventory in vm.inventories" inventory="inventory"></inventory-details>
</div>
<inventory-details inventories="vm.inventories"></inventory-details>
</div>
@@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@ViewBag.Title - InventoryTraker</title>
@Styles.Render("~/Content/all.css")
@Styles.Render("~/Content/all-styles")
@RenderSection("Styles", required: false)
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
@@ -17,7 +17,7 @@
</head>
<body>
<div id="wrapper" ng-cloak>
@(Request.IsAuthenticated ? Html.Partial("_NavigationHero") : Html.Partial("_NavigationNoAuth"))
@(Request.IsAuthenticated ? Html.Partial("_Navigation") : Html.Partial("_NavigationNoAuth"))
<div id="page-wrapper">
<div class="container-fluid">
@RenderBody()
@@ -26,7 +26,7 @@
<!-- /#page-wrapper -->
</div>
<!-- /#wrapper -->
@Scripts.Render("~/js/all.js")
@Scripts.Render("~/js/all-javascript")
@RenderSection("Scripts", required: false)
</body>
</html>
@@ -14,18 +14,25 @@
controller.$inject = ['$scope', 'inventorySvc', 'inventoryTypeSvc'];
function controller($scope, inventorySvc, inventoryTypeSvc) {
var vm = this;
vm.add = add;
vm.add = add;
vm.saving = false;
vm.inventory = {};
vm.inventoryTypes = inventoryTypeSvc.inventoryTypes;
vm.errorMessage = null;
vm.quantity = quantity;
function zeroNaN(v) {
return isNaN(v) ? 0 : v;
}
function quantity() {
vm.inventory.quantity =
$scope.palletCount * $scope.casesPerPallet + $scope.caseCount;
return vm.inventory.quantity;
zeroNaN($scope.palletCount)
* zeroNaN($scope.casesPerPallet)
+ zeroNaN($scope.caseCount);
return vm.inventory.quantity > 0 ? vm.inventory.quantity : "";
}
function add() {
@@ -36,14 +43,15 @@
$scope.$close();
})
.error(function(data) {
vm.errorMessage = 'There was a problem adding the inventory: ' + data;
vm.errorMessage =
'There was a problem adding the inventory: ' + data.errorMessage;
})
.finally(function() {
vm.saving = false;
});
}
$scope.$watch('commodity', function (newValue, oldValue) {
$scope.$watch('vm.commodity', function (newValue, oldValue) {
if (newValue)
vm.inventory.inventoryTypeId = newValue.id;
});
@@ -4,9 +4,7 @@
window.app.directive('inventoryDetails', inventoryDetails);
function inventoryDetails() {
return {
scope: {
inventory: '='
},
scope: {"inventories" : "="},
templateUrl: '/inventory/template/inventoryDetails.tmpl.cshtml',
controller: controller,
controllerAs: 'vm'
@@ -17,9 +15,9 @@
function controller($scope, $uibModal) {
var vm = this;
vm.inventory = $scope.inventory;
vm.inventories = $scope.inventories;
vm.edit = edit;
function edit() {
$uibModal.open({
template: '<editInventory inventory="inventory" />',
@@ -11,7 +11,8 @@
function add() {
$uibModal.open({
template: '<inventory-add />'
template: '<inventory-add />',
backdrop: 'static'
});
}
}
@@ -42,56 +42,6 @@
if (inventories[i].Id == id) return inventories[i];
}
return null;
}
}
})();
(function () {
window.app.factory('inventoryTypeSvc', inventoryTypeSvc);
inventoryTypeSvc.$inject = ['$http'];
function inventoryTypeSvc($http) {
var inventoryTypes = [];
loadInventoryTypes();
var svc = {
add: add,
update: update,
inventoryTypes: inventoryTypes,
getInventoryType: getInventoryType
};
return svc;
function loadInventoryTypes() {
$http.post('/InventoryType/All')
.success(function (data) {
inventoryTypes.addRange(data);
});
}
function add(inventoryType) {
return $http.post('/InventoryType/Add', inventoryType)
.success(function (inventoryType) {
inventoryTypes.unshift(inventoryType);
});
}
function update(existingInventory, updatedInventory) {
return $http.post('/InventoryType/Update', updatedInventory)
.success(function (inventory) {
angular.extend(existingInventory, inventory);
});
}
function getInventoryType(id) {
for (var i = 0; i < inventoryTypes.length; i++) {
if (inventoryTypes[i].Id == id) return inventoryTypes[i];
}
return null;
}
}
@@ -0,0 +1,48 @@
(function () {
window.app.factory('inventoryTypeSvc', inventoryTypeSvc);
inventoryTypeSvc.$inject = ['$http'];
function inventoryTypeSvc($http) {
var inventoryTypes = [];
loadInventoryTypes();
var svc = {
add: add,
update: update,
inventoryTypes: inventoryTypes,
getInventoryType: getInventoryType
};
return svc;
function loadInventoryTypes() {
$http.post('/InventoryType/All')
.success(function (data) {
inventoryTypes.addRange(data);
});
}
function add(inventoryType) {
return $http.post('/InventoryType/Add', inventoryType)
.success(function (inventoryType) {
inventoryTypes.unshift(inventoryType);
});
}
function update(existingInventory, updatedInventory) {
return $http.post('/InventoryType/Update', updatedInventory)
.success(function (inventory) {
angular.extend(existingInventory, inventory);
});
}
function getInventoryType(id) {
for (var i = 0; i < inventoryTypes.length; i++) {
if (inventoryTypes[i].Id == id) return inventoryTypes[i];
}
return null;
}
}
})();
@@ -30,22 +30,22 @@
<div class="form-group has-feedback" ng-class="vm.getValidationClass()" form-group-validation="Commodity">
<label for="Commodity" class="control-label">Commodity</label>
<input name="Commodity" type="text"
ng-model="commodity"
ng-model="vm.commodity"
required
uib-typeahead="inventoryType as inventoryType.name for inventoryType in vm.inventoryTypes | filter:{name:$viewValue} | limitTo:8"
uib-typeahead=
"inventoryType as inventoryType.name for inventoryType in vm.inventoryTypes
| filter:{name:$viewValue}
| limitTo:8"
typeahead-editable='false'
class="form-control">
<i class="fa fa-search form-control-feedback"></i>
<div class="panel panel-default" ng-show="commodity.id">
<div class="panel-heading">Selected Commodity</div>
<div class="panel panel-default" ng-show="vm.commodity.id">
<div class="panel-body">
<dl class="dl-horizontal">
<dt>Commodity ID</dt>
<dd>{{commodity.id}}</dd>
<dt>Name</dt>
<dd>{{commodity.name}}</dd>
<dd>{{vm.commodity.identifier}}</dd>
<dt>Units per Case</dt>
<dd>{{commodity.unitsPerCase}} / {{commodity.containerType}}</dd>
<dd>{{vm.commodity.unitsPerCase}} / {{vm.commodity.containerType}}</dd>
</dl>
</div>
</div>
@@ -57,28 +57,28 @@
<div class="panel-heading"><label>Quantity</label></div>
<div class="panel-body container-fluid">
<div class="row">
<div class="col-sm-5">Pallets</div>
<div class="col-sm-5"><label for="PalletCount">Pallets</label></div>
<div class="col-sm-3">
<input type="number" class="form-control" ng-model="palletCount" />
<input ng-model="palletCount" name="PalletCount" type="number" class="form-control" />
</div>
</div>
<div class="row">
<div class="col-sm-4 col-sm-offset-1">Cases per Pallet</div>
<div class="col-sm-4 col-sm-offset-1"><label for="CasesPerPallet">Cases per Pallet</label></div>
<div class="col-sm-3">
<input type="number" class="form-control" ng-model="casesPerPallet" />
<input ng-model="casesPerPallet" name="CasesPerPallet" type="number" class="form-control" />
</div>
</div>
<hr />
<div class="row">
<div class="col-sm-5">Individual Cases</div>
<div class="col-sm-5"><label for="CaseCount">Individual Cases</label></div>
<div class="col-sm-3">
<input type="number" class="form-control" ng-model="caseCount" />
<input ng-model="caseCount" name="CaseCount" type="number" class="form-control" />
</div>
</div>
<hr />
<div class="row">
<div class="col-sm-5">Total Units</div>
<div class="col-sm-3">{{vm.quantity()}}</div>
<div class="col-sm-5"><strong>Total Units</strong></div>
<div class="col-sm-3"><strong>{{vm.quantity()}}</strong></div>
</div>
</div>
</div>
@@ -1,12 +1,30 @@
@using InventoryTraker.Web.Helpers
@model InventoryTraker.Web.Models.InventoryViewModel
@{
var inventory = Html.Angular().ModelFor("vm.inventory");
var inventory = Html.Angular().ModelFor("inventory");
}
<div class="panel panel-default">
<div class="panel-heading">
@inventory.BindingFor(x => x.Name) <a href="" ng-click="vm.edit()"><i class="fa fa-edit"></i></a>
</div>
Quantity
@inventory.BindingFor(x => x.Quantity)
</div>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Units per Case</th>
<th>Case Qty</th>
<th>Unit Qty</th>
<th>Exp Date</th>
<th>Added Date</th>
<th>Memo</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="inventory in vm.inventories" inventory="inventory">
<td><strong>@inventory.BindingFor(x => x.Name)</strong> <a href="" ng-click="vm.edit()"><i class="fa fa-edit"></i></a></td>
<td>@inventory.BindingFor(x => x.UnitsPerCase) / @inventory.BindingFor(x => x.ContainerType)</td>
<td>@inventory.BindingFor(x => x.Quantity)</td>
<td>{{inventory.quantity * inventory.unitsPerCase}}</td>
<td>@inventory.BindingFor(x => x.ExpirationDate, "date:'shortDate'")</td>
<td>@inventory.BindingFor(x => x.AddedDate, "date:'shortDate'")</td>
<td>@inventory.BindingFor(x => x.Memo)</td>
</tr>
</tbody>
</table>
+4
View File
@@ -8,6 +8,10 @@
<package id="Antlr" version="3.5.0.2" targetFramework="net451" />
<package id="AutoMapper" version="4.2.0" targetFramework="net451" />
<package id="bootstrap" version="3.3.7" targetFramework="net451" />
<package id="ClosedXML" version="0.76.0" targetFramework="net451" />
<package id="CsvHelper" version="2.11.0" targetFramework="net451" />
<package id="CsvHelper.Excel" version="1.0.5" targetFramework="net451" />
<package id="DocumentFormat.OpenXml" version="2.5" targetFramework="net451" />
<package id="EntityFramework" version="6.1.3" targetFramework="net451" />
<package id="FontAwesome" version="4.6.3" targetFramework="net451" />
<package id="Heroic.AutoMapper" version="2.0.0" targetFramework="net451" />