Class: NetSuiteRails::RecordSync::PushManager
- Inherits:
-
Object
- Object
- NetSuiteRails::RecordSync::PushManager
- Defined in:
- lib/netsuite_rails/record_sync/push_manager.rb
Class Method Summary collapse
- .all_netsuite_fields(local_record) ⇒ Object
- .build_netsuite_record(local_record, opts = {}) ⇒ Object
- .build_netsuite_record_reference(local_record) ⇒ Object
- .changed_attributes(local_record) ⇒ Object
- .modified_local_fields(local_record) ⇒ Object
- .push(local_record, opts = {}) ⇒ Object
- .push_add(local_record, netsuite_record, opts = {}) ⇒ Object
- .push_update(local_record, netsuite_record, opts = {}) ⇒ Object
Class Method Details
.all_netsuite_fields(local_record) ⇒ Object
176 177 178 179 180 181 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 176 def all_netsuite_fields(local_record) custom_netsuite_field_list = local_record.netsuite_field_map[:custom_field_list] || {} standard_netsuite_field_list = local_record.netsuite_field_map.except(:custom_field_list) || {} custom_netsuite_field_list.merge(standard_netsuite_field_list) end |
.build_netsuite_record(local_record, opts = {}) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 99 def build_netsuite_record(local_record, opts = {}) netsuite_record = build_netsuite_record_reference(local_record) # TODO need to normalize datetime fields all_field_list = opts[:modified_fields] custom_field_list = local_record.netsuite_field_map[:custom_field_list] || {} field_hints = local_record.netsuite_field_hints reflections = if NetSuiteRails.rails4? local_record.class.reflections else local_record.reflections end all_field_list.each do |local_field, netsuite_field| # allow Procs as field mapping in the record definition for custom mapping if netsuite_field.is_a?(Proc) netsuite_field.call(local_record, netsuite_record, :push) next end # TODO pretty sure this will break if we are dealing with has_many netsuite_field_value = if reflections.has_key?(local_field) if (remote_internal_id = local_record.send(local_field).try(:netsuite_id)).present? { internal_id: remote_internal_id } else nil end else local_record.send(local_field) end if field_hints.has_key?(local_field) && netsuite_field_value.present? netsuite_field_value = NetSuiteRails::Transformations.transform(field_hints[local_field], netsuite_field_value) end # TODO should we skip setting nil values completely? What if we want to nil out fields on update? # be wary of API version issues: https://github.com/NetSweet/netsuite/issues/61 if custom_field_list.keys.include?(local_field) netsuite_record.custom_field_list.send(:"#{netsuite_field}=", netsuite_field_value) else netsuite_record.send(:"#{netsuite_field}=", netsuite_field_value) end end netsuite_record end |
.build_netsuite_record_reference(local_record) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 151 def build_netsuite_record_reference(local_record) # must set internal_id for records on new; will be set to nil if new record netsuite_record = local_record.netsuite_record_class.new(internal_id: local_record.netsuite_id) if local_record.netsuite_custom_record? netsuite_record.rec_type = NetSuite::Records::CustomRecord.new(internal_id: local_record.class.netsuite_custom_record_type_id) end netsuite_record end |
.changed_attributes(local_record) ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 183 def changed_attributes(local_record) # otherwise filter only by attributes that have been changed # limiting the delta sent to NS will reduce hitting edge cases # TODO think about has_many / join table changes reflections = if NetSuiteRails.rails4? local_record.class.reflections else local_record.reflections end association_field_key_mapping = reflections.values.reject(&:collection?).inject({}) do |h, a| begin h[a.association_foreign_key.to_sym] = a.name rescue Exception => e # occurs when `has_one through:` exists on a record but `through` is not a valid reference Rails.logger.error "NetSuite: error detecting foreign key #{a.name}" end h end changed_attributes_keys = local_record.changed_attributes.keys # TODO documentation about serialized values changed_attributes_keys += local_record.serialized_attributes.keys.map do |k| local_record.send(k.to_sym).keys.map(&:to_s) end.flatten # convert relationship symbols from :object_id to :object changed_attributes_keys.map do |k| association_field_key_mapping[k.to_sym] || k.to_sym end end |
.modified_local_fields(local_record) ⇒ Object
163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 163 def modified_local_fields(local_record) synced_netsuite_fields = all_netsuite_fields(local_record) changed_keys = changed_attributes(local_record) # filter out unchanged keys when updating record unless local_record.new_netsuite_record? synced_netsuite_fields.select! { |k,v| changed_keys.include?(k) } end synced_netsuite_fields end |
.push(local_record, opts = {}) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 7 def push(local_record, opts = {}) # TODO check to see if anything is changed before moving forward # if changes_keys.blank? && local_record.netsuite_manual_fields if opts[:modified_fields] # if Array, we need to convert info fields hash based on the record definition if opts[:modified_fields].is_a?(Array) opts[:modified_fields] = all_netsuite_fields(local_record).select { |k,v| opts[:modified_fields].include?(k) } end else opts[:modified_fields] = modified_local_fields(local_record) end netsuite_record = build_netsuite_record(local_record, opts) local_record.netsuite_execute_callbacks(local_record.class.before_netsuite_push, netsuite_record) if !local_record.new_netsuite_record? push_update(local_record, netsuite_record, opts) else push_add(local_record, netsuite_record, opts) end # :aggressive is for custom fields which are based on input – need pull updated values after # the push to netsuite to retrieve the calculated values if local_record.netsuite_sync == :aggressive local_record.netsuite_pull end local_record.netsuite_execute_callbacks(local_record.class.after_netsuite_push, netsuite_record) true end |
.push_add(local_record, netsuite_record, opts = {}) ⇒ Object
42 43 44 45 46 47 48 49 50 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 42 def push_add(local_record, netsuite_record, opts = {}) if netsuite_record.add # update_column to avoid triggering another save local_record.update_column(:netsuite_id, netsuite_record.internal_id) else # TODO use NS error class raise "NetSuite: error creating record #{netsuite_record.errors}" end end |
.push_update(local_record, netsuite_record, opts = {}) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/netsuite_rails/record_sync/push_manager.rb', line 52 def push_update(local_record, netsuite_record, opts = {}) # build change hash to limit the number of fields pushed to NS on change # NS could have logic which could change field functionality depending on # input data; it's safest to limit the number of field changes pushed to NS custom_field_list = local_record.netsuite_field_map[:custom_field_list] || {} modified_fields_list = opts[:modified_fields] update_list = {} modified_fields_list.each do |local_field, netsuite_field| if custom_field_list.keys.include?(local_field) # if custom field has changed, mark and copy over customFieldList later update_list[:custom_field_list] = true else update_list[netsuite_field] = netsuite_record.send(netsuite_field) end end # manual field list is for fields manually defined on the NS record # outside the context of ActiveRecord (e.g. in a before_netsuite_push) (local_record.netsuite_manual_fields || []).each do |netsuite_field| if netsuite_field == :custom_field_list update_list[:custom_field_list] = true else update_list[netsuite_field] = netsuite_record.send(netsuite_field) end end if update_list[:custom_field_list] update_list[:custom_field_list] = netsuite_record.custom_field_list end if local_record.netsuite_custom_record? update_list[:rec_type] = netsuite_record.rec_type end # TODO consider using upsert here if netsuite_record.update(update_list) true else raise "NetSuite: error updating record #{netsuite_record.errors}" end end |