forked from getmoro/moro
-
Notifications
You must be signed in to change notification settings - Fork 0
/
db.js
195 lines (179 loc) · 5.07 KB
/
db.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// native
const path = require('path')
const fs = require('mz/fs')
// packages
const moment = require('moment')
const osHomedir = require('os-homedir')
// constants
const {
DB_FILE_MAIN,
DB_FILE_FOR_TESTS
} = require('./constants.json')
// ours
const helpers = require('./utils/helpers.js')
let dbFileName = DB_FILE_MAIN
// use a temporary db if in test mode
if (process.env.MORO_TEST_MODE === 'true') {
dbFileName = DB_FILE_FOR_TESTS
console.log('[info] moro running in test mode, a temporary db will be used')
}
const knex = require('knex')({
dialect: 'sqlite3',
connection: {
filename: path.join(osHomedir(), dbFileName)
},
useNullAsDefault: true
})
const removeDatabase = (dbFileName) => {
if (process.env.MORO_TEST_MODE === 'true') {
dbFileName = DB_FILE_FOR_TESTS
console.log('[info] moro running in test mode, a temporary db will be used')
}
const databaseFile = path.join(osHomedir(), dbFileName)
return fs.unlink(databaseFile)
.then(() => {
console.log('database file deleted successfully')
console.log('press ctrl - c to exit')
})
.catch((e) => {
console.log('Run: moro report --all to make sure data is cleared', e)
})
}
// Create a table
const createTable = (knex) => (
knex.schema.createTableIfNotExists('records', (table) => {
table.increments('id')
table.date('date')
table.time('start')
table.time('end')
table.integer('breakDuration')
})
.createTableIfNotExists('notes', (table) => {
table.increments('id')
table.date('date')
table.string('createdat')
table.text('note')
})
.catch((e) => console.log('Errors in createTable', e))
// input is an object, {date, start[optional], end[optional], breakDuration, action}
)
const updateDatabase = (options, knex) => {
const {date, start, end, breakDuration, action, note, createdat} = options
return createTable(knex)
.then(() => {
return knex
.select('*')
.from('records')
.where({date})
})
.then((row) => {
// date is there, update the row
if (row.length === 1) {
switch (action) {
case 'setStart':
return knex('records').update({start}).where({date})
case 'setEnd':
return knex('records').update({end}).where({date})
case 'setBreakDuration':
return knex('records').update({breakDuration}).where({date})
case 'addNote':
return knex.insert({date, note, createdat}).into('notes')
}
} else {
// date doesn't exist, insert it
return knex.insert({date, start, end, breakDuration}).into('records')
}
})
// Finally, add a .catch handler for the promise chain
.catch(function (e) {
console.error(e)
})
}
// gets data for a single day
const getDateReport = (date, knex) => (
// Then query the table...
createTable(knex)
.then(() => {
return knex
.select('*')
.from('records')
.where({date})
})
.then((row) => {
return knex
.select('*')
.from('notes')
.where({date})
.then((notes) => {
if (row[0]) {
row[0].notes = notes
}
return row[0]
})
})
.catch(err => {
console.log(err)
})
)
// if start / end is not yet marked, yell at the user
const getUndoneWarnings = (dayRecord) => {
if (!dayRecord || !dayRecord.start) {
return 'Start of your work day is not marked yet! run moro to set it. Start needs to be set before I can give you the report'
}
if (!dayRecord.end) {
return 'The end of your work day is not marked! run moro with no arguments to set it'
}
return undefined
}
const calculateWorkHours = (date, knex) => (
getDateReport(date, knex)
.then((data) => {
if (getUndoneWarnings(data)) {
console.log(getUndoneWarnings(data))
process.exit(0)
}
// console.log('data is: ', data)
const getBreak = (data) => data.breakDuration
const notes = data.notes
// to assign hours to moment objects, we need the diff so current moment is fine
const start = helpers.composeDateObject(data.start)
const end = helpers.composeDateObject(data.end)
const workHours = moment
.duration(end.diff(start.add({minutes: getBreak(data)})))
const hours = workHours.get('hours')
const minutes = workHours.get('minutes')
// to add negative sign
const formattedWorkHours = `${hours} Hours and ${minutes} Minutes`
return { date, formattedWorkHours, notes }
})
.catch((err) => {
console.log(err)
})
)
const getFullReport = (knex) => {
return createTable(knex)
.then(() => {
return knex.select('date')
.from('records')
.whereNotNull('start')
.whereNotNull('end')
.map((row) => calculateWorkHours(row.date, knex))
.then((results) => {
helpers.printAllDaysReport(results)
return (results)
})
.catch((err) => { console.error(err) })
})
.catch((err) => {
console.log(err)
})
}
module.exports = {
createTable,
getDateReport,
updateDatabase,
calculateWorkHours,
getFullReport,
removeDatabase,
knex
}