dovico 1.0.0 → 1.1.0
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/.travis.yml +13 -0
- data/CHANGELOG.md +12 -0
- data/Dockerfile +3 -0
- data/LICENSE.md +21 -0
- data/README.md +1 -3
- data/dovico-client.gemspec +3 -1
- data/lib/dovico.rb +5 -0
- data/lib/dovico/app.rb +24 -43
- data/lib/dovico/config_parser.rb +51 -0
- data/lib/dovico/model/employee.rb +6 -0
- data/lib/dovico/model/project.rb +27 -0
- data/lib/dovico/model/time_entry.rb +30 -0
- data/lib/dovico/model/time_entry_formatter.rb +41 -0
- data/lib/dovico/model/time_entry_generator.rb +0 -2
- data/lib/dovico/version.rb +1 -1
- data/spec/helper.rb +1 -0
- data/spec/unit/dovico/config_parser_spec.rb +99 -0
- data/spec/unit/dovico/model/employee_spec.rb +10 -0
- data/spec/unit/dovico/model/project_spec.rb +21 -0
- data/spec/unit/dovico/model/time_entry_formatter_spec.rb +28 -0
- data/spec/unit/dovico/model/time_entry_spec.rb +67 -0
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6d0fc89e13ae40ce8fba111ea73420cb03dced3
|
4
|
+
data.tar.gz: 2e41cc97b937deb844a8d6da1c24eb3e3f2d3483
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44898ec1528b4f6e4c40cba7d2e44ff3b6b8101cc6b00b39ff5736e80ac87dd6fb0853b459fb8c34e56c8e2068479e4401da83ff3a547447c65b9feebdd9d64a
|
7
|
+
data.tar.gz: 60fa2fd23b39d6a76ed0279a655efce636b3406aafefdfb8b6a04bd1b410190af5610b6b5d383d8a58065aa8c07298571e3549f01708b9d275a8b5948301942e
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Next version
|
2
|
+
|
3
|
+
# Version 1.1.0
|
4
|
+
- Remove `bin/console` from the Gem
|
5
|
+
- Add a ConfigParser and extract code into models
|
6
|
+
- Update Gem metadata
|
7
|
+
- Specify ruby 2.2 as minimum ruby version for the gem
|
8
|
+
- Add --show option to print TimeEntries registered
|
9
|
+
- Add --start=2017-01-31 --end=2017-02-10 options for date options. Beware: it includes Saturdays and Sundays
|
10
|
+
|
11
|
+
# Version 1.0.0
|
12
|
+
- Initial release
|
data/Dockerfile
CHANGED
@@ -17,6 +17,9 @@ COPY ./dovico-client.gemspec /home/dovico/dovico-client.gemspec
|
|
17
17
|
COPY ./lib/dovico/version.rb /home/dovico/lib/dovico/version.rb
|
18
18
|
COPY ./Gemfile /home/dovico/Gemfile
|
19
19
|
|
20
|
+
# Ensure UTF8 strings can be used
|
21
|
+
ENV LANG C.UTF-8
|
22
|
+
|
20
23
|
# Bundle
|
21
24
|
RUN bundle install
|
22
25
|
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Trainline.com Ltd
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
[](https://scm.capitainetrain.com/capitainetrain/dovico-client/commits/master)
|
1
|
+
[](https://travis-ci.org/trainline-eu/dovico)
|
3
2
|
|
4
3
|
Repository for Dovico API management.
|
5
4
|
|
@@ -97,7 +96,6 @@ Year can be set too:
|
|
97
96
|
`make day DAY=2017-12-31`
|
98
97
|
|
99
98
|
# Restrictions and known issues
|
100
|
-
* The timesheet are currently created, but not submitted. You still need to login and submit your timesheet
|
101
99
|
* The client can't edit already created timesheets for now.
|
102
100
|
|
103
101
|
You are warmly welcome to contribute to the project!
|
data/dovico-client.gemspec
CHANGED
@@ -12,11 +12,13 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = %q(Simple client & tools for http://www.dovico.com/.)
|
13
13
|
s.description = %q(Simple client & tools for http://www.dovico.com/.)
|
14
14
|
|
15
|
-
s.files = `git ls-files`.split("\n")
|
15
|
+
s.files = `git ls-files`.split("\n") - ['bin/console']
|
16
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
18
18
|
s.require_paths = ['lib']
|
19
19
|
|
20
|
+
s.required_ruby_version = '>= 2.2.2'
|
21
|
+
|
20
22
|
s.add_dependency 'easy_app_helper'
|
21
23
|
s.add_dependency 'active_attr'
|
22
24
|
s.add_dependency 'typhoeus'
|
data/lib/dovico.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
|
1
4
|
require 'dovico/version'
|
2
5
|
require 'dovico/api_client'
|
3
6
|
require 'dovico/app'
|
7
|
+
require 'dovico/config_parser'
|
4
8
|
require 'dovico/model/assignment'
|
9
|
+
require 'dovico/model/time_entry_formatter'
|
5
10
|
require 'dovico/model/time_entry_generator'
|
6
11
|
require 'dovico/model/employee'
|
7
12
|
require 'dovico/model/project'
|
data/lib/dovico/app.rb
CHANGED
@@ -29,22 +29,30 @@ EOL
|
|
29
29
|
slop.on :tasks, 'Display info on tasks', argument: false
|
30
30
|
end
|
31
31
|
config.add_command_line_section('Fill the timesheets') do |slop|
|
32
|
-
slop.on :fill, 'Fill the timesheet',
|
32
|
+
slop.on :fill, 'Fill the timesheet', argument: false
|
33
|
+
end
|
34
|
+
config.add_command_line_section('Show the timesheets') do |slop|
|
35
|
+
slop.on :show, 'Show the filled timesheets', argument: false
|
33
36
|
end
|
34
37
|
config.add_command_line_section('Submit the timesheets') do |slop|
|
35
|
-
slop.on :submit, 'Submit timesheets',
|
38
|
+
slop.on :submit, 'Submit timesheets', argument: false
|
36
39
|
end
|
37
|
-
config.add_command_line_section('Date options (for --fill and --submit)') do |slop|
|
40
|
+
config.add_command_line_section('Date options (required for --show, --fill and --submit)') do |slop|
|
38
41
|
slop.on :current_week, 'Current week', argument: false
|
39
42
|
slop.on :today, 'Current day', argument: false
|
40
43
|
slop.on :day, 'Specific day', argument: true
|
44
|
+
slop.on :start, 'Specific start day', argument: true
|
45
|
+
slop.on :end, 'Specific end day', argument: true
|
41
46
|
slop.on :week, 'Specific "commercial" week. See https://www.epochconverter.com/weeks/', argument: true, as: Integer
|
42
47
|
slop.on :year, '[optional] Specifiy year (for --week option), default current year', argument: true, as: Integer
|
43
48
|
end
|
44
49
|
end
|
45
50
|
|
46
51
|
def run
|
47
|
-
|
52
|
+
settings = ConfigParser.new(config)
|
53
|
+
start_date, end_date = settings.date_options
|
54
|
+
|
55
|
+
if settings.needs_help?
|
48
56
|
display_help
|
49
57
|
exit 0
|
50
58
|
end
|
@@ -57,16 +65,15 @@ EOL
|
|
57
65
|
display_tasks
|
58
66
|
end
|
59
67
|
|
60
|
-
if config[:
|
61
|
-
start_date, end_date
|
68
|
+
if config[:show]
|
69
|
+
display_time_entries(start_date, end_date)
|
70
|
+
end
|
62
71
|
|
72
|
+
if config[:fill]
|
63
73
|
time_entry_generator = TimeEntryGenerator.new(
|
64
74
|
assignments: config["assignments"],
|
65
75
|
employee_id: myself.id,
|
66
76
|
)
|
67
|
-
end
|
68
|
-
|
69
|
-
if config[:fill]
|
70
77
|
time_entries = time_entry_generator.generate(start_date, end_date)
|
71
78
|
|
72
79
|
saved_time_entries = TimeEntry.batch_create!(time_entries)
|
@@ -87,48 +94,22 @@ EOL
|
|
87
94
|
|
88
95
|
def display_myself
|
89
96
|
puts "Informations about yourself"
|
90
|
-
puts
|
91
|
-
puts " - First Name: #{myself.first_name}"
|
92
|
-
puts " - Last Name: #{myself.last_name}"
|
97
|
+
puts myself
|
93
98
|
puts ""
|
94
99
|
end
|
95
100
|
|
96
101
|
def display_tasks
|
97
|
-
projects = Project.all
|
98
|
-
|
99
102
|
puts "== List of available projects =="
|
100
|
-
puts
|
101
|
-
projects.each do |project|
|
102
|
-
if project.tasks.count > 0
|
103
|
-
project.tasks.each do |task|
|
104
|
-
puts sprintf ' %7d | %4d | %s: %s', project.id, task.id, project.name, task.name
|
105
|
-
end
|
106
|
-
else
|
107
|
-
puts sprintf " %7d | | %s (No tasks linked)", project.id, task.name
|
108
|
-
end
|
109
|
-
end
|
103
|
+
puts Project.format_all
|
110
104
|
puts ""
|
111
105
|
end
|
112
106
|
|
113
|
-
def
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
start_date = Date.current.beginning_of_week
|
120
|
-
end_date = start_date.advance(days: 4)
|
121
|
-
elsif config[:day]
|
122
|
-
start_date = end_date = Date.parse(config[:day])
|
123
|
-
elsif config[:today]
|
124
|
-
start_date = end_date = Date.current
|
125
|
-
else
|
126
|
-
puts "Error : You must precise one date options"
|
127
|
-
display_help
|
128
|
-
exit 1
|
129
|
-
end
|
130
|
-
|
131
|
-
[start_date, end_date]
|
107
|
+
def display_time_entries(start_date, end_date)
|
108
|
+
puts "== List of Time Entries between #{start_date} and #{end_date} =="
|
109
|
+
formatter = TimeEntryFormatter.new(Project.all)
|
110
|
+
time_entries = TimeEntry.search(start_date, end_date)
|
111
|
+
puts formatter.format_entries(time_entries)
|
112
|
+
puts ""
|
132
113
|
end
|
133
114
|
|
134
115
|
def display_help
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Dovico
|
2
|
+
class ConfigParser
|
3
|
+
AVAILABLE_ACTIONS = [:myself, :tasks, :show, :fill, :submit]
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
@start_date, @end_date = parse_date_options
|
8
|
+
end
|
9
|
+
|
10
|
+
def needs_help?
|
11
|
+
if config[:help]
|
12
|
+
true
|
13
|
+
elsif AVAILABLE_ACTIONS.map{|action| config[action] }.compact.empty?
|
14
|
+
true
|
15
|
+
elsif (config[:fill] || config[:submit]) && !(@start_date && @end_date)
|
16
|
+
true
|
17
|
+
else
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def date_options
|
23
|
+
[start_date, end_date]
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
attr_accessor :config, :start_date, :end_date
|
28
|
+
|
29
|
+
def parse_date_options
|
30
|
+
start_date, end_date = nil
|
31
|
+
|
32
|
+
if config[:week]
|
33
|
+
year = config[:year] || Date.current.year
|
34
|
+
start_date = Date.commercial(year, config[:week]).beginning_of_week
|
35
|
+
end_date = start_date.advance(days: 4)
|
36
|
+
elsif config[:current_week]
|
37
|
+
start_date = Date.current.beginning_of_week
|
38
|
+
end_date = start_date.advance(days: 4)
|
39
|
+
elsif config[:day]
|
40
|
+
start_date = end_date = Date.parse(config[:day])
|
41
|
+
elsif config[:today]
|
42
|
+
start_date = end_date = Date.current
|
43
|
+
elsif config[:start] && config[:end]
|
44
|
+
start_date = Date.parse(config[:start])
|
45
|
+
end_date = Date.parse(config[:end])
|
46
|
+
end
|
47
|
+
|
48
|
+
[start_date, end_date]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/dovico/model/project.rb
CHANGED
@@ -5,6 +5,12 @@ module Dovico
|
|
5
5
|
|
6
6
|
attribute :tasks
|
7
7
|
|
8
|
+
def self.parse(hash)
|
9
|
+
project = super(hash)
|
10
|
+
project.tasks ||= []
|
11
|
+
project
|
12
|
+
end
|
13
|
+
|
8
14
|
def self.all
|
9
15
|
projects_search = ApiClient.get(URL_PATH)
|
10
16
|
projects = projects_search["Assignments"].map {|project_hash| parse(project_hash) }
|
@@ -13,6 +19,27 @@ module Dovico
|
|
13
19
|
tasks_search = ApiClient.get("#{URL_PATH}#{project.assignement_id}")
|
14
20
|
project.tasks = tasks_search["Assignments"].map {|task_hash| Task.parse(task_hash) }
|
15
21
|
end
|
22
|
+
|
23
|
+
projects
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.format_all
|
27
|
+
text = " Project | Task | Description"
|
28
|
+
text += all.map(&:to_s).join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
text = ''
|
33
|
+
|
34
|
+
if tasks.count > 0
|
35
|
+
tasks.each do |task|
|
36
|
+
text += sprintf ' %7d | %4d | %s: %s', id, task.id, name, task.name
|
37
|
+
end
|
38
|
+
else
|
39
|
+
text += sprintf " %7d | | %s (No tasks linked)", id, name
|
40
|
+
end
|
41
|
+
|
42
|
+
text
|
16
43
|
end
|
17
44
|
end
|
18
45
|
end
|
@@ -12,6 +12,8 @@ module Dovico
|
|
12
12
|
attribute :project_id
|
13
13
|
attribute :task_id
|
14
14
|
attribute :employee_id
|
15
|
+
attribute :sheet_id
|
16
|
+
attribute :sheet_status
|
15
17
|
attribute :date
|
16
18
|
attribute :total_hours
|
17
19
|
attribute :description
|
@@ -24,6 +26,8 @@ module Dovico
|
|
24
26
|
project_id: hash['Project']['ID'],
|
25
27
|
task_id: hash['Task']['ID'],
|
26
28
|
employee_id:hash['Employee']['ID'],
|
29
|
+
sheet_id: hash['Sheet']['ID'],
|
30
|
+
sheet_status: hash['Sheet']['Status'],
|
27
31
|
date: hash['Date'],
|
28
32
|
total_hours:hash['TotalHours'],
|
29
33
|
description:hash['Description']
|
@@ -35,6 +39,19 @@ module Dovico
|
|
35
39
|
TimeEntry.parse(entry)
|
36
40
|
end
|
37
41
|
|
42
|
+
def self.search(start_date, end_date)
|
43
|
+
api_response = ApiClient.get(
|
44
|
+
"#{URL_PATH}",
|
45
|
+
params: {
|
46
|
+
daterange: "#{start_date} #{end_date}"
|
47
|
+
},
|
48
|
+
)
|
49
|
+
|
50
|
+
api_response["TimeEntries"].map do |time_entry|
|
51
|
+
TimeEntry.parse(time_entry)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
38
55
|
def self.batch_create!(assignments)
|
39
56
|
api_assignements = assignments.map(&:to_api)
|
40
57
|
ApiClient.post(URL_PATH, body: api_assignements.to_json)
|
@@ -72,6 +89,19 @@ module Dovico
|
|
72
89
|
}.compact.stringify_keys
|
73
90
|
end
|
74
91
|
|
92
|
+
def formal_sheet_status
|
93
|
+
case sheet_status
|
94
|
+
when "N"
|
95
|
+
:not_submitted
|
96
|
+
when "A"
|
97
|
+
:approved
|
98
|
+
when "U"
|
99
|
+
:under_review
|
100
|
+
when "R"
|
101
|
+
:rejected
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
75
105
|
private
|
76
106
|
|
77
107
|
def self.parse_id(long_id)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Dovico
|
2
|
+
class TimeEntryFormatter
|
3
|
+
|
4
|
+
def initialize(projects)
|
5
|
+
@projects = projects
|
6
|
+
end
|
7
|
+
|
8
|
+
def format_entries(time_entries)
|
9
|
+
text = ""
|
10
|
+
time_entries.map do |time_entry|
|
11
|
+
text += "#{}"
|
12
|
+
time_entry_text(time_entry)
|
13
|
+
end.join("\n")
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
attr_accessor :projects
|
18
|
+
|
19
|
+
def time_entry_text(time_entry)
|
20
|
+
project, task = project_task(time_entry.project_id, time_entry.task_id)
|
21
|
+
|
22
|
+
progress_bar_width = (time_entry.total_hours.to_f * 2).to_i
|
23
|
+
sprintf("%s [%s] %s : [%8s] %2sh %s %s",
|
24
|
+
time_entry.date,
|
25
|
+
"×" * progress_bar_width,
|
26
|
+
" " * [16 - progress_bar_width, 0].max,
|
27
|
+
time_entry.formal_sheet_status,
|
28
|
+
time_entry.total_hours,
|
29
|
+
project.name,
|
30
|
+
task.name,
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def project_task(project_id, task_id)
|
35
|
+
project = projects.select{ |project| project.id == project_id }.first
|
36
|
+
task = project.tasks.select{ |task| task.id == task_id }.first
|
37
|
+
|
38
|
+
[project, task]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/dovico/version.rb
CHANGED
data/spec/helper.rb
CHANGED
@@ -0,0 +1,99 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
module Dovico
|
4
|
+
describe Dovico::ConfigParser do
|
5
|
+
let(:config) { {} }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
Dovico::ConfigParser.new(config)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#date_options" do
|
12
|
+
context 'with no date options' do
|
13
|
+
let(:config) { {} }
|
14
|
+
|
15
|
+
it 'returns nil, nil' do
|
16
|
+
expect(subject.date_options).to eq([nil, nil])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with week option' do
|
21
|
+
let(:config) { { week: 10, year: 2017 } }
|
22
|
+
|
23
|
+
it 'returns first day of specified week, friday of the week' do
|
24
|
+
expect(subject.date_options).to eq([Date.parse('2017-03-06'), Date.parse('2017-03-10')])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with day options' do
|
29
|
+
let(:config) { { day: '2017-10-12' } }
|
30
|
+
|
31
|
+
it 'returns specified date twice' do
|
32
|
+
expect(subject.date_options).to eq([Date.parse('2017-10-12'), Date.parse('2017-10-12')])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with current_week options' do
|
37
|
+
let(:config) { { current_week: true } }
|
38
|
+
|
39
|
+
it 'returns monday, friday of the current week' do
|
40
|
+
Timecop.freeze(Date.parse('2017-10-12')) do
|
41
|
+
expect(subject.date_options).to eq([Date.parse('2017-10-09'), Date.parse('2017-10-13')])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with start and end options' do
|
46
|
+
let(:config) { { start: '2017-10-12', end: '2017-12-13' } }
|
47
|
+
|
48
|
+
it 'returns the provided dates' do
|
49
|
+
expect(subject.date_options).to eq([Date.parse('2017-10-12'), Date.parse('2017-12-13')])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with today options' do
|
55
|
+
let(:config) { { today: true } }
|
56
|
+
|
57
|
+
it 'returns current day twice' do
|
58
|
+
Timecop.freeze(Date.parse('2017-10-22')) do
|
59
|
+
expect(subject.date_options).to eq([Date.parse('2017-10-22'), Date.parse('2017-10-22')])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#needs_help?' do
|
66
|
+
context 'with no config options' do
|
67
|
+
let(:config) { {} }
|
68
|
+
|
69
|
+
it 'returns true' do
|
70
|
+
expect(subject.needs_help?).to be true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'with --help' do
|
75
|
+
let(:config) { { help: true } }
|
76
|
+
|
77
|
+
it 'returns true' do
|
78
|
+
expect(subject.needs_help?).to be true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'with --fill and not date options' do
|
83
|
+
let(:config) { { fill: true } }
|
84
|
+
|
85
|
+
it 'returns true' do
|
86
|
+
expect(subject.needs_help?).to be true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'with --fill and date options' do
|
91
|
+
let(:config) { { fill: true, week: 42 } }
|
92
|
+
|
93
|
+
it 'returns false' do
|
94
|
+
expect(subject.needs_help?).to be false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -10,6 +10,10 @@ module Dovico
|
|
10
10
|
}.stringify_keys
|
11
11
|
end
|
12
12
|
|
13
|
+
subject do
|
14
|
+
Dovico::Employee.parse(employee_api_hash)
|
15
|
+
end
|
16
|
+
|
13
17
|
describe ".parse" do
|
14
18
|
it "parses the hash" do
|
15
19
|
employee = Dovico::Employee.parse(employee_api_hash)
|
@@ -40,5 +44,11 @@ module Dovico
|
|
40
44
|
expect(myself.id).to eq('123')
|
41
45
|
end
|
42
46
|
end
|
47
|
+
|
48
|
+
describe '#to_s' do
|
49
|
+
it 'returns object with formatted text' do
|
50
|
+
expect(subject.to_s).to eq(" - ID: 123\n - First Name: James\n - Last Name: Bond")
|
51
|
+
end
|
52
|
+
end
|
43
53
|
end
|
44
54
|
end
|
@@ -2,6 +2,10 @@ require "helper"
|
|
2
2
|
|
3
3
|
module Dovico
|
4
4
|
describe Dovico::Project do
|
5
|
+
subject do
|
6
|
+
Dovico::Project.parse(project_api_hash)
|
7
|
+
end
|
8
|
+
|
5
9
|
let(:project_api_hash) do
|
6
10
|
{
|
7
11
|
"ItemID": "123",
|
@@ -52,5 +56,22 @@ module Dovico
|
|
52
56
|
expect(task.name).to eq('Task write specs')
|
53
57
|
end
|
54
58
|
end
|
59
|
+
|
60
|
+
describe ".format_all" do
|
61
|
+
before do
|
62
|
+
allow(ApiClient).to receive(:get).with(Dovico::Project::URL_PATH).and_return(projects_api_hash)
|
63
|
+
allow(ApiClient).to receive(:get).with("#{Dovico::Project::URL_PATH}T456").and_return(tasks_api_hash)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'returns projects with formatted text' do
|
67
|
+
expect(Dovico::Project.format_all).to eq(" Project | Task | Description 123 | 789 | Project Dovico API Client: Task write specs")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#to_s' do
|
72
|
+
it 'returns object with formatted text' do
|
73
|
+
expect(subject.to_s).to eq(" 123 | | Project Dovico API Client (No tasks linked)")
|
74
|
+
end
|
75
|
+
end
|
55
76
|
end
|
56
77
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
module Dovico
|
4
|
+
describe Dovico::TimeEntryFormatter do
|
5
|
+
let(:task) { Dovico::Task.new(id: "1212", name: "TestTask") }
|
6
|
+
let(:project) { Dovico::Project.new(id: "9898", name: "TestProject", tasks: [task]) }
|
7
|
+
let(:time_entry) do
|
8
|
+
Dovico::TimeEntry.new(
|
9
|
+
project_id: "9898",
|
10
|
+
task_id: "1212",
|
11
|
+
start_time: "0900",
|
12
|
+
stop_time: "1200",
|
13
|
+
total_hours: "3",
|
14
|
+
sheet_status: "U"
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
subject do
|
19
|
+
Dovico::TimeEntryFormatter.new([project])
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#format_entries" do
|
23
|
+
it 'returns formatted tasks' do
|
24
|
+
expect(subject.format_entries([time_entry])).to eq(' [××××××] : [under_review] 3h TestProject TestTask')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -20,6 +20,13 @@ module Dovico
|
|
20
20
|
"ID": "333"
|
21
21
|
}.stringify_keys
|
22
22
|
end
|
23
|
+
let(:sheet_status) { "U" }
|
24
|
+
let(:sheet_hash) do
|
25
|
+
{
|
26
|
+
"ID": "444",
|
27
|
+
"Status": sheet_status,
|
28
|
+
}.stringify_keys
|
29
|
+
end
|
23
30
|
let(:time_entry_api_hash) do
|
24
31
|
{
|
25
32
|
"ID": "456",
|
@@ -28,6 +35,7 @@ module Dovico
|
|
28
35
|
"Project": project_hash,
|
29
36
|
"Task": task_hash,
|
30
37
|
"Employee": employee_hash,
|
38
|
+
"Sheet": sheet_hash,
|
31
39
|
"Date": "2017-01-05",
|
32
40
|
"TotalHours": "3",
|
33
41
|
"Description": "Unit test",
|
@@ -42,6 +50,7 @@ module Dovico
|
|
42
50
|
expect(time_entry.start_time).to eq('0800')
|
43
51
|
expect(time_entry.project_id).to eq('111')
|
44
52
|
expect(time_entry.employee_id).to eq('333')
|
53
|
+
expect(time_entry.sheet_id).to eq('444')
|
45
54
|
expect(time_entry.total_hours).to eq('3')
|
46
55
|
end
|
47
56
|
|
@@ -78,6 +87,30 @@ module Dovico
|
|
78
87
|
end
|
79
88
|
end
|
80
89
|
|
90
|
+
describe ".search" do
|
91
|
+
let(:time_entry_list_api) do
|
92
|
+
{
|
93
|
+
"TimeEntries": [ time_entry_api_hash ]
|
94
|
+
}.stringify_keys
|
95
|
+
end
|
96
|
+
|
97
|
+
before do
|
98
|
+
allow(ApiClient).to receive(:get).and_return(time_entry_list_api)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'calls the API and return an TimeEntry object' do
|
102
|
+
time_entries = Dovico::TimeEntry.search(Date.parse('2017-01-10'), Date.parse('2017-01-20'))
|
103
|
+
|
104
|
+
expect(time_entries.count).to eq(1)
|
105
|
+
|
106
|
+
time_entry = time_entries.first
|
107
|
+
|
108
|
+
expect(ApiClient).to have_received(:get).with("#{Dovico::TimeEntry::URL_PATH}", { params: { daterange: "2017-01-10 2017-01-20" } })
|
109
|
+
expect(time_entry).to be_an(Dovico::TimeEntry)
|
110
|
+
expect(time_entry.id).to eq('456')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
81
114
|
describe ".batch_create!" do
|
82
115
|
let(:assignments) do
|
83
116
|
[ subject ]
|
@@ -164,5 +197,39 @@ module Dovico
|
|
164
197
|
)
|
165
198
|
end
|
166
199
|
end
|
200
|
+
|
201
|
+
describe "#formal_sheet_status" do
|
202
|
+
context 'not submitted' do
|
203
|
+
let(:sheet_status) { "N" }
|
204
|
+
|
205
|
+
it 'returns the correct symbol for the status' do
|
206
|
+
expect(subject.formal_sheet_status).to eq(:not_submitted)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'approved' do
|
211
|
+
let(:sheet_status) { "A" }
|
212
|
+
|
213
|
+
it 'returns the correct symbol for the status' do
|
214
|
+
expect(subject.formal_sheet_status).to eq(:approved)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context 'under review' do
|
219
|
+
let(:sheet_status) { "U" }
|
220
|
+
|
221
|
+
it 'returns the correct symbol for the status' do
|
222
|
+
expect(subject.formal_sheet_status).to eq(:under_review)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context 'rejected' do
|
227
|
+
let(:sheet_status) { "R" }
|
228
|
+
|
229
|
+
it 'returns the correct symbol for the status' do
|
230
|
+
expect(subject.formal_sheet_status).to eq(:rejected)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
167
234
|
end
|
168
235
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dovico
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Théophile Helleboid
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-02-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: easy_app_helper
|
@@ -277,8 +277,11 @@ files:
|
|
277
277
|
- ".gitlab-ci.yml"
|
278
278
|
- ".rspec"
|
279
279
|
- ".ruby-version"
|
280
|
+
- ".travis.yml"
|
281
|
+
- CHANGELOG.md
|
280
282
|
- Dockerfile
|
281
283
|
- Gemfile
|
284
|
+
- LICENSE.md
|
282
285
|
- Makefile
|
283
286
|
- README.md
|
284
287
|
- Rakefile
|
@@ -290,19 +293,23 @@ files:
|
|
290
293
|
- lib/dovico.rb
|
291
294
|
- lib/dovico/api_client.rb
|
292
295
|
- lib/dovico/app.rb
|
296
|
+
- lib/dovico/config_parser.rb
|
293
297
|
- lib/dovico/model/assignment.rb
|
294
298
|
- lib/dovico/model/employee.rb
|
295
299
|
- lib/dovico/model/project.rb
|
296
300
|
- lib/dovico/model/task.rb
|
297
301
|
- lib/dovico/model/time_entry.rb
|
302
|
+
- lib/dovico/model/time_entry_formatter.rb
|
298
303
|
- lib/dovico/model/time_entry_generator.rb
|
299
304
|
- lib/dovico/version.rb
|
300
305
|
- spec/helper.rb
|
301
306
|
- spec/unit/dovico/api_client_spec.rb
|
307
|
+
- spec/unit/dovico/config_parser_spec.rb
|
302
308
|
- spec/unit/dovico/model/assignment_spec.rb
|
303
309
|
- spec/unit/dovico/model/employee_spec.rb
|
304
310
|
- spec/unit/dovico/model/project_spec.rb
|
305
311
|
- spec/unit/dovico/model/task_spec.rb
|
312
|
+
- spec/unit/dovico/model/time_entry_formatter_spec.rb
|
306
313
|
- spec/unit/dovico/model/time_entry_generator_spec.rb
|
307
314
|
- spec/unit/dovico/model/time_entry_spec.rb
|
308
315
|
homepage: https://rubygems.org/gems/dovico
|
@@ -317,7 +324,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
317
324
|
requirements:
|
318
325
|
- - ">="
|
319
326
|
- !ruby/object:Gem::Version
|
320
|
-
version:
|
327
|
+
version: 2.2.2
|
321
328
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
322
329
|
requirements:
|
323
330
|
- - ">="
|