|
|
@@ -1,5 +1,5 @@
|
|
|
const _ = require('lodash')
|
|
|
-const { Terminal } = require('../database')
|
|
|
+const { Terminal, ServiceCategory } = require('../database')
|
|
|
const sequelize = require('../database/sequelize')
|
|
|
const { sanitize } = require('@alancnet/material-framework/lib/util')
|
|
|
|
|
|
@@ -13,8 +13,8 @@ const get = async (req, res) => {
|
|
|
loc.key,
|
|
|
wd.date,
|
|
|
wd.laborCost,
|
|
|
- SUM(distinct svc.cartons) as cartons,
|
|
|
- cast(SUM(distinct wd.laborCost) as double) / SUM(distinct svc.cartons) as efficiency
|
|
|
+ SUM(distinct svc.inbound) as inbound,
|
|
|
+ cast(SUM(distinct wd.laborCost) as double) / SUM(distinct svc.inbound) as costPerCarton
|
|
|
FROM workdays wd
|
|
|
JOIN terminals loc on wd.terminalId = loc.id
|
|
|
LEFT JOIN services svc on svc.workdayId = wd.id
|
|
|
@@ -24,15 +24,15 @@ const get = async (req, res) => {
|
|
|
replacements: { terminalIds }
|
|
|
})
|
|
|
|
|
|
- const metricsSql = `
|
|
|
+ const metricsSql = (serviceColumn) => `
|
|
|
select
|
|
|
terminals.key as terminal,
|
|
|
serviceCategories.key as serviceCategory,
|
|
|
serviceCategories.displayOrder,
|
|
|
laborCategories.key as laborCategory,
|
|
|
sum(distinct labors.laborCost) as laborCost,
|
|
|
- sum(distinct services.cartons) as cartons,
|
|
|
- cast(sum(distinct labors.laborCost) as double) / sum(distinct services.cartons) as costPerCarton
|
|
|
+ sum(distinct services.${serviceColumn}) as ${serviceColumn},
|
|
|
+ cast(sum(distinct labors.laborCost) as double) / sum(distinct services.${serviceColumn}) as costPer
|
|
|
|
|
|
-- Start with Terminals
|
|
|
from terminals
|
|
|
@@ -49,62 +49,138 @@ const get = async (req, res) => {
|
|
|
-- Link to ServiceCategory
|
|
|
join laborServiceCategories on laborServiceCategories.laborCategoryId = laborCategories.id
|
|
|
join serviceCategories on laborServiceCategories.serviceCategoryId = serviceCategories.id
|
|
|
+
|
|
|
+ where terminals.id in(:terminalIds)
|
|
|
+ and serviceCategories.key = :serviceCategory
|
|
|
group by terminals.key, serviceCategories.key, laborCategories.key
|
|
|
`
|
|
|
|
|
|
- const metricsPerServiceCategorySql = `
|
|
|
+ const metricsPerServiceCategorySql = (serviceColumn) => `
|
|
|
select
|
|
|
serviceCategory,
|
|
|
displayOrder,
|
|
|
- cast(sum(distinct laborCost) as double) / sum(distinct cartons) as costPerCarton
|
|
|
- from (${metricsSql})
|
|
|
+ cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
|
|
|
+ from (${metricsSql(serviceColumn)})
|
|
|
group by serviceCategory
|
|
|
order by displayOrder
|
|
|
`
|
|
|
|
|
|
- const metricsPerLaborCategorySql = `
|
|
|
+ const metricsPerLaborCategorySql = (serviceColumn) => `
|
|
|
select
|
|
|
serviceCategory,
|
|
|
laborCategory,
|
|
|
- cast(sum(distinct laborCost) as double) / sum(distinct cartons) as costPerCarton
|
|
|
- from (${metricsSql})
|
|
|
+ cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
|
|
|
+ from (${metricsSql(serviceColumn)})
|
|
|
group by laborCategory
|
|
|
`
|
|
|
|
|
|
- const metricsPerTerminalAndServiceCategorySql = `
|
|
|
+ const metricsPerTerminalAndServiceCategorySql = (serviceColumn) => `
|
|
|
select
|
|
|
terminal,
|
|
|
serviceCategory,
|
|
|
- cast(sum(distinct laborCost) as double) / sum(distinct cartons) as costPerCarton
|
|
|
- from (${metricsSql})
|
|
|
+ cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
|
|
|
+ from (${metricsSql(serviceColumn)})
|
|
|
group by terminal, serviceCategory
|
|
|
`
|
|
|
|
|
|
- const metricsPerTerminalAndLaborCategorySql = `
|
|
|
+ const metricsPerTerminalAndLaborCategorySql = (serviceColumn) => `
|
|
|
select
|
|
|
terminal,
|
|
|
serviceCategory,
|
|
|
laborCategory,
|
|
|
- cast(sum(distinct laborCost) as double) / sum(distinct cartons) as costPerCarton
|
|
|
- from (${metricsSql})
|
|
|
+ cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
|
|
|
+ from (${metricsSql(serviceColumn)})
|
|
|
group by terminal, laborCategory
|
|
|
`
|
|
|
- const metricsPerServiceCategory = await sanitize(req, (await sequelize.query(metricsPerServiceCategorySql))[0])
|
|
|
- const metricsPerLaborCategory = await sanitize(req, (await sequelize.query(metricsPerLaborCategorySql))[0])
|
|
|
- const metricsPerTerminalAndServiceCategory = await sanitize(req, (await sequelize.query(metricsPerTerminalAndServiceCategorySql))[0])
|
|
|
- const metricsPerTerminalAndLaborCategory = await sanitize(req, (await sequelize.query(metricsPerTerminalAndLaborCategorySql))[0])
|
|
|
+
|
|
|
+ const lastMetricsSql = (serviceColumn) => `
|
|
|
+ select
|
|
|
+ workdays.date,
|
|
|
+ terminals.key as terminal,
|
|
|
+ sum(distinct labors.laborCost) as laborCost,
|
|
|
+ sum(distinct services.${serviceColumn}) as ${serviceColumn},
|
|
|
+ cast(sum(distinct labors.laborCost) as double) / sum(distinct services.${serviceColumn}) as costPer
|
|
|
+
|
|
|
+ -- Start with Terminals
|
|
|
+ from terminals
|
|
|
+
|
|
|
+ -- Link to labor cost
|
|
|
+ join workdays on workdays.terminalId = terminals.id
|
|
|
+ join services on services.workdayId = workdays.id
|
|
|
+ join labors on labors.workdayId = workdays.id
|
|
|
+
|
|
|
+ -- Link to LaborCategory
|
|
|
+ join staffMembers on labors.staffMemberId = staffMembers.id
|
|
|
+ join laborCategories on staffMembers.laborCategoryId = laborCategories.id
|
|
|
+
|
|
|
+ -- Link to ServiceCategory
|
|
|
+ join laborServiceCategories on laborServiceCategories.laborCategoryId = laborCategories.id
|
|
|
+ join serviceCategories on laborServiceCategories.serviceCategoryId = serviceCategories.id
|
|
|
+
|
|
|
+ where workdays.date = (select max(date) from workdays where laborCost > 0)
|
|
|
+ and serviceCategories.key = :serviceCategory
|
|
|
+ and terminals.id in(:terminalIds)
|
|
|
+
|
|
|
+ `
|
|
|
+
|
|
|
+
|
|
|
+ const serviceCategories = (await ServiceCategory.findAll())
|
|
|
+ //const opts = {replacements: {serviceCategory: sc.key, terminalIds}}
|
|
|
+ const ret = {
|
|
|
+ serviceCategories: await Promise.all(
|
|
|
+ (await ServiceCategory.findAll()).map(async sc => {
|
|
|
+ const opts = {
|
|
|
+ replacements: {
|
|
|
+ terminalIds,
|
|
|
+ serviceCategory: sc.key
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const [mpsc] = await sequelize.query(metricsPerServiceCategorySql(sc.serviceColumn), opts)
|
|
|
+ const [mplc] = await sequelize.query(metricsPerLaborCategorySql(sc.serviceColumn), opts)
|
|
|
+ const [mptsc] = await sequelize.query(metricsPerTerminalAndServiceCategorySql(sc.serviceColumn), opts)
|
|
|
+ const [mptlc] = await sequelize.query(metricsPerTerminalAndLaborCategorySql(sc.serviceColumn), opts)
|
|
|
+ const [lastMetrics] = await sequelize.query(lastMetricsSql(sc.serviceColumn), opts)
|
|
|
+ return {
|
|
|
+ ...mpsc[0],
|
|
|
+ key: sc.key,
|
|
|
+ serviceColumn: sc.serviceColumn,
|
|
|
+ displayOrder: sc.displayOrder,
|
|
|
+ laborCategories: mplc,
|
|
|
+ terminals: mptsc.map(t => ({
|
|
|
+ ...t,
|
|
|
+ key: t.terminal,
|
|
|
+ laborCategories: mptlc.filter(l => l.terminal === t.terminal)
|
|
|
+ })),
|
|
|
+ lastMetrics: lastMetrics[0]
|
|
|
+ }
|
|
|
+ })
|
|
|
+ ),
|
|
|
+ metricsOverTime
|
|
|
+ }
|
|
|
+
|
|
|
+ return res.status(200).send(ret)
|
|
|
+
|
|
|
+
|
|
|
+ const queries = await Promise.all(serviceCategories.map(async sc => ({
|
|
|
+ metricsPerServiceCategory: await sanitize(req, (await sequelize.query(metricsPerServiceCategorySql(sc.serviceColumn), {replacements: {serviceCategory: sc.key, terminalIds}}))[0]),
|
|
|
+ metricsPerLaborCategory: await sanitize(req, (await sequelize.query(metricsPerLaborCategorySql(sc.serviceColumn), {replacements: {serviceCategory: sc.key, terminalIds}}))[0]),
|
|
|
+ metricsPerTerminalAndServiceCategory: await sanitize(req, (await sequelize.query(metricsPerTerminalAndServiceCategorySql(sc.serviceColumn), {replacements: {serviceCategory: sc.key, terminalIds}}))[0]),
|
|
|
+ metricsPerTerminalAndLaborCategory: await sanitize(req, (await sequelize.query(metricsPerTerminalAndLaborCategorySql(sc.serviceColumn), {replacements: {serviceCategory: sc.key, terminalIds}}))[0]),
|
|
|
+ lastMetrics: await sanitize(req, (await sequelize.query(lastMetricsSql(sc.serviceColumn), {replacements: {serviceCategory: sc.key, terminalIds}}))[0])
|
|
|
+
|
|
|
+ })))
|
|
|
|
|
|
const results = {
|
|
|
- serviceCategories: metricsPerServiceCategory.map(mpsc => Object.assign(mpsc, {
|
|
|
- laborCategories: metricsPerLaborCategory.filter(mplc => mplc.serviceCategory === mpsc.serviceCategory),
|
|
|
- terminals: metricsPerTerminalAndServiceCategory.filter(mpt => mpt.serviceCategory === mpsc.serviceCategory).map(mpt => Object.assign(mpt, {
|
|
|
- laborCategories: metricsPerTerminalAndLaborCategory.filter(mptlc => mptlc.serviceCategory === mpsc.serviceCategory && mptlc.terminal === mpt.terminal)
|
|
|
- }))
|
|
|
+ serviceCategories: serviceCategories.map((sc, i) => Object.assign(queries[i].metricsPerServiceCategory[0], {
|
|
|
+ laborCategories: queries[i].metricsPerLaborCategory.filter(mplc => mplc.serviceCategory === sc.key),
|
|
|
+ terminals: queries[i].metricsPerTerminalAndServiceCategory.filter(mpt => mpt.serviceCategory === sc.key).map(mpt => Object.assign(mpt, {
|
|
|
+ laborCategories: queries[i].metricsPerTerminalAndLaborCategory.filter(mptlc => mptlc.serviceCategory === sc.key && mptlc.terminal === mpt.terminal)
|
|
|
+ })),
|
|
|
+ lastMetrics: queries[i].lastMetrics
|
|
|
})),
|
|
|
metricsOverTime
|
|
|
}
|
|
|
res.status(200).send(results)
|
|
|
-
|
|
|
}
|
|
|
|
|
|
module.exports = {
|