Skip to content

Commit 5258c94

Browse files
committed
Add CLI tool which sends a given CSV to careplus service
* Currently uses the mock service until access to the real service is granted * Sets the Careplus URL for each environment * Extracts logic to send requests into Careplus::Client Jira-Issue: MAV-5884
1 parent 2c26e86 commit 5258c94

9 files changed

Lines changed: 524 additions & 0 deletions

File tree

app/lib/careplus/client.rb

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# frozen_string_literal: true
2+
3+
require "cgi"
4+
require "net/http"
5+
require "uri"
6+
7+
module Careplus
8+
class Client
9+
TARGET_NAMESPACE_BASE = "https://careplus.syhapp.thirdparty.nhs.uk"
10+
11+
def initialize(username:, password:, namespace:, payload:)
12+
@username = username
13+
@password = password
14+
@namespace = namespace
15+
@payload = payload
16+
end
17+
18+
def send_csv
19+
uri =
20+
URI.parse("#{Settings.careplus.base_url}/#{namespace}/soap.SchImms.cls")
21+
soap_body = build_soap_envelope
22+
post_soap_request(uri, soap_body)
23+
end
24+
25+
def self.send_csv(...) = new(...).send_csv
26+
27+
private_class_method :new
28+
29+
private
30+
31+
attr_reader :username, :password, :namespace, :payload
32+
33+
def build_soap_envelope
34+
escaped_payload = CGI.escapeHTML(payload)
35+
target_namespace = "#{TARGET_NAMESPACE_BASE}/#{namespace}/webservices"
36+
37+
<<~XML
38+
<?xml version="1.0" encoding="utf-8"?>
39+
<soap:Envelope
40+
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
41+
xmlns:car="#{target_namespace}">
42+
<soap:Body>
43+
<car:InsertImmsRecord>
44+
<car:strUserId>#{username}</car:strUserId>
45+
<car:strPwd>#{password}</car:strPwd>
46+
<car:strPayload>#{escaped_payload}</car:strPayload>
47+
</car:InsertImmsRecord>
48+
</soap:Body>
49+
</soap:Envelope>
50+
XML
51+
end
52+
53+
def post_soap_request(uri, body)
54+
http = Net::HTTP.new(uri.host, uri.port)
55+
http.use_ssl = uri.scheme == "https"
56+
57+
request = Net::HTTP::Post.new(uri.request_uri)
58+
request["Content-Type"] = "text/xml; charset=utf-8"
59+
request.body = body
60+
61+
http.request(request)
62+
end
63+
end
64+
end

app/lib/mavis_cli.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def self.terminal_lines
5858
require_relative "mavis_cli/pds/get"
5959
require_relative "mavis_cli/pds/search"
6060
require_relative "mavis_cli/reports/export_automated_careplus"
61+
require_relative "mavis_cli/reports/send_to_careplus"
6162
require_relative "mavis_cli/schools/add_programme_year_group"
6263
require_relative "mavis_cli/schools/add_to_team"
6364
require_relative "mavis_cli/schools/create"
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "../../careplus/client"
4+
5+
module MavisCLI
6+
module Reports
7+
class SendToCareplus < Dry::CLI::Command
8+
desc "Send a CarePlus CSV file to the CarePlus endpoint"
9+
10+
example [
11+
"--input=tmp/automated_export.csv",
12+
"--input=tmp/automated_export.csv --ods_code=ABC123"
13+
]
14+
15+
FALLBACK_NAMESPACE = "MOCK"
16+
FALLBACK_USERNAME = "mavis_user"
17+
FALLBACK_PASSWORD = "mavis_password"
18+
19+
option :input, required: true, desc: "Path to the CSV file to send"
20+
option :ods_code,
21+
desc: "ODS code of the organisation (to use team credentials)"
22+
option :workgroup,
23+
desc:
24+
"Team workgroup (required if the organisation has multiple teams)"
25+
26+
def call(input:, ods_code: nil, workgroup: nil, **)
27+
MavisCLI.load_rails
28+
29+
unless File.exist?(input)
30+
warn "File not found: '#{input}'"
31+
return
32+
end
33+
34+
username, password, namespace =
35+
resolve_credentials(ods_code:, workgroup:)
36+
return if username.nil?
37+
38+
csv_payload = File.read(input)
39+
40+
response =
41+
Careplus::Client.send_csv(
42+
username:,
43+
password:,
44+
namespace:,
45+
payload: csv_payload
46+
)
47+
48+
if response.is_a?(Net::HTTPSuccess)
49+
puts "Success (HTTP #{response.code})"
50+
puts response.body
51+
else
52+
warn "Request failed with HTTP #{response.code}: #{response.message}"
53+
warn response.body
54+
end
55+
end
56+
57+
private
58+
59+
def resolve_credentials(ods_code:, workgroup:)
60+
if ods_code.nil?
61+
return FALLBACK_USERNAME, FALLBACK_PASSWORD, FALLBACK_NAMESPACE
62+
end
63+
64+
organisation = Organisation.find_by(ods_code:)
65+
if organisation.nil?
66+
warn "Could not find organisation with ODS code '#{ods_code}'"
67+
return nil, nil
68+
end
69+
70+
teams = organisation.teams
71+
teams = teams.where(workgroup:) if workgroup
72+
73+
if teams.empty?
74+
warn(
75+
if workgroup
76+
"Could not find team '#{workgroup}' for organisation '#{ods_code}'"
77+
else
78+
"Organisation '#{ods_code}' has no teams."
79+
end
80+
)
81+
return nil, nil, nil
82+
end
83+
84+
if workgroup.nil? && teams.many?
85+
warn "Organisation '#{ods_code}' has multiple teams. Specify --workgroup."
86+
return nil, nil, nil
87+
end
88+
89+
team = teams.sole
90+
91+
unless team.careplus_username.present? &&
92+
team.careplus_password.present?
93+
warn "Team '#{team.name}' does not have CarePlus credentials configured."
94+
return nil, nil, nil
95+
end
96+
97+
[
98+
team.careplus_username,
99+
team.careplus_password,
100+
team.careplus_namespace
101+
]
102+
end
103+
end
104+
end
105+
106+
register "reports" do |prefix|
107+
prefix.register "send-to-careplus", Reports::SendToCareplus
108+
end
109+
end

config/settings.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ reporting_api:
5757
client_id: <%= Rails.application.credentials.reporting_api&.client_id %>
5858
secret: <%= Rails.application.credentials.reporting_api&.secret %>
5959

60+
careplus:
61+
base_url: https://careplus.syhapp.thirdparty.nhs.uk
62+
6063
# Set a value to override the default values set in config/initializers/devise.rb
6164
devise:
6265
timeout_in_seconds:

config/settings/development.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ splunk:
2626
reporting_api:
2727
client_app:
2828
root_url: http://localhost:4001
29+
30+
careplus:
31+
base_url: http://localhost:8080

config/settings/staging.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ cis2:
1717
pds:
1818
raise_unknown_gp_practice: false
1919
rate_limit_per_second: 5
20+
21+
careplus:
22+
base_url: <%= ENV.fetch("MOCK_CAREPLUS_URL", nil) %>

config/settings/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ splunk:
2424
reporting_api:
2525
client_app:
2626
root_url: http://localhost:5001/
27+
28+
careplus:
29+
base_url: http://localhost:8080

0 commit comments

Comments
 (0)