Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/89 use inventory snapshot for dashboard widgets #142

Merged
Prev Previous commit
Next Next commit
fixed #89: made significant performances improvements to the dashboard
  • Loading branch information
jmiranda committed Apr 30, 2016
commit 892c4123536f8d4feb7b8ab546a9ec56891c0c7a
28 changes: 27 additions & 1 deletion grails-app/conf/spring/resources.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,33 @@ beans = {
dashboardCache(EhCacheFactoryBean) { bean ->
cacheManager = ref("springcacheCacheManager")
cacheName = "dashboardCache"
// these are just examples of properties you could set
eternal = false
diskPersistent = false
memoryStoreEvictionPolicy = "LRU"
timeToLive = 86400 // 1 day = 60 * 60 * 24
timeToIdle = 43200 // 12 hours = 60 * 60 * 12
}
dashboardTotalStockValueCache(EhCacheFactoryBean) { bean ->
cacheManager = ref("springcacheCacheManager")
cacheName = "dashboardTotalStockValueCache"
eternal = false
diskPersistent = false
memoryStoreEvictionPolicy = "LRU"
timeToLive = 86400 // 1 day = 60 * 60 * 24
timeToIdle = 43200 // 12 hours = 60 * 60 * 12
}
dashboardProductSummaryCache(EhCacheFactoryBean) { bean ->
cacheManager = ref("springcacheCacheManager")
cacheName = "dashboardProductSummaryCache"
eternal = false
diskPersistent = false
memoryStoreEvictionPolicy = "LRU"
timeToLive = 86400 // 1 day = 60 * 60 * 24
timeToIdle = 43200 // 12 hours = 60 * 60 * 12
}
dashboardGenericProductSummaryCache(EhCacheFactoryBean) { bean ->
cacheManager = ref("springcacheCacheManager")
cacheName = "dashboardGenericProductSummaryCache"
eternal = false
diskPersistent = false
memoryStoreEvictionPolicy = "LRU"
Expand Down
137 changes: 113 additions & 24 deletions grails-app/controllers/org/pih/warehouse/JsonController.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -249,23 +249,51 @@ class JsonController {
}


// FIXME Remove - Only used for comparison
def getQuantityByProductMap = {
def location = Location.get(session?.warehouse?.id)
def quantityMap = inventoryService.getQuantityByProductMap(location.inventory)

render quantityMap as JSON
}


// FIXME Remove - Only used for compaison
def getQuantityByProductMap2 = {
def location = Location.get(session?.warehouse?.id)
def quantityMap = inventoryService.getCurrentInventory(location)

render quantityMap as JSON
}

def getQuantityByInventoryItem = {
def location = Location.get(session?.warehouse?.id)
def quantityMap = inventoryService.getQuantityForInventory(location.inventory)

quantityMap = quantityMap.sort()


render quantityMap as JSON
}


def getQuantityByInventoryItem2 = {
def location = Location.get(session?.warehouse?.id)
def quantityMap = inventoryService.getQuantityOnHandByInventoryItem(location)

quantityMap = quantityMap.sort()


render quantityMap as JSON
}



@Cacheable("dashboardCache")
def getDashboardAlerts = {
def location = Location.get(session?.warehouse?.id)
def dashboardAlerts = inventoryService.getDashboardAlerts(location)

//def expirationSummary = inventoryService.getExpirationSummary(location)
//expirationSummary.each { key, value ->
// dashboardAlerts[key] = value;
//}

//def totalStockSummary = inventoryService.getTotalStockValue(location)
//dashboardAlerts['totalStockValue'] = g.formatNumber(number: totalStockSummary.totalStockValue, type: 'currency', currencyCode: 'USD')
//dashboardAlerts['totalStockValue'] = totalStockSummary.totalStockValue
//dashboardAlerts['hitCount'] = totalStockSummary.hitCount
//dashboardAlerts['missCount'] = totalStockSummary.missCount
//dashboardAlerts['totalCount'] = totalStockSummary.totalCount

render dashboardAlerts as JSON
}

Expand All @@ -276,16 +304,47 @@ class JsonController {
render map as JSON
}

@Cacheable("dashboardCache")
//@Cacheable("dashboardTotalStockValueCache")
def getTotalStockValue = {
def location = Location.get(session?.warehouse?.id)
def result = inventoryService.getTotalStockValue(location)
def totalValue = g.formatNumber(number: result.totalStockValue)
def lastUpdated = inventoryService.getLastUpdatedInventorySnapshotDate()
lastUpdated = "Last updated " + prettytime.display([date: lastUpdated, showTime: true, capitalize: false]) + "."
def data = [
lastUpdated: lastUpdated,
anotherAttr: "anotherValue",
totalStockValue:result.totalStockValue,
hitCount: result.hitCount,
missCount: result.missCount,
totalCount: result.totalCount,
totalValue: totalValue]
render data as JSON
}

def map = [totalStockValue:result.totalStockValue, hitCount: result.hitCount, missCount: result.missCount, totalCount: result.totalCount]
def getStockValueByProduct = {
def location = Location.get(session?.warehouse?.id)
def result = inventoryService.getTotalStockValue(location)

def stockValueByProduct = []
result.stockValueByProduct.sort { it.value }.reverseEach { product, value ->

value = g.formatNumber(number: value, format: "#######.00")
stockValueByProduct << [id: product.id, productCode: product.productCode, productName: product.name, unitPrice: product.pricePerUnit, totalValue: value ]
}

def map = [aaData: stockValueByProduct]
render map as JSON
}


@CacheFlush("dashboardTotalStockValueCache")
def refreshTotalStockValue = {
render ([success:true] as JSON)
}



@Cacheable("dashboardCache")
def getReconditionedStockCount = {
def location = Location.get(params?.location?.id)
Expand Down Expand Up @@ -355,6 +414,34 @@ class JsonController {
}


def getInventorySnapshots = {

def location = Location.get(params?.location?.id)
def results = inventoryService.findInventorySnapshotByLocation(location)

def inStockCount = results.findAll { it.quantityOnHand > 0 && it.status == InventoryStatus.SUPPORTED }.size()
def lowStockCount = results.findAll { it.quantityOnHand > 0 && it.quantityOnHand <= it.minQuantity && it.status == InventoryStatus.SUPPORTED }.size()
def reoderStockCount = results.findAll { it.quantityOnHand > it.minQuantity && it.quantityOnHand <= it.reorderQuantity && it.status == InventoryStatus.SUPPORTED }.size()
def overStockCount = results.findAll { it.quantityOnHand > it.reorderQuantity && it.quantityOnHand <= it.maxQuantity && it.status == InventoryStatus.SUPPORTED }.size()
def stockOutCount = results.findAll { it.quantityOnHand <= 0 && it.status == InventoryStatus.SUPPORTED }.size()

def totalCount = results.size()


render ([
summary: [
totalCount: totalCount,
inStockCount: inStockCount,
lowStockCount: lowStockCount,
reoderStockCount: reoderStockCount,
overStockCount: overStockCount,
stockOutCount:stockOutCount
],
details: [results:results]
] as JSON)//results.collect { [productCode: it.productCode, quantityOnHand: it.quantityOnHand, ]}

}

def getQuantityOnHandMap = {
def startTime = System.currentTimeMillis()
//def location = Location.get(session?.warehouse?.id)
Expand All @@ -366,9 +453,10 @@ class JsonController {
}


Map<Product,Integer> getQuantityOnHand(Inventory inventory) {
return inventoryService.getQuantityByProductMap(inventory)
}
// FIXME Remove if not used
// Map<Product,Integer> getQuantityOnHand(Inventory inventory) {
// return inventoryService.getQuantityByProductMap(inventory)
// }


def findProductCodes = {
Expand Down Expand Up @@ -1260,39 +1348,39 @@ class JsonController {
if (numMonths >= 24) {
use(groovy.time.TimeCategory) {
numMonths.times { i ->
dates << (today - (i+1).months)
dates << (today - i.months)
}
}
format = "yyyy"
}
else if (numMonths > 12) {
use(groovy.time.TimeCategory) {
numMonths.times { i ->
dates << (today - (i+1).months)
dates << (today - i.months)
}
}
format = "MMM-yy"
}
else if (numMonths >= 6) {
use(groovy.time.TimeCategory) {
numMonths.times { i ->
dates << (today - (i+1).months)
dates << (today - i.months)
}
}
format = "MMM-yyyy"
format = "MMM-yy"
}
else if (numMonths >= 2) {
use(groovy.time.TimeCategory) {
(numMonths*4).times { i ->
dates << (today - (i+1).weeks)
dates << (today - i.weeks)
}
}
format = "'wk' w"
}
else {
use(groovy.time.TimeCategory) {
(numMonths*21).times { i ->
dates << (today - (i+1).days)
dates << (today - i.days)
}
}
format = "dd-MMM"
Expand All @@ -1319,6 +1407,8 @@ class JsonController {

// Get all inventory snapshots for the current product and location
//def inventorySnapshots = InventorySnapshot.findAllByProductAndLocation(product, location)

log.info "Inventory snapshots between " + dates[0] + " " + dates[dates.size()-1]
def inventorySnapshots = InventorySnapshot.createCriteria().list() {
eq("product", product)
eq("location", location)
Expand Down Expand Up @@ -1371,7 +1461,6 @@ class JsonController {
* Dashboard > Fast movers
*/
def getFastMovers = {
log.info "getRequisitionItems: " + params
def dateFormat = new SimpleDateFormat("MM/dd/yyyy")
def date = new Date()
if (params.date) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ class InventoryController {
def list = {
println "List " + params
def location = Location.get(session.warehouse.id)
def quantityMap = inventoryService.getQuantityByProductMap(location.inventory)
def quantityMap = inventoryService.getCurrentInventory(location)
def statusMap = inventoryService.getInventoryStatus(location)
println "QuantityMap: " + quantityMap
[quantityMap:quantityMap,statusMap: statusMap]
Expand Down Expand Up @@ -631,6 +631,21 @@ class InventoryController {
render (view: "list", model: [quantityMap:quantityMap, statusMap: statusMap])
}

def listHealthyStock = {
def location = Location.get(session.warehouse.id)
def quantityMap = inventoryService.getHealthyStock(location)
def statusMap = inventoryService.getInventoryStatus(location)
if (params.format == "csv") {
def filename = "Overstock - " + location.name + ".csv"
response.setHeader("Content-disposition", "attachment; filename='" + filename + "'")
render(contentType: "text/csv", text:getCsvForProductMap(quantityMap, statusMap))
return;
}

//[inventoryItems:lowStock, quantityMap:quantityMap]
render (view: "list", model: [quantityMap:quantityMap, statusMap: statusMap])
}


def listOverStock = {
def location = Location.get(session.warehouse.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,8 @@ class InventorySnapshotController {
def triggerCalculateQuantityOnHandJob = {
println "triggerCalculateQuantityOnHandJob: " + params

def results = CalculateQuantityJob.triggerNow([productId:params.product.id,locationId:params.location.id])
//def location = Location.get(params.location.id)
//def product = Product.get(params.product.id)
//def results = inventoryService.getTransactionDates(location, product)
def results = CalculateQuantityJob.triggerNow([productId:params.product.id,locationId:params.location.id,alltime:true])

println results
render ([started:true, results:results] as JSON)

}
Expand Down
Loading