eco-helpers 2.0.22 → 2.0.27

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +95 -5
  3. data/lib/eco/api/common.rb +0 -1
  4. data/lib/eco/api/common/loaders.rb +2 -0
  5. data/lib/eco/api/common/loaders/base.rb +58 -0
  6. data/lib/eco/api/common/loaders/case_base.rb +33 -0
  7. data/lib/eco/api/common/loaders/error_handler.rb +2 -2
  8. data/lib/eco/api/common/loaders/parser.rb +30 -5
  9. data/lib/eco/api/common/loaders/policy.rb +1 -1
  10. data/lib/eco/api/common/loaders/use_case.rb +1 -1
  11. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +129 -1
  12. data/lib/eco/api/common/people/entries.rb +83 -14
  13. data/lib/eco/api/common/people/entry_factory.rb +11 -10
  14. data/lib/eco/api/common/people/person_attribute_parser.rb +8 -0
  15. data/lib/eco/api/common/people/person_entry.rb +7 -6
  16. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +55 -16
  17. data/lib/eco/api/common/people/person_factory.rb +4 -2
  18. data/lib/eco/api/common/people/person_parser.rb +7 -1
  19. data/lib/eco/api/common/people/supervisor_helpers.rb +1 -1
  20. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +0 -8
  21. data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +0 -8
  22. data/lib/eco/api/microcases/set_core_with_supervisor.rb +4 -2
  23. data/lib/eco/api/microcases/set_supervisor.rb +29 -8
  24. data/lib/eco/api/microcases/with_each.rb +7 -3
  25. data/lib/eco/api/microcases/with_each_starter.rb +3 -2
  26. data/lib/eco/api/organization/people.rb +7 -1
  27. data/lib/eco/api/session.rb +7 -2
  28. data/lib/eco/api/session/batch.rb +1 -1
  29. data/lib/eco/api/session/batch/job.rb +42 -9
  30. data/lib/eco/api/usecases/default_cases/create_case.rb +10 -1
  31. data/lib/eco/api/usecases/default_cases/create_details_case.rb +10 -1
  32. data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +10 -1
  33. data/lib/eco/api/usecases/default_cases/hris_case.rb +25 -1
  34. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +1 -37
  35. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +42 -0
  36. data/lib/eco/api/usecases/default_cases/upsert_case.rb +10 -1
  37. data/lib/eco/cli/config/default/input.rb +2 -2
  38. data/lib/eco/cli/config/default/options.rb +44 -7
  39. data/lib/eco/cli/config/default/usecases.rb +16 -0
  40. data/lib/eco/cli/config/default/workflow.rb +7 -4
  41. data/lib/eco/cli/config/filters.rb +6 -2
  42. data/lib/eco/cli/config/filters/input_filters.rb +3 -2
  43. data/lib/eco/cli/config/filters/people_filters.rb +3 -2
  44. data/lib/eco/cli/config/help.rb +1 -1
  45. data/lib/eco/cli/config/options_set.rb +6 -4
  46. data/lib/eco/cli/config/use_cases.rb +6 -3
  47. data/lib/eco/csv.rb +2 -0
  48. data/lib/eco/language/models/collection.rb +5 -2
  49. data/lib/eco/version.rb +1 -1
  50. metadata +3 -2
  51. data/lib/eco/api/common/base_loader.rb +0 -72
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba43099c7902b3e2623640a196abd86f39215403d28e7a614da78b2422629323
4
- data.tar.gz: 7e3701cbeb7b3a0a65453dc002d6f4c5cb6e6ec4103e6cd0178c1af333d29d7d
3
+ metadata.gz: 144eb5a5b4c0069c07c1af3bac6c23c43b975643f45b8b7d8e5edd05daa8defd
4
+ data.tar.gz: 6f2c5e8f1744380cb543d11087b3d5bbab822697e876c21c8a4ca1984ea5f3a9
5
5
  SHA512:
6
- metadata.gz: f14ab296c2cff2dc694ef9182593329ca1bc86cf08ca32ba879cd5e74d658d1d123add425bc62a981182b9e4da06b33d225d613cd1a9d9cbfd7284e6b6d24ea5
7
- data.tar.gz: f020822ad4ae2e18f1f0424bb3a47417ff9a6bc78a439517cee3cd9212548efe4c89256579d73ccde27709dc5d2ea3d3e74bd072de23d4c089ccf3c7a107fc07
6
+ metadata.gz: 8bb382dbc126f15308cdd51f3ec8d520a154450080388e329243102e0fa2c4d9dcbba395ec91f59ea645ea734f222a5af8fe25a1000a39b2474aba2c89a725dd
7
+ data.tar.gz: 11874a475a744e673e8741777079d54081c0b6be855a609cf7ed6e8a032f29c6e074cefe7e8a94d57944d70be4b8bebbcb5d6a7ff81e25d6e2798ce4259779b1
data/CHANGELOG.md CHANGED
@@ -1,6 +1,101 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [2.0.27] - 2021-06-xx
5
+
6
+ ### Added
7
+
8
+ ### Changed
9
+ - Parent class `Eco::API::UseCases::DefaultCases::ToCsvCase` shouldn't know header maps necessary for `Eco::API::UseCases::DefaultCases::ToCsvDetailedCase`
10
+ * Moved related header maps to `ToCsvDetailedCase`
11
+
12
+ ### Fixed
13
+ - `--help` should work fine now
14
+ - Attribute parsers that depended on indirect parser attributes were **not** included
15
+ - **changed** a couple of classes
16
+ - `Eco::API::Common::People::PersonEntryAttributeMapper`, where methods should receive `data` to re-scope if the data is available (most specifically `#internal_attrs`)
17
+ - `Eco::API::Common::People::PersonEntry`, where when setting the final values on `Person`, it should include any internal attribute that is present in the `final_entry` (the result of all the parsing process)
18
+ - `Eco::API::Common::People::DefaultParsers::CSVParser`
19
+ - indirect attributes that depended on other indirect attributes would show as missing even if they were active
20
+ - i.e. `name` depends on `first-name` & `surname`, **AND** `details-name` depends on `name`
21
+
22
+ ## [2.0.26] - 2021-06-25
23
+
24
+ ### Added
25
+ - `Eco::API::MicroCases#set_supervisor`, tries to keep in sync the `#subordinates` **count** of previous and new supervisor
26
+ - new **option** `-run-postlaunch` to run post launch cases, even when we run in `dry-run` mode
27
+ * when in `dry-run` it will **not** reload the people base of the session
28
+ - new **option** to append **new** entries to the `People` object
29
+ * **invokable** on **cli** via `-append-starters` (`{people: {append_created: true}}`)
30
+ * the following use cases include this option:
31
+ * `Eco::API::UseCases::DefaultCases::UpsertCase`
32
+ * `Eco::API::UseCases::DefaultCases::HrisCase`
33
+ * `Eco::API::UseCases::DefaultCases::CreateDetailsWithSupervisorCase`
34
+ * `Eco::API::UseCases::DefaultCases::CreateDetailsCase`
35
+ * `Eco::API::UseCases::DefaultCases::CreateCase`
36
+ * the option involves a new keyed argument `:append_created` in a couple of `MicroCases`
37
+ * `Eco::API::MicroCases#with_each`: where internally the search is performed against a copy of the `People` object.
38
+ * `Eco::API::MicroCases#with_each_starter`
39
+ * when `--help` is invoked option to filter the shown `-options`, `-usecases` and `filters` by a word contained in the option.
40
+ - **added** `csv` **header checks** for feed files, which entailed some changes:
41
+ * `Eco::API::Common::Loaders::Parser`
42
+ - new **subclass** `RequiredAttrs`, creatred when calling `.active_when_all` and `.active_when_any`
43
+ - **dependency** injection via `.dependencies` as `{required_attrs: RequiredAttrs}`
44
+ * **added** `Eco::API::Common::People::PersonParser#required_attrs` to offer all the `RequiredAttrs`, where defined
45
+ - the **new method** `#required_attrs` to expose the injected `RequiredAttrs`
46
+ * **new** keyed argument `check_headers:` in `Eco::API::Common::People::EntryFactory#entries`
47
+ - subsequent changes to accommodate the new param in `Eco::API::Session#csv_entries`
48
+ - `eco/cli/config/default/input` calls using this param to `true`
49
+ * `Eco::API::Common::People::DefaultParsers::CSVParser`
50
+ - added option `check_headers` via `dependencies` that enables the headers check
51
+ - it will now offer detailed warning messages on what can happen with the **missing headers**
52
+ * it will also list the **unknown header** names
53
+
54
+ ### Changed
55
+ - `Eco::API::MicroCases#set_supervisor`, the order of the 2 first parameters
56
+ - `Eco::API::Organization::People`: internally `@by_id` cache Hash included `nil` values => **not** any more.
57
+ - removed **unused** methods on **patches** for `Ecoportal::API::V1::Person` and `Ecoportal::API::Internal::Person`
58
+ * specifically `#reset_account!` and `#consolidate_account!` as well as `#reset_details!` and `#consolidate_details!`
59
+ - internal changes in `Eco::API::Common::People::Entries#entry`
60
+ * **added** option to trigger `MultipleSearchResults` StandardError when multiple candiates are found.
61
+ * **removed** `nil` values from the `caches` (the Hashes to optimize the search)
62
+ - slight structure refactor of `Eco::API::Common::Loaders`
63
+ * moved base class to subfolder/namespace
64
+ * decoupled pure `Loader` logics to `Loaders::Base` and use case inheriance chain loader to `Loaders::CaseBase`
65
+ - `Eco::API::Session::BatchJob` the `post_launch`:
66
+ * sets the `id` to the `person` if it was **created** successfully
67
+ * when in `dry-run` it fakes the `id` with a counter
68
+ - `Eco::API::Common::People::PersonFactory` gets `subordinates` initialized to `0` (when **creating** a `new` person)
69
+
70
+ ### Fixed
71
+
72
+
73
+ ## [2.0.25] - 2021-06-23
74
+
75
+ ### Added
76
+ - `Eco::API::UseCases::DefaultCases::HrisCase` validation error to require `-schema-id` command line when there are people in schemas other than the active one
77
+
78
+ ### Changed
79
+ - `Eco::API::Session::Batch::Job`
80
+ * for backwards compatibility `-include-only-excluded` should bring an options structure compatible with `-include-excluded`
81
+
82
+ ### Fixed
83
+ - `Eco::API::Session::Batch` fixed typo that would prevent `prompt_user` to work
84
+
85
+ ## [2.0.24] - 2021-06-22
86
+
87
+ ### Added
88
+ - `Eco::API::Session::Batch::Job` made **native** `-include-excluded`
89
+ * also added new option `-include-only-excluded` to be able to only target people HRIS excluded
90
+
91
+ ## [2.0.23] - 2021-06-22
92
+
93
+ ### Added
94
+ - `Eco::API::Session::Batch::Job` **new** option (`-save-requests`) to save requests even if in `dry-run` (`-simulate`)
95
+ ### Changed
96
+ - `Eco::API::Session::Batch::Job` new people won't create updates unless they have either details or account
97
+ * because that entry is not supposed to be created unless has account or details
98
+
4
99
  ## [2.0.22] - 2021-06-18
5
100
 
6
101
  ### Added
@@ -24,10 +119,6 @@ All notable changes to this project will be documented in this file.
24
119
  * we just kept `roo` and `roo-xls`
25
120
  - custom `Error` classes now all inherit from `StandardError` (rather than `Exception`)
26
121
 
27
-
28
- ### Fixed
29
-
30
-
31
122
  ## [2.0.21] - 2021-06-04
32
123
 
33
124
  ### Added
@@ -38,7 +129,6 @@ All notable changes to this project will be documented in this file.
38
129
  ### Changed
39
130
  - `Eco::API::Common::People::EntryFactory` slight **refactor** to boost better support for multiple input formats
40
131
 
41
-
42
132
  ## [2.0.20] - 2021-05-31
43
133
 
44
134
  ### Added
@@ -10,7 +10,6 @@ require_relative 'common/class_helpers'
10
10
  require_relative 'common/class_auto_loader'
11
11
  require_relative 'common/class_hierarchy'
12
12
  require_relative 'common/class_meta_basics'
13
- require_relative 'common/base_loader'
14
13
  require_relative 'common/loaders'
15
14
  require_relative 'common/session'
16
15
  require_relative 'common/people'
@@ -7,6 +7,8 @@ module Eco
7
7
  end
8
8
  end
9
9
 
10
+ require_relative 'loaders/base'
11
+ require_relative 'loaders/case_base'
10
12
  require_relative 'loaders/use_case'
11
13
  require_relative 'loaders/policy'
12
14
  require_relative 'loaders/error_handler'
@@ -0,0 +1,58 @@
1
+ module Eco
2
+ module API
3
+ module Common
4
+ module Loaders
5
+ class Base
6
+ extend Eco::API::Common::ClassHelpers
7
+
8
+ class << self
9
+ # Sort order
10
+ def <=>(other)
11
+ created_at <=> other.created_at
12
+ end
13
+
14
+ # If still not set, it sets the `created_at` class timestamp.
15
+ def set_created_at!
16
+ @created_at = Time.now unless @created_at
17
+ end
18
+
19
+ # Class creation timestamp, to be able to load them in the order they were declared.
20
+ def created_at
21
+ @created_at ||= Time.now
22
+ end
23
+ end
24
+
25
+ # This method will be called when the BaseLoader is created
26
+ # @note
27
+ # - this method should implement the loading logics for the given `Children` class.
28
+ def initialize
29
+ raise "You should implement this method"
30
+ end
31
+
32
+ def name
33
+ self.class.name
34
+ end
35
+
36
+ private
37
+
38
+ def session
39
+ ASSETS.session
40
+ end
41
+
42
+ def config
43
+ session.config
44
+ end
45
+
46
+ def logger
47
+ session.logger
48
+ end
49
+
50
+ def micro
51
+ session.micro
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,33 @@
1
+ module Eco
2
+ module API
3
+ module Common
4
+ module Loaders
5
+ class CaseBase < Loaders::Base
6
+
7
+ class << self
8
+ attr_writer :name, :type
9
+
10
+ # The name that this case, policy or error handler will have.
11
+ def name(value = nil)
12
+ name_only_once! if value
13
+ set_created_at!
14
+ return @name ||= self.to_s unless value
15
+ @name = value
16
+ end
17
+
18
+ # Prevent the same class to be re-opened/re-named
19
+ def name_only_once!
20
+ raise "You have already declared #{self} or you are trying to give it a name twice" if @name
21
+ end
22
+
23
+ end
24
+
25
+ def name
26
+ self.class.name
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,7 +2,7 @@ module Eco
2
2
  module API
3
3
  module Common
4
4
  module Loaders
5
- class ErrorHandler < Eco::API::Common::BaseLoader
5
+ class ErrorHandler < Eco::API::Common::Loaders::CaseBase
6
6
 
7
7
  class << self
8
8
  attr_writer :error
@@ -17,7 +17,7 @@ module Eco
17
17
  end
18
18
 
19
19
  inheritable_class_vars :error
20
-
20
+
21
21
  def initialize(handlers)
22
22
  raise "Expected Eco::API::Policies. Given #{handlers.class}" unless handlers.is_a?(Eco::API::Error::Handlers)
23
23
  handlers.on(self.error, &self.method(:main))
@@ -2,7 +2,28 @@ module Eco
2
2
  module API
3
3
  module Common
4
4
  module Loaders
5
- class Parser < Eco::API::Common::BaseLoader
5
+ class Parser < Eco::API::Common::Loaders::CaseBase
6
+
7
+ # Helper class to scope what required attributes it depends on
8
+ class RequiredAttrs < Struct.new(:attr, :type, :attrs)
9
+ def active?(*input_attrs)
10
+ missing(*input_attrs).empty?
11
+ end
12
+
13
+ def dependant?(attr)
14
+ attrs.include?(attr)
15
+ end
16
+
17
+ def missing(*input_attrs)
18
+ return [] if input_attrs.include?(attr)
19
+ match = input_attrs & attrs
20
+ miss = attrs - match
21
+ return [] if miss.empty?
22
+ return attrs if match.empty?
23
+ return miss if type == :all
24
+ []
25
+ end
26
+ end
6
27
 
7
28
  class << self
8
29
  attr_reader :active_when
@@ -19,12 +40,14 @@ module Eco
19
40
  @attribute = value
20
41
  end
21
42
 
22
- # TODO: it migh rather merge?
23
43
  # Some parsers require dependencies to do their job.
24
- def dependencies(value = nil)
44
+ def dependencies(**value)
25
45
  @dependencies ||= {}
26
- return @dependencies unless value
27
- @dependencies = value
46
+ return @dependencies.merge({
47
+ required_attrs: @active_when_attrs
48
+ }) unless !value.empty?
49
+ raise "Expected Hash. Given: '#{value.class}'" unless value.is_a?(Hash)
50
+ @dependencies.merge!(value)
28
51
  end
29
52
 
30
53
  # Define or get the `phase` that the `parser` kicks in.
@@ -47,6 +70,7 @@ module Eco
47
70
 
48
71
  # Helper to build the `active_when` condition.
49
72
  def active_when_any(*attrs)
73
+ @active_when_attrs = RequiredAttrs.new(attribute, :any, attrs)
50
74
  @active_when = Proc.new do |source_data|
51
75
  keys = data_keys(source_data)
52
76
  attrs.any? {|key| keys.include?(key)}
@@ -55,6 +79,7 @@ module Eco
55
79
 
56
80
  # Helper to build the `active_when` condition.
57
81
  def active_when_all(*attrs)
82
+ @active_when_attrs = RequiredAttrs.new(attribute, :all, attrs)
58
83
  @active_when = Proc.new do |source_data|
59
84
  keys = data_keys(source_data)
60
85
  attrs.all? {|key| keys.include?(key)}
@@ -2,7 +2,7 @@ module Eco
2
2
  module API
3
3
  module Common
4
4
  module Loaders
5
- class Policy < Eco::API::Common::BaseLoader
5
+ class Policy < Eco::API::Common::Loaders::CaseBase
6
6
 
7
7
  def initialize(policies)
8
8
  raise "Expected Eco::API::Policies. Given #{policies.class}" unless policies.is_a?(Eco::API::Policies)
@@ -2,7 +2,7 @@ module Eco
2
2
  module API
3
3
  module Common
4
4
  module Loaders
5
- class UseCase < Eco::API::Common::BaseLoader
5
+ class UseCase < Eco::API::Common::Loaders::CaseBase
6
6
 
7
7
  class << self
8
8
  # @return [Symbol] the `type` of usecase (i.e. `:sync`, `:transform`, `:import`, `:other`)
@@ -2,7 +2,9 @@ class Eco::API::Common::People::DefaultParsers::CSVParser < Eco::API::Common::Lo
2
2
  attribute :csv
3
3
 
4
4
  def parser(data, deps)
5
- Eco::CSV.parse(data, headers: true, skip_blanks: true).each_with_object([]) do |row, arr_hash|
5
+ Eco::CSV.parse(data, headers: true, skip_blanks: true).tap do |table|
6
+ check_headers(table) if deps[:check_headers]
7
+ end.each_with_object([]) do |row, arr_hash|
6
8
  row_hash = row.headers.uniq.each_with_object({}) do |attr, hash|
7
9
  next if attr.to_s.strip.empty?
8
10
  hash[attr.strip] = parse_string(row[attr])
@@ -36,4 +38,130 @@ class Eco::API::Common::People::DefaultParsers::CSVParser < Eco::API::Common::Lo
36
38
  ["NULL"].any? {|token| str == token}
37
39
  end
38
40
 
41
+ def check_headers(table)
42
+ headers = table.headers
43
+ missing = missing_headers(headers)
44
+ unknown = unknown_headers(headers)
45
+ unless missing.empty? && unknown.empty?
46
+ msg = "Detected possible HEADER ISSUES !!!\n"
47
+ msg << "There might be Missing or Wrong HEADER names in the CSV file:\n"
48
+ msg << " * UNKNOWN (or not used?): #{unknown}\n" unless unknown.empty?
49
+ msg << " * MISSING DIRECT: #{missing[:direct]}\n" unless (missing[:direct] || []).empty?
50
+ unless (data = missing[:indirect] || []).empty?
51
+ msg << " * MISSING INDIRECT:\n"
52
+ data.each do |ext, info|
53
+ msg << " - '#{ext}' => "
54
+ msg << (info[:attrs] || {}).map do |status, attrs|
55
+ if status == :inactive
56
+ "makes inactive: #{attrs}"
57
+ elsif status == :active
58
+ "there could be missing info in: #{attrs}"
59
+ end
60
+ end.compact.join("; ") + "\n"
61
+ end
62
+ end
63
+ logger.warn(msg)
64
+ sleep(2)
65
+ end
66
+ end
67
+
68
+ def unknown_headers(headers)
69
+ (headers - known_headers) - all_internal_attrs
70
+ end
71
+
72
+ def missing_headers(headers)
73
+ int_head = internal_present_or_active(headers)
74
+ ext = headers.select do |e|
75
+ i = fields_mapper.to_internal(e)
76
+ int_head.include?(i)
77
+ end
78
+ ext_present = known_headers_present(int_head) | ext
79
+ ext_miss = known_headers - ext_present
80
+
81
+ ext_miss.each_with_object({}) do |ext, missing|
82
+ next unless int = fields_mapper.to_internal(ext)
83
+ if all_internal_attrs.include?(int)
84
+ missing[:direct] ||= []
85
+ missing[:direct] << ext
86
+ end
87
+ related_attrs_requirements = required_attrs.values.select do |req|
88
+ dep = req.dependant?(int)
89
+ affects = dep && !int_head.include?(int)
90
+ in_header = int_head.include?(req.attr)
91
+ affects || (dep && !in_header)
92
+ end
93
+ next if related_attrs_requirements.empty?
94
+ missing[:indirect] ||= {}
95
+ data = missing[:indirect][ext] = {}
96
+ data[:int] = int
97
+ data[:attrs] = {}
98
+ related_attrs_requirements.each_with_object(data[:attrs]) do |req, attrs|
99
+ status = req.active?(*int_head) ? :active : :inactive
100
+ attrs[status] ||= []
101
+ attrs[status] << req.attr
102
+ end
103
+ end
104
+ end
105
+
106
+ def known_headers_present(headers_internal)
107
+ @known_internal ||= known_headers.select do |ext|
108
+ int = fields_mapper.to_internal(ext)
109
+ headers_internal.include?(int)
110
+ end
111
+ end
112
+
113
+ def internal_present_or_active(headers, inactive_requirements = {})
114
+ hint = headers & all_internal_attrs
115
+ hext = headers - hint
116
+ int_present = hint + hext.map {|e| fields_mapper.to_internal(e)}.compact
117
+
118
+ update_inactive = Proc.new do
119
+ inactive_requirements.dup.each do |attr, req|
120
+ if req.active?(*int_present)
121
+ inactive_requirements.delete(attr)
122
+ int_present << attr
123
+ update_inactive.call
124
+ end
125
+ end
126
+ end
127
+
128
+ required_attrs.values.each do |req|
129
+ next if int_present.include?(req)
130
+ if req.active?(*int_present)
131
+ inactive_requirements.delete(req.attr)
132
+ int_present << req.attr
133
+ update_inactive.call
134
+ else
135
+ inactive_requirements[req.attr] = req
136
+ end
137
+ end
138
+ int_present
139
+ end
140
+
141
+ def known_headers
142
+ @known_headers ||= fields_mapper.list(:external).compact
143
+ end
144
+
145
+ def fields_mapper
146
+ session.fields_mapper
147
+ end
148
+
149
+ def required_attrs
150
+ @required_attrs ||= person_parser.required_attrs.each_with_object({}) do |ra, out|
151
+ out[ra.attr] = ra
152
+ end
153
+ end
154
+
155
+ def all_internal_attrs
156
+ @all_internal_attrs ||= [].tap do |int_attrs|
157
+ known_int_attrs = person_parser.all_attrs(include_defined_parsers: true)
158
+ known_int_attrs |= fields_mapper.list(:internal).compact
159
+ int_attrs.concat(known_int_attrs)
160
+ end
161
+ end
162
+
163
+ def person_parser
164
+ session.entry_factory.person_parser
165
+ end
166
+
39
167
  end