{"database": "fishbowl_archive", "table": "biscript", "rows": [[16, "_binary \u0001", "const numOfProd = $NUM{Number_of_products|5};\r\nconst dateRange = $RANGE{Date_Range|this year};\r\nconst chartOption = \"$LIST{Chart_Type|^bar,pie}\";\r\nconst displayLegend = $CHECK{Display_pie_legend|true};\r\nconst displayMiscSale = $CHECK{Display_Misc_Sales_Items|false};\r\nlet miscSale = \"AND soItem.typeId <> 11 \"\r\nif (displayMiscSale == true) {\r\n    miscSale = \" \";\r\n} else {\r\n    miscSale = \"AND soItem.typeId <> 11 \"\r\n}\r\n\r\nconst data = JSON.parse(runQuery(\"SELECT soItem.productNum, SUM(postSoItem.totalPrice) AS totalPrice from postSoItem \" \r\n    + \"JOIN soItem ON postSoItem.soItemId = soItem.id AND soItem.typeId <> 40 \"\r\n    + \"WHERE statusId <> 40 AND dateLastFulfillment >= '\" + dateRange.fromDate + \"' AND dateLastFulfillment <= '\" + dateRange.toDate + \"' \"\r\n    + miscSale\r\n    + \"GROUP BY productNum \"\r\n    + \"ORDER BY totalPrice \" \r\n    + \"DESC LIMIT \" + numOfProd)); \r\n    \r\nconst other = JSON.parse(runQuery(\"SELECT SUM(totalPrice) AS totalPrice \" \r\n    + \"FROM (SELECT SUM(postSoItem.totalPrice) AS totalPrice \"\r\n    + \"FROM postSoItem \"\r\n    + \"JOIN soItem ON postSoItem.soItemId = soItem.id AND soItem.typeId <> 40 AND soItem.statusId = 50 \"\r\n    + \"JOIN postSo ON postSo.soId = soItem.soId \"\r\n    + \"WHERE postSo.postDate >= '\" + dateRange.fromDate + \"' AND postSo.postDate <= '\" + dateRange.toDate + \"' \"\r\n    + \"GROUP BY productNum \"\r\n    + \"ORDER BY totalPrice DESC \"\r\n    + \"LIMIT \" + numOfProd + \", 18446744073709551615) AS subQuery\"));\r\n    //This offset is MySQL Infitity. See https://dev.mysql.com/doc/refman/5.7/en/select.html#id4651990\r\n    \r\nlet dateStr = UTIL.convertDate(dateRange.fromDate, true) + \" - \" + UTIL.convertDate(dateRange.toDate, false);\r\nif (moment(dateRange.fromDate).isSame('1000-01-01', 'year') && moment(dateRange.toDate).isSame('3000-01-01', 'year')) {\r\n  dateStr = 'All';\r\n}\r\n    \r\nfunction createBar(totalPrice, tableColors){\r\n    return {\r\n        backgroundColor: tableColors.halfAlpha,\r\n        borderColor: tableColors.fullAlpha,\r\n        borderWidth: 3,\r\n        data: totalPrice,\r\n    };\r\n}\r\n\r\nfunction createPie(data, tableColors) {\r\n    //Insert grey (other) into pie chart\r\n    tableColors.halfAlpha.push(UTIL.convertHex('#757575', 50));\r\n    tableColors.fullAlpha.push(UTIL.convertHex('#757575', 100));\r\n    return {\r\n        data: data,\r\n        backgroundColor: tableColors.halfAlpha,\r\n        borderColor: tableColors.fullAlpha,\r\n        borderWidth: 2,\r\n    };\r\n}\r\n\r\nconst barLabels = [];\r\nconst pieLabels = [];\r\nconst barTotalPrices = [];\r\nconst pieTotalPrices = [];\r\nlet barTotalPriceOverall = 0;\r\nlet pieTotalPriceOverall = 0;\r\nconst chartData = [];\r\nconst pieData = [];\r\n\r\nfor (let product = 0; product < data.length; product++) {\r\n    barLabels.push(data[product].productnum);\r\n    pieLabels.push(data[product].productnum);\r\n    barTotalPrices.push(data[product].totalprice);\r\n    pieTotalPrices.push(data[product].totalprice);\r\n    barTotalPriceOverall += barTotalPrices[product];\r\n}\r\n\r\npieTotalPriceOverall = barTotalPriceOverall + other[0].totalprice;\r\n\r\nlet tableColors = COLORS.get(numOfProd);\r\nchartData.push(createBar(barTotalPrices, tableColors));\r\n\r\npieTotalPrices.push(other[0].totalprice);\r\npieData.push(createPie(pieTotalPrices, tableColors));\r\npieLabels.push('Other');\r\n\r\nconst barChartData = {\r\n    labels: barLabels,\r\n    datasets: chartData\r\n}\r\n\r\nconst pieChartData = {\r\n    labels: pieLabels,\r\n    datasets: pieData\r\n}\r\n\r\nconst barOptions = {\r\n    title: {\r\n        display: true,\r\n        padding: 3\r\n    },\r\n    mode: 'index',\r\n    position: 'cursor',\r\n    intersect: false,\r\n    legend: {\r\n        display: false,\r\n    },\r\n    scales: {\r\n        xAxes: [{\r\n            stacked: true,\r\n            ticks: {\r\n                autoSkip: false\r\n            }\r\n        }],\r\n        yAxes: [{\r\n            ticks: {\r\n                beginAtZero: true,\r\n                callback: function(value, index, values) {\r\n                    return UTIL.dollarify(value, 0);\r\n                }\r\n            }\r\n        }]\r\n    },\r\n    tooltips: {\r\n        callbacks: {\r\n            label: (tooltipItem, data) => {\r\n                return UTIL.dollarify(tooltipItem.yLabel);\r\n            },\r\n            title: (tooltipItem, data) => {\r\n                return tooltipItem[0].xLabel;\r\n            }\r\n        },\r\n    },\r\n    responsive: true,\r\n    maintainAspectRatio: false,\r\n    plugins: {\r\n        datalabels: {\r\n            align: 'end',\r\n            anchor: 'end',\r\n            color: '#828891',\r\n            font: {\r\n                weight: 'bold',\r\n                family: 'Helvetica'\r\n            },\r\n            formatter: function(value, context) {\r\n                return UTIL.dollarify(value);\r\n            }\r\n        }\r\n    }\r\n};\r\n\r\nconst pieOptions = {\r\n    plugins: {\r\n        datalabels: {\r\n            display: false\r\n        }\r\n    },\r\n    legend: {\r\n        display: displayLegend\r\n    },\r\n    responsive: true,\r\n    maintainAspectRatio: false,\r\n    pieceLabel: {\r\n        render: 'label',\r\n        fontColor: '#828891',\r\n        fontSize: 14,\r\n        fontStyle: 'bold',\r\n        position: 'outside',\r\n        render: function (args) {\r\n            let label = (args.value/pieTotalPriceOverall * 100).toFixed(1) + '%';\r\n            return label;\r\n        }\r\n      },\r\n    tooltips: {\r\n            backgroundColor: '#ffffff',\r\n            titleFontColor: '#4e5156',\r\n            bodyFontColor: '#4e5156',\r\n            callbacks: {\r\n                label: (tooltipItem, data) => {\r\n                    return (data.datasets[0].data[tooltipItem.index] / pieTotalPriceOverall * 100).toFixed(1) + '%'; \r\n                },\r\n                title: (tooltipItem, data) => {\r\n                    return data.labels[tooltipItem[0].index]; \r\n                }\r\n            }\r\n        }\r\n}\r\n\r\nif(chartOption === 'bar') {\r\n    const ctxBar = document.getElementById('productChart');\r\n    new Chart(ctxBar, {\r\n        type: 'bar',\r\n        data: barChartData,\r\n        options: barOptions\r\n    });\r\n} else {\t\t\t\t\r\n    const ctxPie = document.getElementById('productChart');\r\n    new Chart(ctxPie, {\r\n        type: 'pie',\r\n        data: pieChartData,\r\n        options: pieOptions\r\n    });\r\n}\r\n\r\ndocument.getElementById(\"title\").innerHTML = 'Top ' + numOfProd + ' Products';\r\ndocument.getElementById(\"subTitle\").innerHTML = dateStr;\r\ndocument.getElementById(\"description\").innerHTML = '<Description>';\r\n", "2023-01-05 17:28:07.005000", "Query and logic for the Top Products page", "Top Products", "", 20, 4, "top-products", 0]], "columns": ["id", "active", "data", "dateLastModified", "description", "name", "note", "typeId", "fbVersion", "fbName", "published"], "primary_keys": ["id"], "primary_key_values": ["16"], "units": {}, "query_ms": 1.5885420143604279}