eco-helpers 2.0.21 → 2.0.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +101 -4
- data/eco-helpers.gemspec +0 -1
- data/lib/eco/api/common.rb +0 -1
- data/lib/eco/api/common/loaders.rb +2 -0
- data/lib/eco/api/common/loaders/base.rb +58 -0
- data/lib/eco/api/common/loaders/case_base.rb +33 -0
- data/lib/eco/api/common/loaders/error_handler.rb +2 -2
- data/lib/eco/api/common/loaders/parser.rb +30 -5
- data/lib/eco/api/common/loaders/policy.rb +1 -1
- data/lib/eco/api/common/loaders/use_case.rb +1 -1
- data/lib/eco/api/common/people/default_parsers.rb +1 -0
- data/lib/eco/api/common/people/default_parsers/csv_parser.rb +93 -1
- data/lib/eco/api/common/people/default_parsers/xls_parser.rb +53 -0
- data/lib/eco/api/common/people/entries.rb +83 -14
- data/lib/eco/api/common/people/entry_factory.rb +36 -21
- data/lib/eco/api/common/people/person_attribute_parser.rb +8 -0
- data/lib/eco/api/common/people/person_factory.rb +4 -2
- data/lib/eco/api/common/people/person_parser.rb +8 -2
- data/lib/eco/api/common/people/supervisor_helpers.rb +1 -1
- data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +0 -8
- data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +0 -8
- data/lib/eco/api/microcases/set_core_with_supervisor.rb +4 -2
- data/lib/eco/api/microcases/set_supervisor.rb +29 -8
- data/lib/eco/api/microcases/with_each.rb +7 -3
- data/lib/eco/api/microcases/with_each_starter.rb +3 -2
- data/lib/eco/api/organization/people.rb +7 -1
- data/lib/eco/api/session.rb +18 -7
- data/lib/eco/api/session/batch.rb +1 -1
- data/lib/eco/api/session/batch/job.rb +42 -9
- data/lib/eco/api/usecases.rb +2 -2
- data/lib/eco/api/usecases/base_case.rb +2 -2
- data/lib/eco/api/usecases/base_io.rb +17 -4
- data/lib/eco/api/usecases/default_cases/create_case.rb +10 -1
- data/lib/eco/api/usecases/default_cases/create_details_case.rb +10 -1
- data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +10 -1
- data/lib/eco/api/usecases/default_cases/hris_case.rb +25 -1
- data/lib/eco/api/usecases/default_cases/upsert_case.rb +10 -1
- data/lib/eco/cli/config/default/input.rb +63 -10
- data/lib/eco/cli/config/default/options.rb +40 -8
- data/lib/eco/cli/config/default/usecases.rb +16 -0
- data/lib/eco/cli/config/default/workflow.rb +7 -4
- data/lib/eco/cli/config/filters.rb +6 -2
- data/lib/eco/cli/config/filters/input_filters.rb +3 -2
- data/lib/eco/cli/config/filters/people_filters.rb +3 -2
- data/lib/eco/cli/config/help.rb +1 -1
- data/lib/eco/cli/config/options_set.rb +6 -4
- data/lib/eco/cli/config/use_cases.rb +6 -3
- data/lib/eco/cli/scripting/args_helpers.rb +2 -2
- data/lib/eco/csv.rb +2 -0
- data/lib/eco/language/models/collection.rb +5 -2
- data/lib/eco/version.rb +1 -1
- metadata +4 -22
- data/lib/eco/api/common/base_loader.rb +0 -68
@@ -0,0 +1,53 @@
|
|
1
|
+
class Eco::API::Common::People::DefaultParsers::XLSParser < Eco::API::Common::Loaders::Parser
|
2
|
+
attribute :xls
|
3
|
+
|
4
|
+
attr_accessor :already_required
|
5
|
+
attr_reader :file
|
6
|
+
|
7
|
+
def parser(file, deps)
|
8
|
+
@file = file
|
9
|
+
rows.tap {|r| @file = nil}
|
10
|
+
end
|
11
|
+
|
12
|
+
def serializer(array_hash, deps)
|
13
|
+
raise "Not implemented. TODO: using axlsx or rubyXL gems. See: https://spin.atomicobject.com/2017/03/22/parsing-excel-files-ruby/"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def headers
|
19
|
+
raise "You should implement this method"
|
20
|
+
end
|
21
|
+
|
22
|
+
def sheet_name
|
23
|
+
0
|
24
|
+
end
|
25
|
+
|
26
|
+
def workbook
|
27
|
+
require_reading_libs!
|
28
|
+
Roo::Spreadsheet.open(file)
|
29
|
+
end
|
30
|
+
|
31
|
+
def spreadheet(name_or_index = sheet_name)
|
32
|
+
workbook.sheet(name_or_index)
|
33
|
+
end
|
34
|
+
|
35
|
+
def rows(target = headers)
|
36
|
+
begin
|
37
|
+
spreadheet.parse(header_search: target)
|
38
|
+
rescue Roo::HeaderRowNotFoundError => e
|
39
|
+
missing = JSON.parse(e.message)
|
40
|
+
logger.warn("The input file is missing these headers: #{missing}")
|
41
|
+
present = target - missing
|
42
|
+
rows(present)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def require_reading_libs!
|
47
|
+
return if already_required
|
48
|
+
require 'roo'
|
49
|
+
require 'roo-xls'
|
50
|
+
already_required = true
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -5,6 +5,42 @@ module Eco
|
|
5
5
|
# Class meant to offer a _collection_ of entries, normally used to get parsed input data.
|
6
6
|
# @attr_reader entries [Array<Eco::API::Common::PeopleEntry] a pure `Array` object.
|
7
7
|
class Entries < Eco::Language::Models::Collection
|
8
|
+
# Error class that allows to handle cases where multiple entries were found for the same criterion.
|
9
|
+
# @note its main purpose to prevent the false pairing of duplicates or override information between different people.
|
10
|
+
class MultipleSearchResults < StandardError
|
11
|
+
attr_reader :candidates, :property
|
12
|
+
# @param msg [String] the basic message error.
|
13
|
+
# @param candiates [Array<PersonEntry>] the entries that match the same search criterion.
|
14
|
+
# @param property [String] the property of the entry model that triggered the error (base of the search criterion).
|
15
|
+
def initialize(msg, candidates: [], property: "email")
|
16
|
+
@candidates = candidates
|
17
|
+
@property = property
|
18
|
+
super(msg + " " + candidates_summary)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param with_index [Boolean] to add an index to each candidate description.
|
22
|
+
# @return [Array<String>] the `candidates` identified
|
23
|
+
def identify_candidates(with_index: false)
|
24
|
+
candidates.map.each_with_index do |entry, i|
|
25
|
+
index = with_index ? "#{i}. " : ""
|
26
|
+
"#{index} #{entry.identify}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Person] the `candidate` in the `index` position
|
31
|
+
def candidate(index)
|
32
|
+
candidates[index]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def candidates_summary
|
38
|
+
lines = ["The following entries have the same '#{property}':"]
|
39
|
+
lines.concat(identify_candidates(with_index: true)).join("\n ")
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
8
44
|
# build the shortcuts of Collection
|
9
45
|
attr_collection :id, :external_id, :email, :name, :supervisor_id
|
10
46
|
|
@@ -54,19 +90,34 @@ module Eco
|
|
54
90
|
# @!group Searchers
|
55
91
|
|
56
92
|
# Search function to find an `entry` based on one of different options
|
93
|
+
# It searches an entry using the parameters given.
|
94
|
+
# @note This is how the search function actually works:
|
95
|
+
# 1. if eP `id` is given, returns the entry (if found), otherwise...
|
96
|
+
# 2. if `external_id` is given, returns the entry (if found), otherwise...
|
97
|
+
# 3. if `strict` is `false` and `email` is given:
|
98
|
+
# - if there is only 1 entry with that email, returns that entry, otherwise...
|
99
|
+
# - if found but, there are many candidate entries, it raises MultipleSearchResults error
|
100
|
+
# - if entry `external_id` matches `email`, returns that entry
|
101
|
+
# @raise MultipleSearchResults if there are multiple entries with the same `email`
|
102
|
+
# and there's no other criteria to find the entry. It only gets to this point if
|
103
|
+
# `external_id` was **not** provided and we are **not** in 'strict' search mode.
|
104
|
+
# However, it could be we were in `strict` mode and `external_id` was not provided.
|
105
|
+
# @param id [String] the `internal id` of the person
|
106
|
+
# @param external_id [String] the `exernal_id` of the person
|
107
|
+
# @param email [String] the `email` of the person
|
108
|
+
# @param strict [Boolean] if should perform a `:soft` or a `:strict` search. `strict` will avoid repeated email addresses.
|
109
|
+
# @return [Entry, nil] the entry we were searching, or `nil` if not found.
|
57
110
|
def entry(id: nil, external_id: nil, email: nil, strict: false)
|
58
111
|
init_caches
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
pers
|
112
|
+
# normalize values
|
113
|
+
ext_id = !external_id.to_s.strip.empty? && external_id.strip
|
114
|
+
email = !email.to_s.strip.empty? && email.downcase.strip
|
115
|
+
|
116
|
+
e = nil
|
117
|
+
e ||= @by_id[id]&.first
|
118
|
+
e ||= @by_external_id[ext_id]&.first
|
119
|
+
e ||= entry_by_email(email) unless strict && ext_id
|
120
|
+
e
|
70
121
|
end
|
71
122
|
|
72
123
|
# Search function to find an `entry` based on one of different options
|
@@ -136,15 +187,33 @@ module Eco
|
|
136
187
|
|
137
188
|
private
|
138
189
|
|
190
|
+
def entry_by_email(email, prevent_multiple_match: false)
|
191
|
+
return nil unless email
|
192
|
+
|
193
|
+
candidates = @by_email[email] || []
|
194
|
+
return candidates.first if candidates.length == 1
|
195
|
+
|
196
|
+
if prevent_multiple_match && !candidates.empty?
|
197
|
+
msg = "Multiple search results match the criteria."
|
198
|
+
raise MultipleSearchResults.new(msg, candidates: candidates, property: "email")
|
199
|
+
end
|
200
|
+
|
201
|
+
@by_external_id[email]&.first
|
202
|
+
end
|
203
|
+
|
139
204
|
def init_caches
|
140
205
|
return if @caches_init
|
141
|
-
@by_id = to_h
|
142
|
-
@by_external_id = to_h('external_id')
|
143
|
-
@by_email = to_h('email')
|
206
|
+
@by_id = no_nil_key(to_h)
|
207
|
+
@by_external_id = no_nil_key(to_h('external_id'))
|
208
|
+
@by_email = no_nil_key(to_h('email'))
|
144
209
|
@array_supers = sort_by_supervisors(@items)
|
145
210
|
@caches_init = true
|
146
211
|
end
|
147
212
|
|
213
|
+
def no_nil_key(hash)
|
214
|
+
hash.tap {|h| h.delete(nil)}
|
215
|
+
end
|
216
|
+
|
148
217
|
end
|
149
218
|
end
|
150
219
|
end
|
@@ -80,54 +80,69 @@ module Eco
|
|
80
80
|
# @param data [Array<Hash>] data to be parsed. It cannot be used alongside with `file:`
|
81
81
|
# @param file [String] absolute or relative path to the input file. It cannot be used alongside with `data:`.
|
82
82
|
# @param format [Symbol] it must be used when you use the option `file:` (i.e. `:xml`, `:csv`), as it specifies the format of the input `file:`.
|
83
|
-
# @param
|
83
|
+
# @param options [Hash] further options.
|
84
|
+
# @option options [String] :encoding optional parameter to read `file:` by expecting certain encoding.
|
85
|
+
# @option options [Boolean] :check_headers signals if the `csv` file headers should be expected.
|
84
86
|
# @return [Eco::API::Common::People::Entries] collection of `Eco::API::Common::People::PersonEntry`.
|
85
|
-
def entries(data: (no_data = true; nil), file: (no_file = true; nil), format: (no_format = true; nil),
|
87
|
+
def entries(data: (no_data = true; nil), file: (no_file = true; nil), format: (no_format = true; nil), **options)
|
86
88
|
fatal("You should at least use data: or file:, but not both") if no_data == no_file
|
87
89
|
fatal("You must specify a valid format: (symbol) when you use file.") if file && no_format
|
88
90
|
fatal("Format should be a Symbol. Given '#{format}'") if format && !format.is_a?(Symbol)
|
89
91
|
fatal("There is no parser/serializer for format ':#{format.to_s}'") unless no_format || @person_parser.defined?(format)
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
kargs.merge!(format: format) unless no_format
|
95
|
-
kargs.merge!(encoding: encoding) if encoding
|
93
|
+
options.merge!(content: data) unless no_data
|
94
|
+
options.merge!(file: file) unless no_file
|
95
|
+
options.merge!(format: format) unless no_format
|
96
96
|
|
97
|
-
Entries.new(to_array_of_hashes(**
|
97
|
+
Entries.new(to_array_of_hashes(**options), klass: PersonEntry, factory: self)
|
98
98
|
end
|
99
99
|
|
100
100
|
def to_array_of_hashes(**kargs)
|
101
101
|
data = []
|
102
102
|
content, file, encoding, format = kargs.values_at(:content, :file, :encoding, :format)
|
103
103
|
|
104
|
-
|
104
|
+
# Support for multiple file
|
105
|
+
if file.is_a?(Array)
|
106
|
+
return file.each_with_object([]) do |f, out|
|
107
|
+
logger.info("Parsing file '#{f}'")
|
108
|
+
curr = to_array_of_hashes(**kargs.merge(file: f))
|
109
|
+
out.concat(curr)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
# Get content only when it's not :xls
|
113
|
+
# note: even if content was provided, file takes precedence
|
114
|
+
content = get_file_content(file, format, encoding) if (format != :xls) && file
|
105
115
|
|
106
116
|
case content
|
107
|
-
when !content
|
108
|
-
logger.error("Could not obtain any data out of these: #{kargs}")
|
109
|
-
exit(1)
|
110
117
|
when Hash
|
111
118
|
logger.error("Input data as 'Hash' not supported. Expecting 'Enumerable' or 'String'")
|
112
119
|
exit(1)
|
113
120
|
when String
|
114
|
-
|
115
|
-
|
116
|
-
entry_hash.tap {|hash| hash["idx"] = j}
|
117
|
-
end
|
118
|
-
to_array_of_hashes(content: data)
|
121
|
+
deps = {check_headers: true} if kargs[:check_headers]
|
122
|
+
to_array_of_hashes(content: person_parser.parse(format, content, deps: deps || {}))
|
119
123
|
when Enumerable
|
120
124
|
sample = content.to_a.first
|
121
125
|
case sample
|
122
126
|
when Hash, Array, ::CSV::Row
|
123
127
|
Eco::CSV::Table.new(content).to_array_of_hashes
|
124
128
|
else
|
125
|
-
logger.error("Input 'Array' of '#{sample.class}' is not supported.")
|
129
|
+
logger.error("Input content 'Array' of '#{sample.class}' is not supported.")
|
126
130
|
end
|
127
131
|
else
|
128
|
-
|
129
|
-
|
132
|
+
if file && format == :xls
|
133
|
+
person_parser.parse(format, file)
|
134
|
+
else
|
135
|
+
logger.error("Could not obtain any data out of these: #{kargs}. Given content: '#{content.class}'")
|
136
|
+
exit(1)
|
137
|
+
end
|
138
|
+
end.tap do |out_array|
|
139
|
+
start_from_two = (format == :csv) || format == :xls
|
140
|
+
out_array.each_with_index do |entry_hash, i|
|
141
|
+
entry_hash["idx"] = start_from_two ? i + 2 : i + 1
|
142
|
+
entry_hash["source_file"] = file
|
143
|
+
end
|
130
144
|
end
|
145
|
+
|
131
146
|
end
|
132
147
|
|
133
148
|
|
@@ -150,7 +165,7 @@ module Eco
|
|
150
165
|
|
151
166
|
run = true
|
152
167
|
if Eco::API::Common::Session::FileManager.file_exists?(file)
|
153
|
-
prompt_user("
|
168
|
+
prompt_user("Do you want to overwrite it? (Y/n):", explanation: "The file '#{file}' already exists.", default: "Y") do |response|
|
154
169
|
run = (response == "") || reponse.upcase.start_with?("Y")
|
155
170
|
end
|
156
171
|
end
|
@@ -6,6 +6,14 @@ module Eco
|
|
6
6
|
# Class to define a parser/serializer.
|
7
7
|
class PersonAttributeParser < Eco::Language::Models::ParserSerializer
|
8
8
|
|
9
|
+
# @note
|
10
|
+
# - This was introduced at a later stage and might not be available for certain org-parsers configs
|
11
|
+
# @return [RequiredAttrs]
|
12
|
+
def required_attrs
|
13
|
+
@required_attrs ||= @dependencies[:required_attrs]
|
14
|
+
#@required_attrs ||= RequiredAttrs.new(attr, :unkown, [attr])
|
15
|
+
end
|
16
|
+
|
9
17
|
# @see Eco::Language::Models::ParserSerializer#def_parser
|
10
18
|
# @note
|
11
19
|
# - additionally, you can declare a callback `active:` to determine if when the
|
@@ -10,7 +10,7 @@ module Eco
|
|
10
10
|
|
11
11
|
attr_reader :schema, :schema_attrs
|
12
12
|
|
13
|
-
def initialize(person:
|
13
|
+
def initialize(person: nil, schema: {}, account: {}, modifier: Common::People::PersonModifier.new)
|
14
14
|
@modifier = Common::People::PersonModifier.new(modifier)
|
15
15
|
@person = person
|
16
16
|
@account = account
|
@@ -77,7 +77,9 @@ module Eco
|
|
77
77
|
when Hash
|
78
78
|
JSON.parse(person.to_json)
|
79
79
|
else
|
80
|
-
{
|
80
|
+
{
|
81
|
+
"subordinates" => 0
|
82
|
+
}
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
@@ -16,7 +16,7 @@ module Eco
|
|
16
16
|
CORE_ATTRS = ["id", "external_id", "email", "name", "supervisor_id", "filter_tags", "freemium"]
|
17
17
|
ACCOUNT_ATTRS = ["policy_group_ids", "default_tag", "send_invites", "landing_page_id", "login_provider_ids"]
|
18
18
|
TYPE = [:select, :text, :date, :number, :phone_number, :boolean, :multiple]
|
19
|
-
FORMAT = [:csv, :xml, :json]
|
19
|
+
FORMAT = [:csv, :xml, :json, :xls]
|
20
20
|
|
21
21
|
attr_reader :schema
|
22
22
|
attr_reader :details_attrs, :all_model_attrs
|
@@ -59,9 +59,15 @@ module Eco
|
|
59
59
|
|
60
60
|
# @!group Scopping attributes (identifying, presence & active)
|
61
61
|
|
62
|
+
# @return [Array<Eco::API::Common::Loaders::Parser::RequiredAttrs>]
|
63
|
+
def required_attrs
|
64
|
+
@parsers.values_at(*all_attrs(include_defined_parsers: true)).compact.map(&:required_attrs).compact
|
65
|
+
end
|
66
|
+
|
62
67
|
# All the internal name attributes, including _core_, _account_ and _details_.
|
63
68
|
def all_attrs(include_defined_parsers: false)
|
64
|
-
all_model_attrs | defined_model_attrs
|
69
|
+
return all_model_attrs | defined_model_attrs if include_defined_parsers
|
70
|
+
all_model_attrs
|
65
71
|
end
|
66
72
|
|
67
73
|
# Scopes `source_attrs` using the _**core** attributes_.
|
@@ -15,7 +15,7 @@ module Eco
|
|
15
15
|
# Reorders as follows:
|
16
16
|
# 1. supervisors, people with no supervisor or where their supervisor not present
|
17
17
|
# 2. subordinates
|
18
|
-
# @return [Array<
|
18
|
+
# @return [Array<PersonEntry>] `values` sorted by supervisors/subordinates
|
19
19
|
def sort_by_supervisors(values, supervisors_first: true)
|
20
20
|
raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
|
21
21
|
return [] unless values && values.is_a?(Enumerable)
|
@@ -5,14 +5,6 @@ module Ecoportal
|
|
5
5
|
class Person
|
6
6
|
attr_accessor :entry
|
7
7
|
|
8
|
-
def reset_details!
|
9
|
-
doc["details"] = JSON.parse(original_doc["details"])
|
10
|
-
end
|
11
|
-
|
12
|
-
def consolidate_details!
|
13
|
-
original_doc["details"] = JSON.parse(doc["details"])
|
14
|
-
end
|
15
|
-
|
16
8
|
def identify(section = :person)
|
17
9
|
if entry && section == :entry
|
18
10
|
entry.to_s(:identify)
|
@@ -3,14 +3,6 @@ module Ecoportal
|
|
3
3
|
class Internal
|
4
4
|
class Person
|
5
5
|
|
6
|
-
def reset_account!
|
7
|
-
doc["account"] = JSON.parse(original_doc["account"])
|
8
|
-
end
|
9
|
-
|
10
|
-
def consolidate_account!
|
11
|
-
original_doc["account"] = JSON.parse(doc["account"])
|
12
|
-
end
|
13
|
-
|
14
6
|
def new?(doc = :initial)
|
15
7
|
ref_doc = (doc == :original) ? original_doc : initial_doc
|
16
8
|
!ref_doc["details"] && !ref_doc["account"]
|
@@ -12,9 +12,11 @@ module Eco
|
|
12
12
|
unless options.dig(:exclude, :core) && !person.new?
|
13
13
|
micro.set_core(entry, person, options)
|
14
14
|
if entry.supervisor_id?
|
15
|
-
micro.set_supervisor(entry.supervisor_id,
|
15
|
+
micro.set_supervisor(person, entry.supervisor_id, people, options) do |unknown_id|
|
16
16
|
# delay setting supervisor if does not exit
|
17
|
-
supers_job.add(person)
|
17
|
+
supers_job.add(person) do |person|
|
18
|
+
micro.set_supervisor(person, unknown_id, people, options)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -1,22 +1,27 @@
|
|
1
1
|
module Eco
|
2
2
|
module API
|
3
3
|
class MicroCases
|
4
|
-
#
|
5
|
-
# @note delaying the setting of a `supervisor_id` can save errors when the supervisor still does not exit.
|
6
|
-
# @param sup_id [nil, String] the **supervisor id** we should set on the `person`.
|
4
|
+
# Unique access point to set the `supervisor_id` value on a person.
|
7
5
|
# @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
|
8
|
-
# @param
|
6
|
+
# @param sup_id [nil, String] the **supervisor id** we should set on the `person`.
|
7
|
+
# @param people [Eco::API::Organization::People] _People_ involved in the current update.
|
9
8
|
# @param options [Hash] the options.
|
10
9
|
# @yield [supervisor_id] callback when the supervisor_id is **unknown** (not `nil` nor any one's in `people`).
|
11
10
|
# @yieldparam supervisor_id [String] the **unknown** `supervisor_id`.
|
12
|
-
def set_supervisor(
|
11
|
+
def set_supervisor(person, sup_id, people, options)
|
13
12
|
unless options.dig(:exclude, :core) || options.dig(:exclude, :supervisor)
|
14
|
-
|
13
|
+
cur_id = person.supervisor_id
|
14
|
+
cur_super = cur_id && with_supervisor(cur_id, people)
|
15
|
+
micro.with_supervisor(sup_id, people) do |new_super|
|
15
16
|
if !sup_id
|
16
17
|
person.supervisor_id = nil
|
17
|
-
|
18
|
-
|
18
|
+
descrease_subordinates(cur_super)
|
19
|
+
elsif new_super && id = new_super.id
|
20
|
+
person.supervisor_id = id
|
21
|
+
descrease_subordinates(cur_super)
|
22
|
+
increase_subordinates(new_super)
|
19
23
|
elsif !block_given?
|
24
|
+
descrease_subordinates(cur_super)
|
20
25
|
person.supervisor_id = sup_id
|
21
26
|
else
|
22
27
|
yield(sup_id) if block_given?
|
@@ -25,6 +30,22 @@ module Eco
|
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
33
|
+
private
|
34
|
+
|
35
|
+
def descrease_subordinates(person, by = 1)
|
36
|
+
if person.is_a?(Ecoportal::API::V1::Person)
|
37
|
+
person.subordinates -= by
|
38
|
+
#person.subordinates = 0 if person.subordinates < 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def increase_subordinates(person, by = 1)
|
43
|
+
if person.is_a?(Ecoportal::API::V1::Person)
|
44
|
+
#person.subordinates = 0 if person.subordinates < 0
|
45
|
+
person.subordinates += by
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
28
49
|
end
|
29
50
|
end
|
30
51
|
end
|