Class: DebtManagementCenter::Sharepoint::Request

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Common::Client::Concerns::Monitoring
Defined in:
lib/debt_management_center/sharepoint/request.rb

Defined Under Namespace

Classes: ListItemNotFound

Constant Summary collapse

STATSD_KEY_PREFIX =
'api.vha.financial_status_report.sharepoint.request'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Common::Client::Concerns::Monitoring

#increment, #increment_failure, #increment_total, #with_monitoring

Constructor Details

#initializeRequest

Returns a new instance of Request.



21
22
23
24
# File 'lib/debt_management_center/sharepoint/request.rb', line 21

def initialize
  @settings = initialize_settings
  @access_token = set_sharepoint_access_token
end

Instance Attribute Details

#access_tokenObject

Returns the value of attribute access_token.



16
17
18
# File 'lib/debt_management_center/sharepoint/request.rb', line 16

def access_token
  @access_token
end

#settingsObject (readonly)

Returns the value of attribute settings.



15
16
17
# File 'lib/debt_management_center/sharepoint/request.rb', line 15

def settings
  @settings
end

#userObject

Returns the value of attribute user.



16
17
18
# File 'lib/debt_management_center/sharepoint/request.rb', line 16

def user
  @user
end

Instance Method Details

#auth_connectionObject (private)



167
168
169
170
171
172
173
174
175
176
177
# File 'lib/debt_management_center/sharepoint/request.rb', line 167

def auth_connection
  Faraday.new(url: authentication_url, headers: auth_headers) do |conn|
    conn.request :url_encoded
    conn.use :breakers
    conn.use Faraday::Response::RaiseError
    conn.response :raise_custom_error, error_prefix: service_name
    conn.response :json
    conn.response :betamocks if mock_enabled?
    conn.adapter Faraday.default_adapter
  end
end

#auth_headersHash (private)

HTTP headers for Microsoft Access Control authentication

Returns:

  • (Hash)


209
210
211
212
213
# File 'lib/debt_management_center/sharepoint/request.rb', line 209

def auth_headers
  {
    'Content-Type' => 'application/x-www-form-urlencoded'
  }
end

#get_pdf_list_item_id(pdf_upload_response) ⇒ Number (private)

Get the ID of the uploaded document’s list item

Parameters:

  • pdf_upload_response (Faraday::Response)
    • Network response from initial upload

Returns:

  • (Number)


124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/debt_management_center/sharepoint/request.rb', line 124

def get_pdf_list_item_id(pdf_upload_response)
  uri = pdf_upload_response.body['d']['ListItemAllFields']['__deferred']['uri']
  path = uri.slice(uri.index(base_path)..-1)

  with_monitoring do
    get_item_response = sharepoint_connection.get(path)

    list_item_id = get_item_response.body.dig('d', 'ID')
    raise ListItemNotFound if list_item_id.nil?

    list_item_id
  end
end

#initialize_settingsObject (private)



227
228
229
# File 'lib/debt_management_center/sharepoint/request.rb', line 227

def initialize_settings
  @settings = Settings.vha.sharepoint
end

#mock_enabled?Boolean (private)

Betamocks enabled status from settings

Returns:

  • (Boolean)


240
241
242
# File 'lib/debt_management_center/sharepoint/request.rb', line 240

def mock_enabled?
  settings.mock || false
end

#mpi_serviceObject (private)



231
232
233
# File 'lib/debt_management_center/sharepoint/request.rb', line 231

def mpi_service
  @service ||= MPI::Service.new
end

#set_sharepoint_access_tokenString (private)

Set the access token for SharePoint authentication from Microsoft Access Control

Returns:

  • (String)
    • The access token



62
63
64
65
66
67
68
69
70
71
# File 'lib/debt_management_center/sharepoint/request.rb', line 62

def set_sharepoint_access_token
  auth_response = auth_connection.post("/#{tenant_id}/tokens/OAuth/2", {
                                         grant_type: 'client_credentials',
                                         client_id: "#{client_id}@#{tenant_id}",
                                         client_secret:,
                                         resource: "#{resource}/#{sharepoint_url}@#{tenant_id}"
                                       })

  auth_response.body['access_token']
end

#set_user_data(user_account_id) ⇒ Object (private)



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/debt_management_center/sharepoint/request.rb', line 73

def set_user_data()
   = UserAccount.find()
   = mpi_service.find_profile_by_identifier(identifier: .icn,
                                                        identifier_type: MPI::Constants::ICN)

  {
    ssn: .profile.ssn,
    first_name: .profile.given_names.first,
    last_name: .profile.family_name
  }
end

#sharepoint_connectionObject (private)



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/debt_management_center/sharepoint/request.rb', line 179

def sharepoint_connection
  Faraday.new(url: "https://#{sharepoint_url}", headers: sharepoint_headers) do |conn|
    conn.request :json
    conn.use :breakers
    conn.use Faraday::Response::RaiseError
    conn.response :raise_custom_error, error_prefix: service_name
    conn.response :json
    conn.response :betamocks if mock_enabled?
    conn.adapter Faraday.default_adapter
  end
end

#sharepoint_file_connectionObject (private)



191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/debt_management_center/sharepoint/request.rb', line 191

def sharepoint_file_connection
  Faraday.new(url: "https://#{sharepoint_url}", headers: sharepoint_headers) do |conn|
    conn.request :multipart
    conn.request :url_encoded
    conn.use :breakers
    conn.use Faraday::Response::RaiseError
    conn.response :raise_custom_error, error_prefix: service_name
    conn.response :json
    conn.response :betamocks if mock_enabled?
    conn.adapter Faraday.default_adapter
  end
end

#sharepoint_headersHash (private)

HTTP headers for uploading documents to SharePoint

Returns:

  • (Hash)


220
221
222
223
224
225
# File 'lib/debt_management_center/sharepoint/request.rb', line 220

def sharepoint_headers
  {
    'Authorization' => "Bearer #{access_token}",
    'Accept' => 'application/json;odata=verbose'
  }
end

#update_list_item_fields(list_item_id:, form_submission:, station_id:) ⇒ Faraday::Response (private)

Populate data columns with properties needed by VHA

Parameters:

  • list_item_id (Number)
    • ID of SharePoint list item

  • form_submission (Form5655Submission)
    • Persisted form

  • station_id (String)
    • VHA Station identifier

Returns:

  • (Faraday::Response)


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/debt_management_center/sharepoint/request.rb', line 147

def update_list_item_fields(list_item_id:, form_submission:, station_id:)
  path = "#{base_path}/_api/Web/Lists/GetByTitle('Submissions')/items(#{list_item_id})"
  with_monitoring do
    sharepoint_connection.post(path) do |req|
      req.headers['Content-Type'] = 'application/json;odata=verbose'
      req.headers['X-HTTP-METHOD'] = 'MERGE'
      req.headers['If-Match'] = '*'
      req.body = {
        '__metadata' => {
          'type' => 'SP.Data.SubmissionsItem'
        },
        'StationId' => station_id,
        'UID' => form_submission.id,
        'SSN' => user[:ssn],
        'Name1' => "#{user[:last_name]}, #{user[:first_name]}"
      }.to_json
    end
  end
end

#upload(form_contents:, form_submission:, station_id:) ⇒ Faraday::Response

Upload a PDF file of 5655 form to VHA SharePoint

Parameters:

  • form_contents (Hash)
    • The JSON of the form

  • form_submission (Form5655Submission)
    • Persisted submission of the form

  • station_id (String)
    • The VHA station the form belongs to

Returns:

  • (Faraday::Response)
    • Response from SharePoint upload



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/debt_management_center/sharepoint/request.rb', line 35

def upload(form_contents:, form_submission:, station_id:)
  @user = set_user_data(form_submission.)
  upload_response = upload_pdf(form_contents:, form_submission:,
                               station_id:)

  list_item_id = get_pdf_list_item_id(upload_response)

  resp = update_list_item_fields(list_item_id:, form_submission:, station_id:)
  if resp.success?
    StatsD.increment("#{STATSD_KEY_PREFIX}.success")
  else
    StatsD.increment("#{STATSD_KEY_PREFIX}.failure")
  end
  resp
rescue => e
  StatsD.increment("#{STATSD_KEY_PREFIX}.failure")
  Rails.logger.error('Sharepoint Upload failed', e.message)
  raise e
end

#upload_pdf(form_contents:, form_submission:, station_id:) ⇒ Faraday::Response (private)

Upload PDF document to SharePoint site

Parameters:

  • form_contents (Hash)
    • Contents to fill form with

  • form_submission (Form5655Submission)
    • Persisted form

  • station_id (String)
    • VHA Station identifier

Returns:

  • (Faraday::Response)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/debt_management_center/sharepoint/request.rb', line 94

def upload_pdf(form_contents:, form_submission:, station_id:)
  pdf_path = PdfFill::Filler.fill_ancillary_form(form_contents, "#{form_submission.id}-#{station_id}", '5655')
  fsr_pdf = File.open(pdf_path)

  file_name = "#{DateTime.now.strftime('%Y%m%dT%H%M%S')}_#{user[:ssn].last(4)}_#{user[:last_name].tr(' ', '_')}"

  file_transfer_path =
    "#{base_path}/_api/Web/GetFolderByServerRelativeUrl('#{base_path}/Submissions')" \
    "/Files/add(url='#{file_name}.pdf',overwrite=true)"

  with_monitoring do
    response = sharepoint_file_connection.post(file_transfer_path) do |req|
      req.headers['Content-Type'] = 'octet/stream'
      req.headers['Content-Length'] = fsr_pdf.size.to_s
      req.body = Faraday::UploadIO.new(fsr_pdf, 'octet/stream')
    end

    File.delete(pdf_path)

    response
  end
end