From b3db65d1b817221593cc058324e99bc116e889e9 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Thu, 29 Jan 2026 10:40:13 +0100 Subject: [PATCH] Add money history graph feature: Implement moneyHistoryGraph method in FalukantService and corresponding controller and router updates. Enhance frontend with a new dialog for displaying money history over various time ranges, including localization updates for German and English. This improves user experience by providing visual insights into financial data. --- backend/controllers/falukantController.js | 4 + backend/routers/falukantRouter.js | 1 + backend/services/falukantService.js | 56 +++++++ .../falukant/MoneyHistoryGraphDialog.vue | 150 ++++++++++++++++++ frontend/src/i18n/locales/de/falukant.json | 16 ++ frontend/src/i18n/locales/en/falukant.json | 16 ++ .../src/views/falukant/MoneyHistoryView.vue | 17 ++ 7 files changed, 260 insertions(+) create mode 100644 frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue diff --git a/backend/controllers/falukantController.js b/backend/controllers/falukantController.js index a248c7a..bf84b07 100644 --- a/backend/controllers/falukantController.js +++ b/backend/controllers/falukantController.js @@ -56,6 +56,10 @@ class FalukantController { if (!page) page = 1; return this.service.moneyHistory(userId, page, filter); }); + this.moneyHistoryGraph = this._wrapWithUser((userId, req) => { + const { range } = req.body || {}; + return this.service.moneyHistoryGraph(userId, range || '24h'); + }); this.getStorage = this._wrapWithUser((userId, req) => this.service.getStorage(userId, req.params.branchId)); this.buyStorage = this._wrapWithUser((userId, req) => { const { branchId, amount, stockTypeId } = req.body; diff --git a/backend/routers/falukantRouter.js b/backend/routers/falukantRouter.js index 8dc3aaa..618e20f 100644 --- a/backend/routers/falukantRouter.js +++ b/backend/routers/falukantRouter.js @@ -28,6 +28,7 @@ router.get('/inventory/?:branchId', falukantController.getInventory); router.post('/sell/all', falukantController.sellAllProducts); router.post('/sell', falukantController.sellProduct); router.post('/moneyhistory', falukantController.moneyHistory); +router.post('/moneyhistory/graph', falukantController.moneyHistoryGraph); router.get('/storage/:branchId', falukantController.getStorage); router.post('/storage', falukantController.buyStorage); router.delete('/storage', falukantController.sellStorage); diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index db10ee8..a88a60c 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -1802,6 +1802,62 @@ class FalukantService extends BaseService { return { data: rows, total: count, currentPage: page, totalPages: Math.ceil(count / limit) }; } + /** + * Geldverlauf für Graphenansicht. + * range: 'today' | '24h' | 'week' | 'month' | 'year' | 'all' + */ + async moneyHistoryGraph(hashedUserId, range = '24h') { + const u = await getFalukantUserOrFail(hashedUserId); + + const where = { falukantUserId: u.id }; + const now = new Date(); + let start = null; + + switch (range) { + case 'today': { + start = new Date(); + start.setHours(0, 0, 0, 0); + break; + } + case '24h': { + start = new Date(now.getTime() - 24 * 60 * 60 * 1000); + break; + } + case 'week': { + start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); + break; + } + case 'month': { + start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); + break; + } + case 'year': { + start = new Date(now.getTime() - 365 * 24 * 60 * 60 * 1000); + break; + } + case 'all': + default: + start = null; + } + + if (start) { + where.time = { [Op.gte]: start }; + } + + const rows = await MoneyFlow.findAll({ + where, + order: [['time', 'ASC']] + }); + + return rows.map(r => ({ + time: r.time, + moneyBefore: r.moneyBefore, + moneyAfter: r.moneyAfter, + changeValue: r.changeValue, + activity: r.activity + })); + } + async getStorage(hashedUserId, branchId) { const user = await getFalukantUserOrFail(hashedUserId); const branch = await getBranchOrFail(user.id, branchId); diff --git a/frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue b/frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue new file mode 100644 index 0000000..c3ce6ba --- /dev/null +++ b/frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/frontend/src/i18n/locales/de/falukant.json b/frontend/src/i18n/locales/de/falukant.json index ee61a6b..00bceb1 100644 --- a/frontend/src/i18n/locales/de/falukant.json +++ b/frontend/src/i18n/locales/de/falukant.json @@ -581,6 +581,22 @@ "time": "Zeit", "prev": "Zurück", "next": "Weiter", + "graph": { + "open": "Verlauf anzeigen", + "title": "Geldentwicklung", + "close": "Schließen", + "loading": "Lade Verlauf...", + "noData": "Für den gewählten Zeitraum liegen keine Buchungen vor.", + "range": { + "label": "Zeitraum", + "today": "Heute", + "24h": "Letzte 24 Stunden", + "week": "Letzte Woche", + "month": "Letzter Monat", + "year": "Letztes Jahr", + "all": "Gesamter Verlauf" + } + }, "activities": { "Product sale": "Produkte verkauft", "Production cost": "Produktionskosten", diff --git a/frontend/src/i18n/locales/en/falukant.json b/frontend/src/i18n/locales/en/falukant.json index 88dcf8c..afe0335 100644 --- a/frontend/src/i18n/locales/en/falukant.json +++ b/frontend/src/i18n/locales/en/falukant.json @@ -111,6 +111,22 @@ "time": "Time", "prev": "Previous", "next": "Next", + "graph": { + "open": "Show graph", + "title": "Money over time", + "close": "Close", + "loading": "Loading history...", + "noData": "No entries for the selected period.", + "range": { + "label": "Range", + "today": "Today", + "24h": "Last 24 hours", + "week": "Last week", + "month": "Last month", + "year": "Last year", + "all": "All history" + } + }, "activities": { "Product sale": "Product sale", "Production cost": "Production cost", diff --git a/frontend/src/views/falukant/MoneyHistoryView.vue b/frontend/src/views/falukant/MoneyHistoryView.vue index fda9101..bc939ad 100644 --- a/frontend/src/views/falukant/MoneyHistoryView.vue +++ b/frontend/src/views/falukant/MoneyHistoryView.vue @@ -9,6 +9,12 @@ +
+ +
+ @@ -42,17 +48,21 @@ {{ $t('falukant.moneyHistory.next') }} + + @@ -106,6 +119,10 @@ export default { margin-bottom: 1rem; } +.graph-section { + margin-bottom: 1rem; +} + table { width: 100%; border-collapse: collapse;