eco-helpers 2.0.22 → 2.0.27

Sign up to get free protection for your applications and to get access to all the features.
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