| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- const _ = require('lodash')
- const { Terminal, ServiceCategory } = require('../database')
- const sequelize = require('../database/sequelize')
- const { sanitize } = require('@alancnet/material-framework/lib/util')
- const moment = require('moment-immutable')
- const get = async (req, res) => {
- const terminalIds = (await Terminal.findAll())
- .filter(loc => req.claims.TERMINAL_ALL_ACCESS || req.claims[`TERMINAL_${loc.key}_ACCESS`])
- .map(loc => loc.id)
- const date = req.params.date
- ? moment(req.params.date)
- : moment((await sequelize.query('select max(date) as date from workdays where laborCost > 0'))[0].date || moment.now())
- const [metricsOverTime, metadata] = await sequelize.query(`
- SELECT
- loc.key,
- wd.date,
- wd.laborCost,
- 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
- WHERE loc.id IN(:terminalIds)
- AND wd.date <= :date
- AND wd.date >= :startDate
- GROUP BY loc.key, wd.date
- `, {
- replacements: {
- terminalIds,
- date: date.format('YYYY-MM-DD'),
- startDate: date.add(-30, 'days').format('YYYY-MM-DD')
- }
- })
- const metricsOverTimeSql = (serviceColumn) => `
- select
- terminals.key,
- workdays.date,
- 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 terminals.id in(:terminalIds)
- and serviceCategories.key = :serviceCategory
- and workdays.date <= :date
- and workdays.date >= :startDate
- group by terminals.key, workdays.date
- `
- 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.${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 terminals.id in(:terminalIds)
- and workdays.date = :date
- and serviceCategories.key = :serviceCategory
- group by terminals.key, serviceCategories.key, laborCategories.key
- `
- const metricsPerServiceCategorySql = (serviceColumn) => `
- select
- serviceCategory,
- displayOrder,
- cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
- from (${metricsSql(serviceColumn)})
- group by serviceCategory
- order by displayOrder
- `
- const metricsPerLaborCategorySql = (serviceColumn) => `
- select
- serviceCategory,
- laborCategory,
- cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
- from (${metricsSql(serviceColumn)})
- group by laborCategory
- `
- const metricsPerTerminalAndServiceCategorySql = (serviceColumn) => `
- select
- terminal,
- serviceCategory,
- cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
- from (${metricsSql(serviceColumn)})
- group by terminal, serviceCategory
- `
- const metricsPerTerminalAndLaborCategorySql = (serviceColumn) => `
- select
- terminal,
- serviceCategory,
- laborCategory,
- cast(sum(distinct laborCost) as double) / sum(distinct ${serviceColumn}) as costPer
- from (${metricsSql(serviceColumn)})
- group by terminal, laborCategory
- `
- 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 = :date
- and serviceCategories.key = :serviceCategory
- and terminals.id in(:terminalIds)
- `
- const serviceCategories = (await ServiceCategory.findAll())
- //const opts = {replacements: {serviceCategory: sc.key, terminalIds}}
- const ret = {
- date,
- serviceCategories: await Promise.all(
- (await ServiceCategory.findAll()).map(async sc => {
- const opts = {
- replacements: {
- terminalIds,
- serviceCategory: sc.key,
- date: date.format('YYYY-MM-DD'),
- startDate: date.add(-30, 'days').format('YYYY-MM-DD')
- }
- }
- 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)
- const [metricsOverTime] = await sequelize.query(metricsOverTimeSql(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
- }
- })
- ),
- 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: 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: queries[i].metricsOverTime
- })),
- metricsOverTime
- }
- res.status(200).send(results)
- }
- module.exports = {
- get
- }
|