Inventory details

This commit is contained in:
2016-09-02 12:33:38 -04:00
parent f5e438e994
commit 9cdf90b1e9
18 changed files with 206 additions and 171 deletions
+4 -2
View File
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using Humanizer;
using InventoryTraker.Web.Core; using InventoryTraker.Web.Core;
using InventoryTraker.Web.Data; using InventoryTraker.Web.Data;
using InventoryTraker.Web.Identity; using InventoryTraker.Web.Identity;
@@ -77,7 +76,7 @@ namespace InventoryTraker.Web
var inventoryTypes = context.InventoryTypes.ToList(); var inventoryTypes = context.InventoryTypes.ToList();
var cityNames = new List<string> {"Maryville", "Wartburg", "Clinton", "Oak Ridge", "Alcoa", "Jellico"}; var cityNames = new List<string> {"Maryville", "Wartburg", "Clinton", "Oak Ridge", "Alcoa", "Jellico"};
for (int i = 0; i < 100; i++) for (int i = 0; i < 200; i++)
{ {
var inventoryType = inventoryTypes.ElementAt(r.Next(0, context.InventoryTypes.Count())); var inventoryType = inventoryTypes.ElementAt(r.Next(0, context.InventoryTypes.Count()));
var addedDate = DateTime.Today.AddMonths(-r.Next(1, 24)); var addedDate = DateTime.Today.AddMonths(-r.Next(1, 24));
@@ -114,6 +113,9 @@ namespace InventoryTraker.Web
Transaction transaction; Transaction transaction;
if (transactionDate >= expiration) if (transactionDate >= expiration)
{ {
if (r.Next(1, 3) == 1)
break;
transaction = new Transaction transaction = new Transaction
{ {
TransactionType = TransactionType.Expired, TransactionType = TransactionType.Expired,
@@ -35,6 +35,13 @@ namespace InventoryTraker.Web.Controllers
return BetterJson(viewModels); return BetterJson(viewModels);
} }
public JsonResult Find(int id)
{
var inventory = _context.Inventories.Find(id);
var viewModel = Mapper.Map<InventoryViewModel>(inventory);
return BetterJson(viewModel);
}
private IQueryable<Inventory> AllInventory() private IQueryable<Inventory> AllInventory()
{ {
return _context return _context
@@ -35,18 +35,26 @@ namespace InventoryTraker.Web.Controllers
return BetterJson(viewModels); return BetterJson(viewModels);
} }
public JsonResult GetTransactions(int pageNumber, int pageSize) public JsonResult GetTransactions(int? pageNumber, int? pageSize, int? inventoryId)
{ {
var viewModels = IQueryable<Transaction> query =
_context.Transactions _context.Transactions
.OrderByDescending(t => t.Timestamp) .OrderByDescending(t => t.Timestamp);
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize) if (inventoryId.HasValue)
query =
query.Where(t => t.Inventory.Id == inventoryId.Value);
if (pageNumber.HasValue && pageSize.HasValue)
query = query
.Skip((pageNumber.Value - 1) * pageSize.Value)
.Take(pageSize.Value);
var totalItems = _context.Transactions.Count();
var transactions = query
.ProjectTo<TransactionViewModel>() .ProjectTo<TransactionViewModel>()
.ToArray(); .ToArray();
return BetterJson(new { totalItems, transactions });
var count = _context.Transactions.Count();
return BetterJson(new {totalItems = count, transactions = viewModels});
} }
} }
} }
@@ -229,7 +229,7 @@
<Content Include="js\inventoryType\InventoryTypeEditDirective.js" /> <Content Include="js\inventoryType\InventoryTypeEditDirective.js" />
<Content Include="js\inventoryType\InventoryTypeController.js" /> <Content Include="js\inventoryType\InventoryTypeController.js" />
<Content Include="js\inventory\InventoryAddDirective.js" /> <Content Include="js\inventory\InventoryAddDirective.js" />
<Content Include="js\inventory\InventoryDetailsDirective.js" /> <Content Include="js\inventory\InventoryListDirective.js" />
<Content Include="js\inventory\InventoryListController.js" /> <Content Include="js\inventory\InventoryListController.js" />
<Content Include="js\inventoryType\inventoryTypeSvc.js" /> <Content Include="js\inventoryType\inventoryTypeSvc.js" />
<Content Include="js\inventory\inventorySvc.js" /> <Content Include="js\inventory\inventorySvc.js" />
@@ -345,7 +345,7 @@
<Content Include="js\web.config" /> <Content Include="js\web.config" />
<Content Include="packages.config" /> <Content Include="packages.config" />
<Content Include="js\inventory\templates\inventoryAdd.tmpl.cshtml" /> <Content Include="js\inventory\templates\inventoryAdd.tmpl.cshtml" />
<Content Include="js\inventory\templates\inventoryDetails.tmpl.cshtml" /> <Content Include="js\inventory\templates\inventoryList.tmpl.cshtml" />
<Content Include="js\inventory\templates\inventoryEdit.tmpl.cshtml" /> <Content Include="js\inventory\templates\inventoryEdit.tmpl.cshtml" />
<Content Include="Scripts\angular.min.js.map" /> <Content Include="Scripts\angular.min.js.map" />
<Content Include="Scripts\angular-animate.min.js.map" /> <Content Include="Scripts\angular-animate.min.js.map" />
@@ -27,6 +27,8 @@ namespace InventoryTraker.Web.Models
public string Memo { get; set; } public string Memo { get; set; }
public bool IsExpired => ExpirationDate < DateTime.Today;
public void CreateMappings(IMapperConfiguration configuration) public void CreateMappings(IMapperConfiguration configuration)
{ {
configuration.CreateMap<Inventory, InventoryViewModel>() configuration.CreateMap<Inventory, InventoryViewModel>()
@@ -10,6 +10,7 @@ namespace InventoryTraker.Web.Models
{ {
[Required] [Required]
public int Id { get; set; } public int Id { get; set; }
public int InventoryId { get; set; }
public string Name { get; set; } public string Name { get; set; }
public int UnitsPerCase { get; set; } public int UnitsPerCase { get; set; }
@@ -36,6 +37,8 @@ namespace InventoryTraker.Web.Models
public void CreateMappings(IMapperConfiguration configuration) public void CreateMappings(IMapperConfiguration configuration)
{ {
configuration.CreateMap<Transaction, TransactionViewModel>() configuration.CreateMap<Transaction, TransactionViewModel>()
.ForMember(d => d.InventoryId,
opt => opt.MapFrom(s => s.Inventory.Id))
.ForMember(d => d.Name, .ForMember(d => d.Name,
opt => opt.MapFrom(s => s.Inventory.InventoryType.Name)) opt => opt.MapFrom(s => s.Inventory.InventoryType.Name))
.ForMember(d => d.ExpirationDate, .ForMember(d => d.ExpirationDate,
@@ -1,7 +1,12 @@
<div ng-controller="InventoryListController as vm"> @{
ViewBag.Title = "Inventory";
}
<div ng-controller="InventoryListController as vm">
<h1 class="page-header"> <h1 class="page-header">
<i class="fa fa-cubes"></i> Inventory <i class="fa fa-cubes"></i> Inventory
</h1> </h1>
<h4>Current inventory</h4>
<div class="pull-left"> <div class="pull-left">
<a class="btn btn-default" href="" ng-click="vm.add()"><i class="fa fa-plus-circle"></i> Arrival</a> <a class="btn btn-default" href="" ng-click="vm.add()"><i class="fa fa-plus-circle"></i> Arrival</a>
<a class="btn btn-default" href="" ng-click="vm.distribute()"><i class="fa fa-share-square"></i> Distribute</a> <a class="btn btn-default" href="" ng-click="vm.distribute()"><i class="fa fa-share-square"></i> Distribute</a>
@@ -10,5 +15,5 @@
<a class="btn btn-default" href="/InventoryType"><i class="fa fa-cube"></i> Commodity Types</a> <a class="btn btn-default" href="/InventoryType"><i class="fa fa-cube"></i> Commodity Types</a>
</div> </div>
<inventory-details inventories="vm.inventories"></inventory-details> <inventory-list inventories="vm.inventories"></inventory-list>
</div> </div>
+4 -32
View File
@@ -47,38 +47,6 @@ textarea {
min-height: 90px; min-height: 90px;
} }
/* Customer List */
.customer-list .panel-heading {
font-size: 1.4em;
}
.customer-list .panel-heading .btn {
margin-top: -5px;
}
.customer-list th {
width: 100px;
}
.customer-list table {
font-size: 1em;
}
.customer-list .panel > .table + .panel-body {
border-top: none;
}
.opportunity-list h3, .risk-list h3 {
margin-top: 0;
}
.opportunity-list .add-btn,
.risk-list .add-btn {
display: inline-block;
font-size: 0.9em;
margin-top: 1.5em;
}
.ng-hide-remove { .ng-hide-remove {
-webkit-transition:0.3s linear opacity; -webkit-transition:0.3s linear opacity;
transition:0.3s linear opacity; transition:0.3s linear opacity;
@@ -101,6 +69,10 @@ textarea {
height: 70vh; height: 70vh;
} }
th.control-column {
width: 1%;
}
/*.has-feedback ng-transclude ~ input-validation-icons .form-control-feedback { /*.has-feedback ng-transclude ~ input-validation-icons .form-control-feedback {
top: 26px; top: 26px;
}*/ }*/
@@ -14,13 +14,24 @@
} }
} }
controller.$inject = ['$scope', 'inventorySvc']; controller.$inject = ['$scope', 'inventorySvc', 'transactionSvc'];
function controller($scope, inventorySvc) { function controller($scope, inventorySvc, transactionSvc) {
var vm = this; var vm = this;
vm.save = save;
vm.saving = false;
vm.inventory = angular.copy($scope.inventory); vm.inventory = angular.copy($scope.inventory);
vm.transactions = [];
function loadTransactions() {
transactionSvc
.filterByInventoryId(vm.inventory.id)
.success(function(data) {
angular.merge(vm.transactions, data.transactions);
});
}
loadTransactions();
vm.save = save;
vm.saving = false;
vm.errorMessage = null; vm.errorMessage = null;
function save() { function save() {
@@ -1,11 +1,11 @@
(function() { (function() {
'use strict'; 'use strict';
window.app.directive('inventoryDetails', inventoryDetails); window.app.directive('inventoryList', inventoryList);
function inventoryDetails() { function inventoryList() {
return { return {
scope: {"inventories" : "="}, scope: {"inventories" : "="},
templateUrl: '/inventory/template/inventoryDetails.tmpl.cshtml', templateUrl: '/inventory/template/inventoryList.tmpl.cshtml',
controller: controller, controller: controller,
controllerAs: 'vm' controllerAs: 'vm'
} }
@@ -18,10 +18,10 @@
vm.inventories = $scope.inventories; vm.inventories = $scope.inventories;
vm.edit = edit; vm.edit = edit;
function edit() { function edit(inventory) {
$uibModal.open({ $uibModal.open({
template: '<editInventory inventory="inventory" />', template: '<edit-inventory inventory="inventory" />',
scope: angular.extend($scope.$new(true), { inventory: vm.inventory }) scope: angular.extend($scope.$new(true), { inventory: inventory })
}); });
} }
} }
@@ -46,11 +46,7 @@
} }
function getInventory(id) { function getInventory(id) {
for (var i = 0; i < inventories.length; i++) { return $http.post('/Inventory/Find', { id: id });
if (inventories[i].Id == id) return inventories[i];
}
return null;
} }
} }
})(); })();
@@ -1,30 +0,0 @@
@using InventoryTraker.Web.Helpers
@model InventoryTraker.Web.Models.InventoryViewModel
@{
var inventory = Html.Angular().ModelFor("inventory");
}
<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">
<td><a href="" ng-click="vm.edit()"><i class="fa fa-edit"></i></a> @inventory.BindingFor(x => x.Name) </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>
@@ -23,10 +23,15 @@
@distribution.FormGroupFor(m => m.Destination) @distribution.FormGroupFor(m => m.Destination)
<table class="table" ng-class="vm.getValidationClass()"> @distribution.FormGroupFor(m => m.DistributedDate)
@distribution.FormGroupFor(m => m.Memo)
<table class="table table-condensed" ng-class="vm.getValidationClass()">
<thead> <thead>
<tr> <tr>
<th>Name<br/>Units per Case<br/>Expiration Date</th> <th>Name<br/>Units per Case</th>
<th>Expiration Date</th>
<th>Available Case Qty</th> <th>Available Case Qty</th>
<th>Distribute Case Qty</th> <th>Distribute Case Qty</th>
</tr> </tr>
@@ -36,11 +41,11 @@
<td> <td>
{{inventory.name}}<br/> {{inventory.name}}<br/>
{{inventory.unitsPerCase}} / {{inventory.containerType}}<br/> {{inventory.unitsPerCase}} / {{inventory.containerType}}<br/>
Exp: {{inventory.expirationDate | date:'shortDate'}}
</td> </td>
<td>{{inventory.expirationDate | date:'shortDate'}}</td>
<td>{{inventory.quantity}}</td> <td>{{inventory.quantity}}</td>
<td> <td>
<div class="form-group col-sm-7" form-group-validation="DistributeQuantity{{inventory.name}}"> <div class="form-group col-sm-9" form-group-validation="DistributeQuantity{{inventory.name}}">
<input name="DistributeQuantity{{inventory.name}}" type="number" <input name="DistributeQuantity{{inventory.name}}" type="number"
class="form-control" class="form-control"
ng-model="inventory.distributeQuantity" ng-model="inventory.distributeQuantity"
@@ -53,10 +58,6 @@
</table> </table>
@distribution.FormGroupFor(m => m.DistributedDate)
@distribution.FormGroupFor(m => m.Memo)
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@@ -6,25 +6,56 @@
<fieldset ng-disabled="vm.saving"> <fieldset ng-disabled="vm.saving">
<div class="modal-header"> <div class="modal-header">
<h3 class="modal-title"><i class="fa fa-cubes"></i> Edit Inventory</h3> <h3 class="modal-title"><i class="fa fa-cubes"></i> Inventory Details</h3>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="alert alert-info" ng-hide="vm.errorMessage != null">
Make changes to the inventory below.
</div>
<div class="alert alert-danger" ng-show="vm.errorMessage != null"> <div class="alert alert-danger" ng-show="vm.errorMessage != null">
{{vm.errorMessage}} {{vm.errorMessage}}
</div> </div>
@Html.Angular().FormForModel("vm.inventory") <dl class="dl-horizontal">
<dt>Name</dt>
<dd>{{vm.inventory.name}}</dd>
<dt>Added</dt>
<dd>{{vm.inventory.addedDate | date:'shortDate'}}</dd>
<dt>Expiration</dt>
<dd>{{vm.inventory.expirationDate | date:'shortDate'}}</dd>
</dl>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Memo</th>
<th>Transaction Date</th>
<th>Add Qty</th>
<th>Remove Qty</th>
<th>Qty</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="transaction in vm.transactions | orderBy:'-transactionDate'">
<td>{{transaction.transactionType}}</td>
<td>{{transaction.memo}}</td>
<td>{{transaction.transactionDate | date:'shortDate'}}</td>
<td>{{transaction.addedQuantity}}</td>
<td>{{transaction.removedQuantity}}</td>
<td>{{transaction.currentQuantity}}</td>
<td><a href="" ng-show="$first"><i class="fa fa-trash"></i></a></td>
</tr>
</tbody>
</table>
<div >
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-success">Save</button> <button class="btn btn-success">Save</button>
<button type="button" class="btn btn-warning" ng-click="$parent.$dismiss()">Cancel</button> <button type="button" class="btn" ng-click="$parent.$dismiss()">Cancel</button>
</div> </div>
</fieldset> </fieldset>
@@ -0,0 +1,34 @@
@using InventoryTraker.Web.Helpers
@model InventoryTraker.Web.Models.InventoryViewModel
@{
var inventory = Html.Angular().ModelFor("inventory");
}
<table class="table table-striped">
<thead>
<tr>
<th class="control-column"></th>
<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">
<td><a href="" ng-click="vm.edit(inventory)"><i class="fa fa-edit"></i></a></td>
<td>@inventory.BindingFor(x => x.Name) </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 ng-class="{ danger: inventory.isExpired }">
@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>
@@ -1,6 +1,7 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th class="control-column"></th>
<th>ID</th> <th>ID</th>
<th>Name</th> <th>Name</th>
<th>Units per Case</th> <th>Units per Case</th>
@@ -11,10 +12,8 @@
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="inventoryType in vm.inventoryTypes | orderBy:'name'"> <tr ng-repeat="inventoryType in vm.inventoryTypes | orderBy:'name'">
<td> <td><a href="" ng-click="vm.edit(inventoryType)"><i class="fa fa-edit"></i></a></td>
<a href="" ng-click="vm.edit(inventoryType)"><i class="fa fa-edit"></i></a> <td>{{inventoryType.identifier}}</td>
{{inventoryType.identifier}}
</td>
<td>{{inventoryType.name}}</td> <td>{{inventoryType.name}}</td>
<td>{{inventoryType.unitsPerCase}}</td> <td>{{inventoryType.unitsPerCase}}</td>
<td>{{inventoryType.containerType}}</td> <td>{{inventoryType.containerType}}</td>
@@ -3,20 +3,21 @@
window.app.controller('TransactionController', TransactionController); window.app.controller('TransactionController', TransactionController);
TransactionController.$inject = ['$scope', '$uibModal', 'transactionSvc', 'uiGridConstants']; TransactionController.$inject = ['$scope', '$uibModal', 'transactionSvc', 'inventorySvc', 'uiGridConstants'];
function TransactionController($scope, $uibModal, transactionSvc, uiGridConstants) { function TransactionController($scope, $uibModal, transactionSvc, inventorySvc, uiGridConstants) {
var vm = this; var vm = this;
var paginationOptions = { var paginationOptions = {
pageNumber: 1, pageNumber: 1,
pageSize: 20, pageSize: 20,
pageSizes: [20,50,100],
sort: null sort: null
}; };
vm.gridOptions = { vm.gridOptions = {
enablePaginationControls: true, enablePaginationControls: true,
paginationPageSize: paginationOptions.pageSize, paginationPageSize: paginationOptions.pageSize,
paginationPageSizes: [20,50,100], paginationPageSizes: paginationOptions.pageSizes,
useExternalPagination: true, useExternalPagination: true,
enableSorting: false, enableSorting: false,
columnDefs: [ columnDefs: [
@@ -30,7 +31,7 @@
'\r{{row.entity.unitsPerCase}} / {{row.entity.containerType}}' + '\r{{row.entity.unitsPerCase}} / {{row.entity.containerType}}' +
'\rExp Date: {{row.entity.expirationDate | date:\'shortDate\'}}' + '\rExp Date: {{row.entity.expirationDate | date:\'shortDate\'}}' +
'\rAdd Date: {{row.entity.addedDate | date:\'shortDate\'}}">' + '\rAdd Date: {{row.entity.addedDate | date:\'shortDate\'}}">' +
'<a href="" ng-click="vm.edit()"><i class="fa fa-edit"></i></a> ' + '<a href="" ng-click="grid.appScope.editInventory(row.entity.inventoryId)"><i class="fa fa-edit"></i></a> ' +
'{{row.entity.name}}</div>' '{{row.entity.name}}</div>'
}, },
{ field: 'transactionType', name: 'Type', width: "10%" }, { field: 'transactionType', name: 'Type', width: "10%" },
@@ -43,33 +44,34 @@
], ],
onRegisterApi: function(gridApi) { onRegisterApi: function(gridApi) {
vm.gridApi = gridApi; vm.gridApi = gridApi;
//vm.gridApi.core.on.sortChanged($scope, vm.gridApi.pagination
// function(grid, sortColumns) { .on.paginationChanged($scope, function(pageNumber, pageSize) {
// if (sortColumns.length == 0) { paginationOptions.pageNumber = pageNumber;
// paginationOptions.sort = null;
// } else {
// paginationOptions.sort = sortColumns[0].sort.direction;
// }
// getPage();
// });
vm.gridApi.pagination.on.paginationChanged($scope,
function(newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize; paginationOptions.pageSize = pageSize;
updateData(); updateData();
}); });
} }
}; };
var updateData = function () { function updateData() {
transactionSvc transactionSvc
.getTransactions(paginationOptions.pageNumber, paginationOptions.pageSize) .filterByPage(paginationOptions.pageNumber, paginationOptions.pageSize)
.success(function (data) { .success(function (data) {
vm.gridOptions.totalItems = data.totalItems;
vm.gridOptions.data = data.transactions; vm.gridOptions.data = data.transactions;
vm.gridOptions.totalItems = data.totalItems;
}); });
}; }
updateData(); updateData();
$scope.editInventory = function (inventoryId) {
inventorySvc.getInventory(inventoryId)
.success(function(inventory) {
$uibModal.open({
template: '<edit-inventory inventory="inventory" />',
scope: angular.extend($scope.$new(true), { inventory: inventory })
});
});
}
} }
})(); })();
@@ -5,33 +5,25 @@
function transactionSvc($http) { function transactionSvc($http) {
var svc = { var svc = {
update: update, filterByPage: filterByPage,
getTransactions: getTransactions, filterByInventoryId: filterByInventoryId
getTransaction: getTransaction
}; };
return svc; return svc;
function getTransactions(pageNumber, pageSize) { function filterByPage(pageNumber, pageSize) {
return getTransactions({ pageNumber: pageNumber, pageSize: pageSize });
}
function filterByInventoryId(inventoryId) {
return getTransactions({ inventoryId: inventoryId });
}
function getTransactions(params) {
var url = '/Transaction/GetTransactions'; var url = '/Transaction/GetTransactions';
return $http.post(url, { pageNumber: pageNumber, pageSize: pageSize }); return $http.post(url, params)
//.success(function(data) { .success(function (data) {
// return data.data;
//});
}
function update(existingTransaction, updatedTransaction) {
return $http.post('/Transaction/Update', updatedTransaction)
.success(function(transaction) {
angular.extend(existingTransaction, transaction);
}); });
} }
function getTransaction(id) {
for (var i = 0; i < transactions.length; i++) {
if (transactions[i].Id == id) return transactions[i];
}
return null;
}
} }
})(); })();