Receipts: Historical stats command

This commit is contained in:
2026-02-03 12:16:29 +01:00
parent fceefcc667
commit fb3f659831

View File

@@ -29,6 +29,11 @@ module.exports = {
.setDescription('Show spendings from the previous budget cycle instead of the current one')
.setRequired(false)
)
)
.addSubcommand(subcommand =>
subcommand
.setName('stats')
.setDescription('View detailed spending and savings statistics')
),
async execute(interaction) {
console.log('budget command entrypoint');
@@ -100,6 +105,47 @@ module.exports = {
await interaction.reply({ embeds: [budgetEmbed] });
break
case 'stats':
const allBudgets = db.prepare(`
SELECT id, budget_amount, exchange_rate, start_date, end_date
FROM weekly_budgets
ORDER BY start_date DESC
LIMIT 4
`).all();
let statsDescription = "";
let cumulativeSavingsEur = 0;
for (const budgetPeriod of allBudgets) {
const periodSpendings = db.prepare(`
SELECT amount
FROM grocery_spendings
WHERE budget_id = ? AND discord_id = ?
`).all(budgetPeriod.id, interaction.member.id);
const totalSpentInPeriodEur = periodSpendings.reduce((acc, s) => acc + s.amount, 0);
const savedInPeriodEur = budgetPeriod.budget_amount - totalSpentInPeriodEur;
cumulativeSavingsEur += savedInPeriodEur;
statsDescription += `**Period: ${budgetPeriod.start_date} - ${budgetPeriod.end_date}**\n`;
statsDescription += `Budget: ${budgetPeriod.budget_amount.toFixed(2)}\n`;
statsDescription += `Spent: ${totalSpentInPeriodEur.toFixed(2)}€ (${(totalSpentInPeriodEur * budgetPeriod.exchange_rate).toFixed(2)} kr)\n`;
statsDescription += `Saved: ${savedInPeriodEur.toFixed(2)}€ (${(savedInPeriodEur * budgetPeriod.exchange_rate).toFixed(2)} kr)\n`;
statsDescription += `Cumulative: ${cumulativeSavingsEur.toFixed(2)}\n\n`;
}
if (allBudgets.length === 0) {
statsDescription = "No budget periods on record.";
}
const statsEmbed = new EmbedBuilder()
.setColor(0x0099ff)
.setTitle(`${interaction.member.displayName}'s Budget Statistics`)
.setDescription(statsDescription)
.setTimestamp();
await interaction.reply({ embeds: [statsEmbed] });
break;
default:
await interaction.reply(`Sub mismatch. Switching on ${interaction.options.getSubcommand()}`);
break;