From 2790602d8b5cce38cd1095f51f2f7af76301841b Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 30 Apr 2024 01:49:30 -0400 Subject: [PATCH] earnings reports and ioserver keepalive tweaking --- app/services/report.js | 63 +++++++++++++------ app/views/home.pug | 16 ++--- .../report/components/weekly-summary.pug | 17 +++++ app/views/report/dashboard.pug | 14 +---- lib/site-ioserver.js | 6 +- 5 files changed, 73 insertions(+), 43 deletions(-) create mode 100644 app/views/report/components/weekly-summary.pug diff --git a/app/services/report.js b/app/services/report.js index 8241723..f980456 100644 --- a/app/services/report.js +++ b/app/services/report.js @@ -21,31 +21,56 @@ export default class ReportService extends SiteService { } async getWeeklyEarnings (user) { + const { client: clientService } = this.dtp.services; + const NOW = new Date(); const dateStart = this.startOfWeek(NOW); const dateEnd = dayjs(dateStart).add(1, 'week').toDate(); this.log.debug('computing weekly earnings', { dateStart, dateEnd }); - /* - * I'm sure there's some beautiful way to do this using aggregation but I - * don't care at all (and won't) until aggregation becomes a usable API. - */ - const response = { sessionCount: 0, duration: 0, billable: 0 }; - await TaskSession - .find({ - user: user._id, - $and: [ - { created: { $gte: dateStart } }, - { finished: { $lt: dateEnd } }, - ], - }) - .cursor() - .eachAsync(async (session) => { - response.sessionCount += 1; - response.duration += session.duration; - response.billable += session.hourlyRate * (session.duration / 60 / 60); - }); + const data = await TaskSession.aggregate([ + { + $match: { + user: user._id, + $and: [ + { created: { $gte: dateStart } }, + { finished: { $lt: dateEnd } }, + ], + }, + }, + { + $group: { + _id: { project: '$project' }, + sessionCount: { $sum: 1 }, + duration: { $sum: '$duration' }, + billable: { + $sum: { + $multiply: [ + '$hourlyRate', + { $divide: ['$duration', 3600 ] }, + ], + }, + }, + }, + }, + { + $project: { + _id: 0, + project: '$_id.project', + sessionCount: '$sessionCount', + duration: '$duration', + billable: '$billable', + }, + }, + ]); + + const response = await TaskSession.populate(data, [ + { + path: 'project', + populate: clientService.populateClientProject, + }, + ]); return response; } diff --git a/app/views/home.pug b/app/views/home.pug index 741dfc0..cc73043 100644 --- a/app/views/home.pug +++ b/app/views/home.pug @@ -2,21 +2,13 @@ extends layout/main block view-content include task/components/grid + include report/components/weekly-summary - section.uk-section.uk-section-secondary.uk-section-small + section.uk-section.uk-section-muted.uk-section-small .uk-container - div(uk-grid).uk-flex-between - .uk-width-auto - div sessions - .uk-text-large.uk-text-bold= formatCount(weeklyEarnings.sessionCount) - .uk-width-auto - div time worked - .uk-text-large.uk-text-bold= numeral(weeklyEarnings.duration).format('0:00:00') - .uk-width-auto - div billable - .uk-text-large.uk-text-bold= numeral(weeklyEarnings.billable).format('$0,0.00') + +renderWeeklySummaryReport(weeklyEarnings) - section.uk-section.uk-section-default + section.uk-section.uk-section-default.uk-section-small .uk-container +renderTaskGrid( taskGrid.pendingTasks, diff --git a/app/views/report/components/weekly-summary.pug b/app/views/report/components/weekly-summary.pug new file mode 100644 index 0000000..9d0cd36 --- /dev/null +++ b/app/views/report/components/weekly-summary.pug @@ -0,0 +1,17 @@ +mixin renderWeeklySummaryReport (data) + table.uk-table.uk-table-small.uk-table-justify.no-select + thead + tr + th Project + th Client + th Sessions + th Time Worked + th Billable + tbody + each row in data + tr + td.uk-table-expand=row.project.name + td= row.project.client.name + td= formatCount(row.sessionCount) + td= numeral(row.duration).format('0:00:00') + td= numeral(row.billable).format('$0,0.00') \ No newline at end of file diff --git a/app/views/report/dashboard.pug b/app/views/report/dashboard.pug index 8f909f1..6725163 100644 --- a/app/views/report/dashboard.pug +++ b/app/views/report/dashboard.pug @@ -1,16 +1,8 @@ extends ../layout/main block view-content + include components/weekly-summary + section.uk-section.uk-section-default.uk-section .uk-container - - div(uk-grid).uk-flex-between - .uk-width-auto - .uk-text-bold.uk-text-small Sessions - div= formatCount(weeklyEarnings.sessionCount) - .uk-width-auto - .uk-text-bold.uk-text-small Hours - div= numeral(weeklyEarnings.duration).format('0:00:00') - .uk-width-auto - .uk-text-bold.uk-text-small Billable - div= numeral(weeklyEarnings.billable).format('$0,0.00') \ No newline at end of file + +renderWeeklySummaryReport(weeklyEarnings) \ No newline at end of file diff --git a/lib/site-ioserver.js b/lib/site-ioserver.js index 7c9f678..64c7858 100644 --- a/lib/site-ioserver.js +++ b/lib/site-ioserver.js @@ -50,7 +50,11 @@ export class SiteIoServer extends SiteCommon { this.adapterSubClient = this.dtp.redis.duplicate(); this.adapter = createAdapter(this.adapterPubClient, this.adapterSubClient); - this.io = new Server(httpServer, { adapter: this.adapter, transports }); + this.io = new Server(httpServer, { + adapter: this.adapter, transports, + pingInterval: 5000, + pingTimeout: 3000, + }); this.io.adapter(this.adapter); this.io.on('connection', this.onSocketConnect.bind(this));