diff --git a/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java b/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java index d7800b2bec9a9dd3519a8a4a55403777880784fb..1c9f805d31d587749d71804ac89d1f50c81c0e62 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java +++ b/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java @@ -62,6 +62,10 @@ public class DefaultCharts getChartFromFile("charts/AverageMonthlyIncomesAndExpendituresPerYearBar.js"), ChartType.DEFAULT, 9, ChartDisplayType.BAR, ChartGroupType.YEAR, "averageMonthlyIncomesAndExpendituresPerYearBar.png"); + private static final Chart CHART_AVERAGE_MONTHLY_INCOMES_AND_EXPENDITURES_PER_CATEGORY_BAR = new Chart("charts.default.averageMonthlyIncomesAndExpendituresPerCategoryBar", + getChartFromFile("charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js"), + ChartType.DEFAULT, 1, ChartDisplayType.BAR, ChartGroupType.NONE, "averageMonthlyIncomesAndExpendituresPerCategoryBar.png"); + private DefaultCharts() { } @@ -80,6 +84,7 @@ public class DefaultCharts charts.add(CHART_INCOMES_AND_EXPENDITURES_PER_YEAR_BY_CATEGORIES); charts.add(CHART_AVERAGE_TRANSACTION_AMOUNT_PER_CATEGORY); charts.add(CHART_AVERAGE_MONTHLY_INCOMES_AND_EXPENDITURES_PER_YEAR_BAR); + charts.add(CHART_AVERAGE_MONTHLY_INCOMES_AND_EXPENDITURES_PER_CATEGORY_BAR); return charts; } diff --git a/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js b/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js new file mode 100644 index 0000000000000000000000000000000000000000..8ab1d393da9c66a65485b4a54fc95470bd578409 --- /dev/null +++ b/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js @@ -0,0 +1,150 @@ +/* This list will be dynamically filled with all the transactions between + * the start and and date you select on the "Show Chart" page + * and filtered according to your specified filter. + * An example entry for this list and tutorial about how to create custom charts ca be found in the BudgetMaster wiki: + * https://github.com/deadlocker8/BudgetMaster/wiki/How-to-create-custom-charts + */ +var transactionData = []; + +// Note: All variables starting with "localized" are only available inside default charts. +moment.locale(localizedLocale); + +var months = []; +var categoryNames = []; +var colors = []; +var incomesPerCategory = []; +var expendituresPerCategory = []; + +for(var i = 0; i < transactionData.length; i++) +{ + var transaction = transactionData[i]; + + var month = moment(transaction.date).startOf('month').format('MMM YY'); + if(!months.includes(month)) + { + months.push(month); + } + + var categoryName = transaction.category.name; + // create new category if not already in dict + if(!categoryNames.includes(categoryName)) + { + categoryNames.push(categoryName); + colors.push(transaction.category.color); + incomesPerCategory.push([]); + expendituresPerCategory.push([]); + } + + // determine index of categoryName in list because the transactions are not ordered by category and some categories + // will be missing either for income or expenditures + var index = categoryNames.indexOf(categoryName); + + // add to income or expenditure sum + var amount = transaction.amount; + if(amount > 0) + { + incomesPerCategory[index].push(amount); + expendituresPerCategory[index].push(0); + } + else + { + incomesPerCategory[index].push(0); + expendituresPerCategory[index].push(amount); + } +} + + +// Prepare your chart settings here (mandatory) +var plotlyData = []; + +for(var j = 0; j < categoryNames.length; j++) +{ + var currentName = categoryNames[j]; + + var incomeAverage = calculateAverage(incomesPerCategory[j], months.length); + var expenditureAverage = calculateAverage(expendituresPerCategory[j], months.length); + + addDPlotlyData(plotlyData, incomeAverage, currentName, colors[j]); + addDPlotlyData(plotlyData, expenditureAverage, currentName, colors[j], false); +} + + +// Add your Plotly layout settings here (optional) +var plotlyLayout = { + title: { + text: localizedTitle + }, + xaxis: { + }, + yaxis: { + title: localizedData['label1'] + ' ' + localizedCurrency, + rangemode: 'tozero', + tickformat: '.2f', + showline: true + }, + barmode: 'relative', + hovermode: 'closest' // show hover popup only for hovered item +}; + +// Add your Plotly configuration settings here (optional) +var plotlyConfig = { + showSendToCloud: false, + displaylogo: false, + showLink: false, + responsive: true, + displayModeBar: true, + toImageButtonOptions: { + format: 'png', + filename: 'BudgetMaster_chart_export', + height: 1080, + width: 1920, + } +}; + +// Don't touch this line +Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); + + +function addDPlotlyData(plotlyData, averageValue, categoryName, color, showLegend) +{ + // add border if category color is white + var borderWidth = 0; + if(color.toUpperCase().startsWith('#FFFFFF')) + { + borderWidth = 1; + } + + plotlyData.push({ + y: [averageValue], + x: [categoryName], + orientation: 'v', + type: 'bar', + hoverinfo: 'text', + hovertext: [prepareHoverText(categoryName, averageValue)], + name: categoryName, + legendgroup: categoryName, + showlegend: showLegend, + marker: { + color: color, // use the category's color + line: { + color: '#212121', + width: borderWidth + } + } + }); +} + +function calculateAverage(values, numberOfMonths) +{ + var sum = 0; + values.forEach(function(value) + { + sum += value; + }); + return (sum / numberOfMonths) / 100; +} + +function prepareHoverText(categoryName, value) +{ + return categoryName + ' ' + value.toFixed(1) + ' ' + localizedCurrency; +} \ No newline at end of file diff --git a/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js b/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js index ec9504869d73627feb44cf2886110441b9942e19..cd69d8e2f1b02d2732d793b79a32c493be4e23a6 100644 --- a/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js +++ b/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js @@ -140,45 +140,3 @@ function prepareHoverText(categoryName, value) { return categoryName + ' ' + value.toFixed(1) + ' ' + localizedCurrency; } - - -// Add your Plotly layout settings here (optional) -var plotlyLayout = { - title: { - text: localizedTitle - }, - xaxis: { - }, - yaxis: { - title: localizedData['label1'] + ' ' + localizedCurrency, - rangemode: 'tozero', - tickformat: '.2f', - showline: true - }, - barmode: 'stack', - hovermode: 'closest' // show hover popup only for hovered item -}; - -// Add your Plotly configuration settings here (optional) -var plotlyConfig = { - showSendToCloud: false, - displaylogo: false, - showLink: false, - responsive: true, - displayModeBar: true, - toImageButtonOptions: { - format: 'png', - filename: 'BudgetMaster_chart_export', - height: 1080, - width: 1920, - } -}; - -// Don't touch this line -Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); - - -function prepareHoverText(categoryName, value) -{ - return categoryName + ' ' + value.toFixed(1) + ' ' + localizedCurrency; -} \ No newline at end of file diff --git a/src/main/resources/languages/base_de.properties b/src/main/resources/languages/base_de.properties index f6a548612f73d8c0cd597dd1531a03d9b09c915d..88f1e7d7589c0556dfc40a6bf45d3f2aed41b00f 100644 --- a/src/main/resources/languages/base_de.properties +++ b/src/main/resources/languages/base_de.properties @@ -560,6 +560,8 @@ charts.default.averageTransactionAmountPerCategory=Durchschnittlicher Transaktio charts.default.averageTransactionAmountPerCategory.localization='{"label1": "Durchschnittlicher Transaktionsbetrag in"'} charts.default.averageMonthlyIncomesAndExpendituresPerYearBar=Durchschnittliche monatliche Einnahmen/Ausgaben charts.default.averageMonthlyIncomesAndExpendituresPerYearBar.localization='{"traceName1": "Einnahmen", "traceName2": "Ausgaben"', "axisY": "Durchschnittlicher monatlicher Betrag in"'} +charts.default.averageMonthlyIncomesAndExpendituresPerCategoryBar=Durchschnittliche monatliche Einnahmen/Ausgaben pro Kategorie +charts.default.averageMonthlyIncomesAndExpendituresPerCategoryBar.localization='{"label1": "Durchschnittlicher Summe in"'} charts.custom=Eigene Diagramme charts.default=Standarddiagramme diff --git a/src/main/resources/languages/base_en.properties b/src/main/resources/languages/base_en.properties index 23161e21ff127c39b9cb0f3d36c3a25f18510310..8fb2dc4d1fb5aa572f3c91892cc97e0279c5914a 100644 --- a/src/main/resources/languages/base_en.properties +++ b/src/main/resources/languages/base_en.properties @@ -560,6 +560,8 @@ charts.default.averageTransactionAmountPerCategory=Average transaction amount pe charts.default.averageTransactionAmountPerCategory.localization='{"label1": "Average transaction amount in"'} charts.default.averageMonthlyIncomesAndExpendituresPerYearBar=Average monthly incomes/expenditures charts.default.averageMonthlyIncomesAndExpendituresPerYearBar.localization='{"traceName1": "Incomes", "traceName2": "Expenditures"', "axisY": "Average monthly amount in"'} +charts.default.averageMonthlyIncomesAndExpendituresPerCategoryBar=Average monthly incomes/expenditures per category +charts.default.averageMonthlyIncomesAndExpendituresPerCategoryBar.localization='{"label1": "Average sum in"'} charts.custom=Custom Charts charts.default=Default Charts diff --git a/src/main/resources/static/images/charts/averageMonthlyIncomesAndExpendituresPerCategoryBar.png b/src/main/resources/static/images/charts/averageMonthlyIncomesAndExpendituresPerCategoryBar.png new file mode 100644 index 0000000000000000000000000000000000000000..1f57eb679c64903a21716019cb36a39cb544540c Binary files /dev/null and b/src/main/resources/static/images/charts/averageMonthlyIncomesAndExpendituresPerCategoryBar.png differ