@gameroom/cli
Version:
A command line tool for Gameroom
161 lines (151 loc) • 5.5 kB
JavaScript
const cosmetic = require('cosmetic'),
Table = require('tabley'),
{
enums: { timecard_status },
models: { User, Timecard }
} = require('@gameroom/kit'),
{ join, resolve } = require('path'),
{ correctionStatus, dateAddDays, dateLocaleString, dateString, getAll, grGreen, printTable, writeCSVFile } = require('../../helpers'),
{ spinner } = require('../../refs')
module.exports = async({ start_at, end_at, days, weeks, id, email, first, last, write }) => {
spinner.start()
spinner.info(`generating ${grGreen('timecards')} report`)
spinner.info(`from ${grGreen(start_at.toLocaleString())} to ${grGreen(end_at.toLocaleString())}`)
const filters = [{ key: 'locked', value: false }]
if (id) filters.push({ key: 'id', value: id })
if (email) filters.push({ key: 'email', value: email })
if (first) filters.push({ key: 'first_name', value: first })
if (last) filters.push({ key: 'last_name', value: last })
spinner.text = `getting ${grGreen('users')}`
const users = await getAll(User, {
filter: { and: filters },
sort : [{ last_name: 1 }]
})
spinner.succeed(`got ${users.length} ${grGreen('users')}`)
spinner.text = `getting ${grGreen('timecards')}`
let timecards = await getAll(Timecard, { filter: {
and: [
{ key: 'started_at', comparison: '>=', value: start_at },
{ key: 'ended_at', comparison: '<=', value: end_at },
{ key: 'status', comparison: '!=', value: 3 }
]
} })
const corrected_timecards = await getAll(Timecard, { filter: {
and: [
{ key: 'started_correction', comparison: '>=', value: start_at },
{ key: 'ended_correction', comparison: '<=', value: end_at },
{ key: 'status', value: 3 }
]
} })
const all_timecards = [ ...timecards, ...corrected_timecards ].filter(t => users.find(u => u.id === t.user_id)).sort((a, b) => (a.status === 3 ? a.started_correction : a. started_at) < (b.status === 3 ? b.started_correction : b. started_at) ? -1 : 1)
spinner.succeed(`got ${all_timecards.length} total ${grGreen('timecards')}`)
const csv_data = []
for (const user of users) {
const user_timecards = all_timecards.filter(t => t.user_id === user.id)
if (user_timecards.length === 0) continue
// meta
const total = {
first: user.first_name,
last: user.last_name,
email: user.email,
week: 'total',
in: start_at,
out: dateAddDays(end_at, -1),
hours: 0,
status: null,
error: null
}
const week_totals = []
if (!weeks) weeks = []
for (let [index, week] of weeks.entries()) week_totals.push({
first: user.first_name,
last: user.last_name,
email: user.email,
week: `week ${index + 1}`,
in: (dateAddDays(start_at, index * 7)),
out: dateAddDays(week, -1),
hours: 0,
status: null,
error: null
})
let previous
// timecards
const rows = []
for (let [index, timecard] of user_timecards.entries()) {
const started_at = timecard.status === 3 ? timecard.started_correction : timecard.started_at
const ended_at = timecard.status === 3 ? timecard.ended_correction : timecard.ended_at
// row
const row = {
first: user.first_name,
last: user.last_name,
email: user.email,
in: started_at,
out: ended_at,
hours: (ended_at - started_at) / 36e2,
status: timecard_status[timecard.status],
error: null
}
// week meta hours
for (let [index, week] of week_totals.entries()) {
const end = new Date(ended_at * 1000)
if (end > week.in && end <= dateAddDays(week.out, 1)) {
week.hours += row.hours
row.week = week.week
break
}
}
// total hours
total.hours += row.hours
// Error Checking
if (row.hours > 11) row.error = ('>11')
if (previous && row.in < previous.out) {
if (row.error) {
row.error += ' overlap'
} else {
row.error = 'overlap'
}
}
previous = row
rows.push(row)
}
const meta = [ ...week_totals, total ]
for (const m of meta) {
m.in = m.in.toLocaleDateString()
m.out = m.out.toLocaleDateString()
}
for (const r of rows) {
r.in = r.in.toLocaleString()
r.out = r.out.toLocaleString()
r.hours = r.hours.toFixed ? r.hours.toFixed(2) : r.hours
}
// table
const columns = [
{ key: 'first', hidden: true },
{ key: 'last', hidden: true },
{ key: 'email', hidden: true },
{ key: 'in', title: 'In' },
{ key: 'out', title: 'Out' },
{ key: 'hours', title: 'Hours' },
{ key: 'status', title: 'Status', value: v => correctionStatus(v) },
{ key: 'error', title: 'Error', value: v => cosmetic.red(v) }
]
if (weeks.length) columns.splice(1, 0, { key: 'week', title: 'Week' })
const table = new Table(rows, {
title: grGreen(user.last_name && user.first_name ? `${user.last_name}, ${user.first_name}` : user.email),
align: 'center',
meta,
columns,
margin: 4,
})
csv_data.push(...rows, ...meta)
spinner.stop()
table.print()
console.log()
spinner.start()
}
if (write) {
const path = await writeCSVFile(join(resolve(write === true ? '.' : write), 'gameroom-timecards-report.csv'), csv_data)
spinner.succeed(`wrote data to ${path}`)
}
spinner.succeed(`generated ${grGreen('timecards')} report `).stop()
}