working_times 0.3.2 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/working_times.rb +1 -0
- data/lib/working_times/cli.rb +64 -23
- data/lib/working_times/config.rb +41 -31
- data/lib/working_times/constants.rb +8 -3
- data/lib/working_times/invoice.rb +135 -0
- data/lib/working_times/record.rb +28 -23
- data/lib/working_times/state.rb +16 -25
- metadata +39 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7141b461d0bf7215ca3656d259de497ec7062a3639a0945a1fa8dea9deea27ce
|
4
|
+
data.tar.gz: ce7ffcd9a86aa7395d15ccab63a44408ddbf5e00aa1ce489bdb0266c2d2170d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94cfce8f51ded451931e65fbab2983b0a51a769522c7e762625e739e44484e5f0224ffba32bc9c357f26fc0c28b1d5e5dc641cb452695766198e3f83d239689e
|
7
|
+
data.tar.gz: 50d4bab6fa14e2c69eeec085e373694384cd94a72f0647b8212581820b0e019447ffd2603de052de3b13b865a57299731ebb08558dbe46ac1d374fe251a0ae69
|
data/lib/working_times.rb
CHANGED
data/lib/working_times/cli.rb
CHANGED
@@ -1,59 +1,100 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require 'thor'
|
2
|
+
require 'fileutils'
|
4
3
|
|
5
4
|
module WorkingTimes
|
6
5
|
class CLI < Thor
|
7
6
|
include State
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
desc 'init WORKON [TERM] [COMPANY]', 'initialize data directory for your working'
|
9
|
+
def init(workon, term = 'default', company = '')
|
10
|
+
if Dir.exist?(workon)
|
11
|
+
puts "WORKON '#{workon}' is already created. Or name conflicted.'"
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
FileUtils.mkdir_p(File.join(workon, 'terms'))
|
16
|
+
FileUtils.mkdir_p(File.join(workon, 'invoices'))
|
17
|
+
initialize_wtconf(workon, term, company)
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'start [COMMENT] ', 'Start working with comment.'
|
21
|
+
def start(comment = '')
|
13
22
|
if working?
|
14
23
|
puts "You are already on working at #{current_work}."
|
15
24
|
puts "To finish this, execute 'wt finish'."
|
16
25
|
return
|
17
26
|
end
|
18
27
|
|
19
|
-
|
20
|
-
|
28
|
+
initialize_term_log
|
29
|
+
|
30
|
+
Record.new(timestamp: DateTime.now, comment: comment).start
|
31
|
+
start_work
|
21
32
|
end
|
22
33
|
|
23
|
-
desc 'st [COMMENT]
|
34
|
+
desc 'st [COMMENT]', 'Short hand for *start*'
|
24
35
|
alias st start
|
25
36
|
|
26
37
|
desc 'finish [COMMENT]', 'Finish working on current group.'
|
27
|
-
def finish(comment =
|
38
|
+
def finish(comment = '')
|
28
39
|
unless working?
|
29
40
|
puts 'You are not starting work. Execute "wt start" to start working.'
|
30
41
|
return
|
31
42
|
end
|
32
43
|
|
33
|
-
Record.new(timestamp:
|
44
|
+
Record.new(timestamp: DateTime.now, comment: comment).finish
|
34
45
|
finish_work
|
35
46
|
end
|
36
47
|
|
37
48
|
desc 'fi [COMMENT]', 'Short hand for *finish*'
|
38
49
|
alias fi finish
|
39
50
|
|
40
|
-
desc 'rest DURATION', 'Record resting time. e.g. \'wt rest 1h30m\''
|
41
|
-
def rest(duration
|
42
|
-
if duration.nil?
|
43
|
-
puts <<~MSG
|
44
|
-
Please specify duration of resting.
|
45
|
-
e.g. wt rest 1h30m
|
46
|
-
e.g. wt rest '1 hour 30 minutes'
|
47
|
-
MSG
|
48
|
-
return
|
49
|
-
end
|
50
|
-
|
51
|
+
desc 'rest DURATION', 'Record resting time. e.g. \'wt rest 1h30m\'\'wt rest 1 hour 30 minutes\''
|
52
|
+
def rest(duration)
|
51
53
|
unless working?
|
52
54
|
puts 'You are not starting work. Execute "wt start" to start working.'
|
53
55
|
return
|
54
56
|
end
|
55
57
|
|
56
|
-
Record.new(timestamp:
|
58
|
+
Record.new(timestamp: DateTime.now, duration: duration).rest
|
59
|
+
end
|
60
|
+
|
61
|
+
option :build, type: :boolean, aliases: ['-b']
|
62
|
+
desc 'invoice', 'Create invoice for current term by TeX template. It will build pdf if option is set'
|
63
|
+
def invoice
|
64
|
+
Invoice.new.tap do |invoice|
|
65
|
+
invoice.generate
|
66
|
+
invoice.build if options[:build]
|
67
|
+
end
|
68
|
+
puts "Invoice created to #{path_invoice_current_term}."
|
69
|
+
end
|
70
|
+
|
71
|
+
desc 'version', 'Show version of working_times'
|
72
|
+
def version
|
73
|
+
puts 'version: ' + VERSION
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def initialize_wtconf(workon, term, company)
|
79
|
+
# on initializing, we shouldn't use path helper e.g. Config#data_dir
|
80
|
+
data_dir = File.expand_path(workon)
|
81
|
+
File.write(File.join(data_dir, 'wtconf.json'), <<~WTCONF)
|
82
|
+
{
|
83
|
+
"term": "#{term}",
|
84
|
+
"invoice": {
|
85
|
+
"company": "#{company}",
|
86
|
+
"template": "",
|
87
|
+
"salaryPerHour": 0,
|
88
|
+
"taxRate": 0.0
|
89
|
+
}
|
90
|
+
}
|
91
|
+
WTCONF
|
92
|
+
end
|
93
|
+
|
94
|
+
def initialize_term_log
|
95
|
+
return if File.exist?(path_current_term)
|
96
|
+
|
97
|
+
File.write(path_current_term, SCHEMA.join(',') + "\n")
|
57
98
|
end
|
58
99
|
end
|
59
100
|
end
|
data/lib/working_times/config.rb
CHANGED
@@ -1,45 +1,55 @@
|
|
1
|
-
|
1
|
+
require 'json'
|
2
2
|
|
3
3
|
module WorkingTimes
|
4
4
|
module Config
|
5
5
|
private
|
6
6
|
|
7
|
-
# return where data directory is
|
8
7
|
def data_dir
|
9
|
-
File.expand_path(
|
8
|
+
File.expand_path('.')
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def path_wtconf
|
12
|
+
File.join(data_dir, 'wtconf.json')
|
13
|
+
end
|
14
|
+
|
15
|
+
def term_dir
|
16
|
+
File.join(data_dir, 'terms')
|
17
|
+
end
|
18
|
+
|
19
|
+
def path_working_flag
|
20
|
+
File.join(data_dir, '.working')
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_term
|
24
|
+
wtconf['term']
|
25
|
+
end
|
26
|
+
|
27
|
+
def path_current_term
|
28
|
+
File.join(term_dir, current_term)
|
29
|
+
end
|
30
|
+
|
31
|
+
def current_company
|
32
|
+
wtconf['company']
|
33
|
+
end
|
34
|
+
|
35
|
+
def invoice_dir
|
36
|
+
File.join(data_dir, 'invoices')
|
37
|
+
end
|
38
|
+
|
39
|
+
def invoice_info
|
40
|
+
wtconf['invoice']
|
41
|
+
end
|
42
|
+
|
43
|
+
def dir_invoice_current_term
|
44
|
+
File.join(invoice_dir, current_term)
|
45
|
+
end
|
46
|
+
|
47
|
+
def path_invoice_current_term
|
48
|
+
File.join(dir_invoice_current_term, "#{current_term}.tex")
|
15
49
|
end
|
16
50
|
|
17
|
-
# parse ~/.wtconf
|
18
51
|
def wtconf
|
19
|
-
|
20
|
-
begin
|
21
|
-
File
|
22
|
-
.readlines(File.expand_path('~/.wtconf'))
|
23
|
-
.map(&:chomp)
|
24
|
-
.each do |row|
|
25
|
-
k, v = row.split('=')
|
26
|
-
conf[k] = v
|
27
|
-
end
|
28
|
-
rescue Errno::ENOENT
|
29
|
-
puts '~/.wtconf not found, generated.'
|
30
|
-
generate_wtconf
|
31
|
-
end
|
32
|
-
conf
|
33
|
-
end
|
34
|
-
|
35
|
-
# default configurations of .wtconf
|
36
|
-
def default_conf
|
37
|
-
{ 'DATADIR' => File.expand_path('~/.wt'), 'DEFAULTWORK' => 'default' }
|
38
|
-
end
|
39
|
-
|
40
|
-
# generate configuration file to ~/.wtconf when does not exist
|
41
|
-
def generate_wtconf
|
42
|
-
File.open(File.expand_path('~/.wtconf'), 'w') { |f| f.puts(default_conf.map { |k, v| "#{k}=#{v}" }) }
|
52
|
+
JSON.parse(File.read(path_wtconf))
|
43
53
|
end
|
44
54
|
end
|
45
55
|
end
|
@@ -1,7 +1,5 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module WorkingTimes
|
4
|
-
VERSION = '0.
|
2
|
+
VERSION = '0.7.2'.freeze
|
5
3
|
|
6
4
|
START_MSG = [
|
7
5
|
'Have a nice work!',
|
@@ -12,4 +10,11 @@ module WorkingTimes
|
|
12
10
|
'Great job!',
|
13
11
|
'Time to beer!'
|
14
12
|
].freeze
|
13
|
+
|
14
|
+
SCHEMA = [
|
15
|
+
'started_at', # DateTime#rfc3339
|
16
|
+
'finished_at', # DateTime#rfc3339
|
17
|
+
'rest_sec', # Integer (inidicates second)
|
18
|
+
'comment' # String
|
19
|
+
].freeze
|
15
20
|
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module WorkingTimes
|
2
|
+
# Class about creating invoice
|
3
|
+
# This class is designed to build data_dir/invoices/current_term/invoice.tex
|
4
|
+
# from data_dir/invoices/template.tex
|
5
|
+
class Invoice
|
6
|
+
include Config
|
7
|
+
attr_reader :path_template, :salary_per_hour, :tax_rate, :company
|
8
|
+
|
9
|
+
WDAYS = %w[日 月 火 水 木 金 土].freeze
|
10
|
+
Date::DATE_FORMATS[:jp_date] = '%m月%d日'
|
11
|
+
Time::DATE_FORMATS[:only_hm] = '%H:%M'
|
12
|
+
|
13
|
+
# path_template : String
|
14
|
+
# salary_per_hour : Integer
|
15
|
+
# tax_rate : Float
|
16
|
+
# company : String
|
17
|
+
def initialize
|
18
|
+
h_invoice_info = invoice_info
|
19
|
+
|
20
|
+
@path_template = h_invoice_info['template']
|
21
|
+
@salary_per_hour = h_invoice_info['salaryPerHour']
|
22
|
+
@tax_rate = h_invoice_info['taxRate']
|
23
|
+
@company = h_invoice_info['company']
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate
|
27
|
+
create_dir_invoice_current_term
|
28
|
+
makeup_worktable
|
29
|
+
generate_invoice_from_template
|
30
|
+
end
|
31
|
+
|
32
|
+
def build
|
33
|
+
puts 'Currently, it is not available to build pdf with latexmk.'
|
34
|
+
puts 'Wait for new version!'
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def create_dir_invoice_current_term
|
40
|
+
FileUtils.mkdir_p(dir_invoice_current_term)
|
41
|
+
end
|
42
|
+
|
43
|
+
def makeup_worktable
|
44
|
+
@worktable = [
|
45
|
+
'\hline',
|
46
|
+
'日付 & 曜日 & 内容 & 出勤 & 退勤 & 休憩 & 労働時間 \\\\ \hline\hline'
|
47
|
+
]
|
48
|
+
@allworktime_on_sec = 0.0
|
49
|
+
working_times = CSV.open(path_current_term, headers: true)
|
50
|
+
row = working_times.first
|
51
|
+
date_itr = beginning_of_month(row['started_at'])
|
52
|
+
date_itr.upto(date_itr.end_of_month) do |date|
|
53
|
+
if row.nil?
|
54
|
+
@worktable << format_worktable_row(date)
|
55
|
+
elsif same_day?(row['started_at'], date.rfc3339)
|
56
|
+
worktime = calculate_worktime(row['started_at'], row['finished_at'], row['rest_sec'])
|
57
|
+
@allworktime_on_sec += worktime
|
58
|
+
@worktable <<
|
59
|
+
format_worktable_row(date, row['comment'], row['started_at'], row['finished_at'], row['rest_sec'], worktime)
|
60
|
+
row = working_times.readline
|
61
|
+
else
|
62
|
+
@worktable << format_worktable_row(date)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_invoice_from_template
|
68
|
+
template = File.readlines(path_template)
|
69
|
+
File.open(path_invoice_current_term, 'w') do |f|
|
70
|
+
template.each do |t|
|
71
|
+
t.gsub!(/##COMPANY##/, company)
|
72
|
+
t.gsub!(/##WORKTIME##/, parse_second_to_hh_str(@allworktime_on_sec))
|
73
|
+
t.gsub!(/##ACTUALWORKTIME##/, parse_second_to_hm_str(@allworktime_on_sec))
|
74
|
+
t.gsub!(/##SALARYPERHOUR##/, salary_per_hour.to_s)
|
75
|
+
t.gsub!(/##SALARY##/, salary.to_s)
|
76
|
+
t.gsub!(/##TAXRATE##/, "#{(tax_rate * 100).to_i}\\%")
|
77
|
+
t.gsub!(/##TAX##/, tax.to_s)
|
78
|
+
t.gsub!(/##SALARYWITHTAX##/, (salary + tax).to_s)
|
79
|
+
# on gsub, '\' means 'replace sub string'.
|
80
|
+
# so we should use block if work as expected
|
81
|
+
t.gsub!(/##WORKTABLE##/) { @worktable.join("\n") }
|
82
|
+
|
83
|
+
f.write(t)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def beginning_of_month(rfc3339)
|
89
|
+
Date.parse(rfc3339).beginning_of_month
|
90
|
+
end
|
91
|
+
|
92
|
+
def same_day?(one_rfc3339, another_rfc3339)
|
93
|
+
Date.parse(one_rfc3339) == Date.parse(another_rfc3339)
|
94
|
+
end
|
95
|
+
|
96
|
+
def calculate_worktime(st_rfc3339, fi_rfc3339, rest_sec)
|
97
|
+
Time.parse(fi_rfc3339) - Time.parse(st_rfc3339) - rest_sec.to_i
|
98
|
+
end
|
99
|
+
|
100
|
+
# date : Date
|
101
|
+
# comment : String
|
102
|
+
# started_at, finished_at : String (RFC3339)
|
103
|
+
# rest, worktime : Integer
|
104
|
+
def format_worktable_row(date, comment = nil, started_at = nil, finished_at = nil, rest = nil, worktime = nil)
|
105
|
+
"#{date.to_s(:jp_date)} & " \
|
106
|
+
"#{WDAYS[date.wday]} & " \
|
107
|
+
"#{comment || '-'} & " \
|
108
|
+
"#{started_at.nil? ? '-' : Time.parse(started_at).to_s(:only_hm)} & " \
|
109
|
+
"#{finished_at.nil? ? '-' : Time.parse(finished_at).to_s(:only_hm)} & " \
|
110
|
+
"#{rest.nil? ? '-' : parse_second_to_hm_str(rest.to_i)} & " \
|
111
|
+
"#{worktime.nil? ? '-' : parse_second_to_hm_str(worktime)} \\\\ \\hline"
|
112
|
+
end
|
113
|
+
|
114
|
+
# second : Float
|
115
|
+
def parse_second_to_hm_str(second)
|
116
|
+
second = second.to_i
|
117
|
+
h = second / 3600
|
118
|
+
m = (second - 3600 * h) / 60
|
119
|
+
"#{h}:#{m.to_s.rjust(2, '0')}"
|
120
|
+
end
|
121
|
+
|
122
|
+
def parse_second_to_hh_str(second)
|
123
|
+
(second / 3600).to_i.to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
# calculate with 'hour' only
|
127
|
+
def salary
|
128
|
+
@salary ||= @allworktime_on_sec.to_i / 3600 * salary_per_hour
|
129
|
+
end
|
130
|
+
|
131
|
+
def tax
|
132
|
+
@tax ||= (salary * tax_rate).to_i
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/working_times/record.rb
CHANGED
@@ -1,57 +1,62 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require 'active_support/time'
|
2
|
+
require 'csv'
|
4
3
|
|
5
4
|
module WorkingTimes
|
6
5
|
class Record
|
7
6
|
include State
|
8
7
|
|
9
|
-
|
8
|
+
OPTIONS = { headers: true, return_headers: true, write_headers: true }.freeze
|
9
|
+
|
10
|
+
attr_reader :timestamp, :comment, :duration
|
10
11
|
|
11
|
-
def initialize(timestamp:, comment: nil, duration: nil
|
12
|
+
def initialize(timestamp:, comment: nil, duration: nil)
|
12
13
|
@timestamp = timestamp
|
13
14
|
@comment = comment
|
14
15
|
@duration = duration
|
15
|
-
@work_on = work_on.nil? ? default_work : work_on
|
16
16
|
end
|
17
17
|
|
18
18
|
def start
|
19
|
-
|
20
|
-
|
19
|
+
CSV.open(path_current_term, 'a+', OPTIONS) do |csv|
|
20
|
+
csv.puts([timestamp.rfc3339, '', 0, comment])
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
def finish
|
25
|
-
|
26
|
-
|
25
|
+
updated_csv = ''
|
26
|
+
CSV.filter(File.open(path_current_term), updated_csv, OPTIONS) do |row|
|
27
|
+
next if row.header_row?
|
28
|
+
next unless row['finished_at'].empty?
|
29
|
+
|
30
|
+
row['finished_at'] = timestamp.rfc3339
|
31
|
+
row['comment'] = comment
|
27
32
|
end
|
33
|
+
File.write(path_current_term, updated_csv)
|
28
34
|
end
|
29
35
|
|
30
36
|
def rest
|
31
|
-
|
32
|
-
File.open("#{data_dir}/#{current_work}", 'a+') do |f|
|
33
|
-
f.puts "#{timestamp.rfc3339},#{@finished_at.rfc3339},#{comment},rest"
|
34
|
-
end
|
37
|
+
parse_rest_sec
|
35
38
|
|
36
|
-
|
39
|
+
updated_csv = ''
|
40
|
+
CSV.filter(File.open(path_current_term), updated_csv, OPTIONS) do |row|
|
41
|
+
next if row.header_row?
|
42
|
+
next unless row['finished_at'].empty?
|
43
|
+
|
44
|
+
row['rest_sec'] = @rest_sec
|
45
|
+
end
|
46
|
+
File.write(path_current_term, updated_csv)
|
37
47
|
end
|
38
48
|
|
39
49
|
private
|
40
50
|
|
41
|
-
def
|
42
|
-
@
|
51
|
+
def parse_rest_sec
|
52
|
+
@rest_sec = 0
|
43
53
|
if /(?<hour>\d+)\s*h/ =~ duration
|
44
|
-
@
|
54
|
+
@rest_sec += hour.to_i * 3600
|
45
55
|
end
|
46
56
|
|
47
57
|
if /(?<minute>\d+)\s*m/ =~ duration
|
48
|
-
@
|
58
|
+
@rest_sec += minute.to_i * 60
|
49
59
|
end
|
50
60
|
end
|
51
|
-
|
52
|
-
def show_rest_msg
|
53
|
-
Time::DATE_FORMATS[:rest_finished_at] = '%H:%M:%S'
|
54
|
-
puts "You can rest until #{@finished_at.to_s(:rest_finished_at)}."
|
55
|
-
end
|
56
61
|
end
|
57
62
|
end
|
data/lib/working_times/state.rb
CHANGED
@@ -1,46 +1,37 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module WorkingTimes
|
4
2
|
module State
|
5
3
|
private
|
6
4
|
|
7
5
|
include Config
|
8
6
|
|
9
|
-
# generate data directory when does not exist
|
10
|
-
# it is usually called by 'start' command
|
11
|
-
def initialize_data_dir
|
12
|
-
return if exist_data_dir?
|
13
|
-
|
14
|
-
puts 'data directory .wt not found, generated.'
|
15
|
-
Dir.mkdir(data_dir)
|
16
|
-
end
|
17
|
-
|
18
|
-
def exist_data_dir?
|
19
|
-
File.exist?(data_dir)
|
20
|
-
end
|
21
|
-
|
22
7
|
def working?
|
23
|
-
File.exist?(
|
8
|
+
File.exist?(path_working_flag)
|
24
9
|
end
|
25
10
|
|
26
11
|
# return what kind of working on
|
27
12
|
def current_work
|
28
|
-
File.readlines(
|
13
|
+
File.readlines(path_working_flag).last.chomp
|
29
14
|
end
|
30
15
|
|
31
|
-
|
32
|
-
|
33
|
-
def start_work(work_on)
|
34
|
-
work_on = work_on.nil? ? default_work : work_on
|
35
|
-
File.open("#{data_dir}/.working", 'w+') { |f| f.puts work_on }
|
16
|
+
def start_work
|
17
|
+
File.write(path_working_flag, current_term)
|
36
18
|
puts START_MSG.sample
|
37
19
|
end
|
38
20
|
|
39
|
-
# delete 'working' flag
|
40
|
-
# and show 'finished' message
|
41
21
|
def finish_work
|
42
|
-
|
22
|
+
puts "You were working about #{worked_time}."
|
23
|
+
File.delete(path_working_flag)
|
43
24
|
puts FINISH_MSG.sample
|
44
25
|
end
|
26
|
+
|
27
|
+
def worked_time
|
28
|
+
last_record = CSV.read(path_current_term).last
|
29
|
+
started_at = Time.parse(last_record[0])
|
30
|
+
finished_at = Time.parse(last_record[1])
|
31
|
+
duration = (finished_at - started_at).to_i
|
32
|
+
hour = duration / 3600
|
33
|
+
min = (duration - 3600 * hour) / 60
|
34
|
+
"#{hour.to_s.rjust(2, '0')} hour #{min.to_s.rjust(2, '0')} min"
|
35
|
+
end
|
45
36
|
end
|
46
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: working_times
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aoshi Fujioka
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 5.2.4.3
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 5.2.4.3
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thor
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,28 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1
|
47
|
+
version: '2.1'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '1
|
54
|
+
version: '2.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 12.3.3
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 12.3.3
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
description: Store your working/worked time simply. This gem gives simple CLI tool.
|
98
126
|
email:
|
99
127
|
- blue20will@gmail.com
|
@@ -107,6 +135,7 @@ files:
|
|
107
135
|
- lib/working_times/cli.rb
|
108
136
|
- lib/working_times/config.rb
|
109
137
|
- lib/working_times/constants.rb
|
138
|
+
- lib/working_times/invoice.rb
|
110
139
|
- lib/working_times/record.rb
|
111
140
|
- lib/working_times/state.rb
|
112
141
|
homepage: https://github.com/arsley/working_times
|