Ver código fonte

Charts per service category

Alan Colon 7 anos atrás
pai
commit
5fb89e49ac

+ 51 - 0
app/components/dashboard-page.js

@@ -138,6 +138,39 @@ app.component('appDashboardPage', {
                 </tbody>
               </table>
             </div>
+            <md-card>
+              <md-card-title>
+                <md-card-title-text>Labor cost</md-card-title-text>
+              </md-card-title>
+              <md-card-content>
+                <div style="width: 520px; height: 260px;" >
+                  <canvas class="chart chart-line" chart-data="serviceCategory.charts.laborCost.data" chart-colors="serviceCategory.charts.laborCost.colors"
+                    chart-labels="serviceCategory.charts.laborCost.labels" chart-series="serviceCategory.charts.laborCost.series" chart-options="serviceCategory.charts.laborCost.options">
+                  </canvas>
+                </div>
+                <div ng-repeat="color in serviceCategory.charts.laborCost.colors">
+                  <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
+                  {{$ctrl.charts.costPerCarton.series[$index]}}
+                </div>
+              </md-card-content>
+            </md-card>
+            <md-card>
+              <md-card-title>
+                <md-card-title-text>Cost per carton</md-card-title-text>
+              </md-card-title>
+              <md-card-content>
+                <div style="width: 520px; height: 260px;" >
+                  <canvas class="chart chart-line" chart-data="serviceCategory.charts.costPerCarton.data" chart-colors="serviceCategory.charts.costPerCarton.colors"
+                    chart-labels="serviceCategory.charts.costPerCarton.labels" chart-series="serviceCategory.charts.costPerCarton.series" chart-options="serviceCategory.charts.costPerCarton.options">
+                  </canvas>
+                </div>
+                <div ng-repeat="color in serviceCategory.charts.costPerCarton.colors">
+                  <div style="background-color: {{color}}; width: 16px; height: 16px; display: inline-block; margin: 0 4px;"></div>
+                  {{$ctrl.charts.costPerCarton.series[$index]}}
+                </div>
+              </md-card-content>
+            </md-card>
+
           </md-card-content>
         </md-card>
       </div>
@@ -189,6 +222,24 @@ app.component('appDashboardPage', {
     const load = (date) => {
       api.statistics(date).then(stats => {
         this.statistics = stats
+        stats.serviceCategories.forEach(serviceCategory => {
+          serviceCategory.charts = {
+            costPerCarton: statistics.chart({
+              rows: serviceCategory.metricsOverTime,
+              seriesField: 'key',
+              dataField: 'costPer',
+              labelsField: 'date',
+              format: (label, value) => `${label}: $${value.toFixed(2)} per carton`
+            }),
+            laborCost: statistics.chart({
+              rows: serviceCategory.metricsOverTime,
+              seriesField: 'key',
+              dataField: 'laborCost',
+              labelsField: 'date',
+              format: (label, value) => `${label}: $${value.toFixed(2)} labor cost`
+            })
+          }
+        })
         this.charts = statistics.charts(stats.metricsOverTime)
         this.last = stats.last
       })

+ 2 - 0
app/services/statistics.js

@@ -100,4 +100,6 @@ app.service('statistics', function(api, $mdColors) {
       })
     }
   }
+
+  this.chart = chart
 })

+ 38 - 3
lib/controllers/statistics.js

@@ -35,6 +35,37 @@ const get = async (req, res) => {
     }
   })
 
+  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,
@@ -146,7 +177,8 @@ const get = async (req, res) => {
           replacements: {
             terminalIds,
             serviceCategory: sc.key,
-            date: date.format('YYYY-MM-DD')
+            date: date.format('YYYY-MM-DD'),
+            startDate: date.add(-30, 'days').format('YYYY-MM-DD')
           }
         }
         const [mpsc] = await sequelize.query(metricsPerServiceCategorySql(sc.serviceColumn), opts)
@@ -154,6 +186,7 @@ const get = async (req, res) => {
         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,
@@ -165,7 +198,8 @@ const get = async (req, res) => {
             key: t.terminal,
             laborCategories: mptlc.filter(l => l.terminal === t.terminal)
           })),
-          lastMetrics: lastMetrics[0]
+          lastMetrics: lastMetrics[0],
+          metricsOverTime
         }
       })
     ),
@@ -190,7 +224,8 @@ const get = async (req, res) => {
       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
+      lastMetrics: queries[i].lastMetrics,
+      metricsOverTime: queries[i].metricsOverTime
     })),
     metricsOverTime
   }

+ 1 - 1
package.json

@@ -14,7 +14,7 @@
   "dependencies": {
     "@alancnet/icomoon-svg": "^2.0.0",
     "@alancnet/material-design-icons": "^1.0.0",
-    "@alancnet/material-framework": "^1.0.15",
+    "@alancnet/material-framework": "^1.0.16",
     "aguid": "^2.0.0",
     "angular": "^1.6.10",
     "angular-animate": "^1.7.0",