synrp 0.16.4

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.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in synrp.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ synrp (0.16.4)
5
+ cri (~> 2.2)
6
+ json
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ cri (2.2.1)
12
+ json (1.6.6)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ synrp!
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/synrp ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Try loading bundler if it's possible
4
+ begin
5
+ require 'rubygems'
6
+ require 'bundler/setup'
7
+ rescue LoadError
8
+ # no problem
9
+ end
10
+
11
+ # Add lib to load path
12
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
13
+
14
+ require 'synrp'
15
+ require 'synrp/cli'
16
+
17
+ Synrp::CLI.run(ARGV)
18
+
data/lib/synrp/cli.rb ADDED
@@ -0,0 +1,190 @@
1
+ require 'cri'
2
+
3
+ module Synrp::CLI
4
+
5
+ synRP = Synrp::SynRP.new
6
+
7
+ @cmd = Cri::Command.define do
8
+ name 'rpt'
9
+ usage 'rpt [options] [command] [options]'
10
+ summary 'to access ressourceplanning via commandline'
11
+ description <<-DESC
12
+ For --site, --username and --passwort parameters you can
13
+ also use a yaml config file.
14
+
15
+ To do so, just
16
+
17
+ cp config.yaml.sample ~/.synRP_config.yaml
18
+
19
+ DESC
20
+
21
+ flag :h, :help, 'show help for this command' do |value, cmd|
22
+ puts @cmd.help
23
+ exit 0
24
+ end
25
+
26
+ required :s, :site, 'domain name of respt system (without http://)'
27
+ required :u, :username, 'username at given site'
28
+ required :p, :password, 'password at given site'
29
+ end
30
+
31
+ @cmd.add_command Cri::Command.new_basic_help
32
+
33
+ @cmd.define_command do
34
+ name 'req'
35
+ aliases :request, :allocation_request
36
+ usage 'req [options]'
37
+ summary 'requests ressources'
38
+
39
+ required :k, :kw, 'yyyy-Wn (e. g. 2012-W6)'
40
+ required :P, :project, 'project id or name'
41
+ required :e, :person, 'person id or display name (find id via "persons")'
42
+ required :m, :minutes, 'request time in minutes'
43
+ required :c, :comment, 'comment to the request'
44
+
45
+ run do |opts, args|
46
+
47
+ synRP.verify_opts_present(opts, [ :site, :username, :password, :kw, :project, :person, :minutes ])
48
+
49
+ synRP.connect(opts[:site], opts[:username], opts[:password])
50
+
51
+ project_id = synRP.find_project_id_by_project_name(opts[:project]) || opts[:project]
52
+ person_id = synRP.find_person_id_by_displayname(opts[:person]) || opts[:person]
53
+
54
+ synRP.request_res(opts[:kw], project_id, person_id, opts[:minutes], opts[:comment])
55
+ end
56
+ end
57
+
58
+ @cmd.define_command do
59
+ name 'availabilities'
60
+ usage 'availabilities [options]'
61
+ summary 'check who is available in given week'
62
+
63
+ required :k, :kw, 'yyyy-Wn (e. g. 2012-W6)'
64
+
65
+ run do |opts, args|
66
+
67
+ synRP.verify_opts_present(opts, [ :site, :username, :password, :kw ])
68
+
69
+ synRP.connect(opts[:site], opts[:username], opts[:password])
70
+
71
+ puts JSON.pretty_generate synRP.get_availabilities_persons(opts[:kw])
72
+ end
73
+ end
74
+
75
+ @cmd.define_command do
76
+ name 'allocation_requests'
77
+ usage 'allocation_requests [options]'
78
+ summary 'get all allocation requests of a given week'
79
+
80
+ required :k, :kw, 'yyyy-Wn (e. g. 2012-W6)'
81
+
82
+ run do |opts, args|
83
+
84
+ synRP.verify_opts_present(opts, [ :site, :username, :password, :kw ])
85
+
86
+ synRP.connect(opts[:site], opts[:username], opts[:password])
87
+
88
+ puts JSON.pretty_generate synRP.get_allocation_requests(opts[:kw])
89
+ end
90
+ end
91
+
92
+ @cmd.define_command do
93
+ name 'remaining_availabilities'
94
+ usage 'remaining_availabilities [options]'
95
+ summary 'remaining_availabilities of a given week'
96
+
97
+ required :k, :kw, 'yyyy-Wn (e. g. 2012-W6)'
98
+
99
+ run do |opts, args|
100
+
101
+ synRP.verify_opts_present(opts, [ :site, :username, :password, :kw ])
102
+
103
+ synRP.connect(opts[:site], opts[:username], opts[:password])
104
+
105
+ puts JSON.pretty_generate synRP.calculate_remaining_availabilities(opts[:kw])
106
+ end
107
+ end
108
+
109
+ @cmd.define_command do
110
+ name 'reqs_of_person'
111
+ usage 'reqs_of_person [options]'
112
+ summary 'get all allocation requests of a given week of a person'
113
+
114
+ required :k, :kw, 'yyyy-Wn (e. g. 2012-W6)'
115
+ required :e, :person, 'person id or display name (find id via "persons")'
116
+
117
+ run do |opts, args|
118
+
119
+ synRP.verify_opts_present(opts, [ :site, :username, :password, :kw, :person ])
120
+
121
+ synRP.connect(opts[:site], opts[:username], opts[:password])
122
+
123
+ person_id = synRP.find_person_id_by_displayname(opts[:person]) || opts[:person]
124
+
125
+ puts JSON.pretty_generate synRP.get_allocation_requests_of_person(opts[:kw], person_id)
126
+ end
127
+ end
128
+
129
+ @cmd.define_command do
130
+ name 'req_all_meta'
131
+ usage 'req_all_meta [options]'
132
+ summary 'request meta ressources for all available employees'
133
+
134
+ required :k, :kw, 'yyyy-Wn (e. g. 2012-W6)'
135
+
136
+ run do |opts, args|
137
+
138
+ synRP.verify_opts_present(opts, [ :site, :username, :password, :kw ])
139
+
140
+ synRP.connect(opts[:site], opts[:username], opts[:password])
141
+
142
+ project_id = synRP.find_project_id_by_project_name("Meta")
143
+
144
+ all_persons = synRP.get_persons
145
+
146
+ synRP.get_availabilities(opts[:kw]).each do |person_id, minutes|
147
+ person = all_persons.find {|p| p["id"] == person_id.to_i }
148
+ if minutes > 0 && person["visible"]
149
+ synRP.request_res(opts[:kw], project_id, person_id, 120, 'Default Meta')
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ @cmd.define_command do
156
+ name 'persons'
157
+ usage 'persons [options]'
158
+ summary 'get all persons as json'
159
+
160
+ run do |opts, args|
161
+
162
+ synRP.verify_opts_present(opts, [ :site, :username, :password ])
163
+
164
+ synRP.connect(opts[:site], opts[:username], opts[:password])
165
+
166
+ puts JSON.pretty_generate synRP.get_persons
167
+ end
168
+ end
169
+
170
+ @cmd.define_command do
171
+ name 'projects'
172
+ usage 'projects [options]'
173
+ summary 'get all projects as json'
174
+
175
+ run do |opts, args|
176
+
177
+ synRP.verify_opts_present(opts, [ :site, :username, :password ])
178
+
179
+ synRP.connect(opts[:site], opts[:username], opts[:password])
180
+
181
+ puts JSON.pretty_generate synRP.get_projects
182
+ end
183
+ end
184
+
185
+ def self.run(args)
186
+ @cmd.run(ARGV)
187
+ end
188
+
189
+ end
190
+
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Library to use SynRP REST API
4
+ #
5
+ # Author
6
+ #
7
+ # Fabian Buch
8
+ #
9
+
10
+ require 'net/http'
11
+ require 'json'
12
+ require 'yaml'
13
+
14
+ module Synrp
15
+ class SynRP
16
+
17
+ def setup(opts)
18
+ opts = verify_opts_present(opts, [ :site, :username, :password ])
19
+ end
20
+
21
+ def verify_opts_present(opts, req_opts)
22
+ config_opts = read_config
23
+ req_opts.each do |r_opt|
24
+ unless opts[r_opt]
25
+ if config_opts[r_opt.to_s]
26
+ opts[r_opt] = config_opts[r_opt.to_s]
27
+ else
28
+ $stderr.puts "--#{r_opt} option is required"
29
+ exit 1
30
+ end
31
+ end
32
+ end
33
+ opts
34
+ end
35
+
36
+ def read_config
37
+ begin
38
+ return YAML.load_file(File.expand_path("~/.synRP_config.yaml"))
39
+ rescue
40
+ begin
41
+ current_dir = File.dirname(File.expand_path(__FILE__))
42
+ return YAML.load_file(current_dir + "/config.yaml")
43
+ rescue
44
+ end
45
+ end
46
+ return {}
47
+ end
48
+
49
+ def connect(site, username, password)
50
+ $conn = Net::HTTP.new(site, 80)
51
+ resp, data = $conn.post("/web/j_spring_security_check", "j_username=#{username}&j_password=#{password}", {})
52
+ cookie = resp.response['set-cookie']
53
+ $headers = { "Cookie" => cookie }
54
+ end
55
+
56
+ def get_persons
57
+ resp, data = $conn.get("/web/persons.json", $headers)
58
+ JSON.parse data
59
+ end
60
+
61
+ def find_project_id_by_project_name(pname)
62
+ project = get_projects.find {|p| p["name"] == pname }
63
+ project_id = project ? project["id"] : nil
64
+ end
65
+
66
+ def find_person_id_by_displayname(person_name)
67
+ person = get_persons.find { |p|
68
+ # replace weird whitespace with new one before comparing
69
+ p["displayName"].gsub(/\302\240/, ' ').match(person_name)
70
+ }
71
+ person_id = person ? person["id"] : nil
72
+ end
73
+
74
+ def find_person_by_id(id)
75
+ get_persons.find {|p| p["id"].to_s == id.to_s }
76
+ end
77
+
78
+ def get_projects
79
+ resp, data = $conn.get("/web/projects.json", $headers)
80
+ JSON.parse data
81
+ end
82
+
83
+ def get_availabilities(yearWeek)
84
+ resp, data = $conn.get("/web/availabilities.json?yearWeek=#{yearWeek}", $headers)
85
+ av = JSON.parse data
86
+ without_invisible = av.reject { |k,v| !find_person_by_id(k)["visible"] }
87
+ end
88
+
89
+ # get availabilities with resolved person, not their IDs
90
+ def get_availabilities_persons(yearWeek)
91
+ avails = get_availabilities(yearWeek)
92
+ avails.map { |k,v| { find_person_by_id(k)["displayName"], "#{v / 60.0} h" } }.inject(&:merge)
93
+ end
94
+
95
+ def get_allocation_requests(yearWeek)
96
+ resp, data = $conn.get("/web/allocation-requests.json?yearWeek=#{yearWeek}", $headers)
97
+ JSON.parse data
98
+ end
99
+
100
+ def get_allocation_requests_of_person(yearWeek, person_id)
101
+ reqs = get_allocation_requests(yearWeek)
102
+ reqs.find_all { |req| req["person"]["id"].to_s == person_id.to_s }
103
+ end
104
+
105
+ def calculate_remaining_availabilities(yearWeek)
106
+ avails = get_availabilities(yearWeek)
107
+ avails_minus_requests = avails.map do |person_id, minutes|
108
+ person = find_person_by_id(person_id)
109
+ reqs_of_person = get_allocation_requests_of_person(yearWeek, person_id)
110
+ remaining_minutes = minutes - sum_minutes_of_requests(reqs_of_person)
111
+ { person, remaining_minutes }
112
+ end.inject(&:merge)
113
+ avails_minus_requests.to_a.sort_by { |av| -av[1] }
114
+ end
115
+
116
+ def sum_minutes_of_requests(reqs)
117
+ sum = 0
118
+ reqs.each do |req|
119
+ sum += req["minutes"]
120
+ end
121
+ sum
122
+ end
123
+
124
+ def request_res(yearWeek, project, person, minutes, comment='')
125
+ puts "Requesting yearWeek=#{yearWeek}&project=#{project}&person=#{person}&minutes=#{minutes}&comment=#{comment}"
126
+ $conn.post("/web/allocation-requests/", "yearWeek=#{yearWeek}&project=#{project}&person=#{person}&minutes=#{minutes}&comment=#{comment}", $headers)
127
+ end
128
+
129
+ end
130
+ end
131
+
@@ -0,0 +1,3 @@
1
+ module Synrp
2
+ VERSION = "0.16.4"
3
+ end
data/lib/synrp.rb ADDED
@@ -0,0 +1,19 @@
1
+ #
2
+ # Library to use SynRP REST API
3
+ #
4
+ # Author
5
+ #
6
+ # Fabian Buch
7
+ #
8
+ #
9
+
10
+ require "synrp/version"
11
+ require "synrp/synrp"
12
+
13
+ module Synrp
14
+
15
+ def self.version_information
16
+ Nanoc::VERSION
17
+ end
18
+
19
+ end
data/synrp.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "synrp/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "synrp"
7
+ s.version = Synrp::VERSION
8
+ s.authors = ["Fabian Buch"]
9
+ s.email = ["buch@synyx.de"]
10
+ s.homepage = "https://github.com/Synyx/synRP"
11
+ s.summary = %q{Commandline Client for Synyx Resource Planner (synRP)}
12
+ s.description = %q{The synyx Resource Planner is a web application for managing work assignments. See https://github.com/Synyx/synRP for more information. This is a commandline client that uses its REST service.}
13
+
14
+ s.files = Dir['[A-Z]*'] + Dir['{bin,lib,tasks,test}/**/*'] + [ 'synrp.gemspec' ]
15
+ s.executables = [ 'synrp' ]
16
+ s.require_paths = [ 'lib' ]
17
+
18
+ s.add_runtime_dependency "cri", '~> 2.2'
19
+ s.add_runtime_dependency "json"
20
+
21
+ s.post_install_message = %q{------------------------------------------------------------------------------
22
+ run "synrp help" for usage information
23
+ ------------------------------------------------------------------------------
24
+ }
25
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: synrp
3
+ version: !ruby/object:Gem::Version
4
+ hash: 87
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 16
9
+ - 4
10
+ version: 0.16.4
11
+ platform: ruby
12
+ authors:
13
+ - Fabian Buch
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-04-11 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: cri
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 7
29
+ segments:
30
+ - 2
31
+ - 2
32
+ version: "2.2"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: json
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description: The synyx Resource Planner is a web application for managing work assignments. See https://github.com/Synyx/synRP for more information. This is a commandline client that uses its REST service.
50
+ email:
51
+ - buch@synyx.de
52
+ executables:
53
+ - synrp
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - Gemfile.lock
60
+ - Gemfile
61
+ - Rakefile
62
+ - bin/synrp
63
+ - lib/synrp.rb
64
+ - lib/synrp/cli.rb
65
+ - lib/synrp/synrp.rb
66
+ - lib/synrp/version.rb
67
+ - synrp.gemspec
68
+ homepage: https://github.com/Synyx/synRP
69
+ licenses: []
70
+
71
+ post_install_message: |
72
+ ------------------------------------------------------------------------------
73
+ run "synrp help" for usage information
74
+ ------------------------------------------------------------------------------
75
+
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.10
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Commandline Client for Synyx Resource Planner (synRP)
105
+ test_files: []
106
+