Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ RESEED_API_KEY=changeme

# Enable immediate onboarding for schools
ENABLE_IMMEDIATE_SCHOOL_ONBOARDING=true

# Salesforce Connect
SALESFORCE_ENABLED=true
SALESFORCE_CONNECT_HOST=salesforce_connect
SALESFORCE_CONNECT_PASSWORD=password
SALESFORCE_CONNECT_USER=postgres
33 changes: 33 additions & 0 deletions app/jobs/salesforce/salesforce_sync_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# # frozen_string_literal: true

module Salesforce
class SalesforceSyncJob < ApplicationJob
include GoodJob::ActiveJobExtensions::Concurrency

good_job_control_concurrency_with(
perform_throttle: [2, 1.second]
)

SalesforceRecordNotFound = Class.new(StandardError)
SkipBecauseSalesforceIsDisabled = Class.new(StandardError)

include ActionView::Helpers::SanitizeHelper

queue_as :salesforce_sync

discard_on SkipBecauseSalesforceIsDisabled

before_perform do |_job|
unless ENV.fetch('SALESFORCE_ENABLED', 'true') == 'true'
raise SkipBecauseSalesforceIsDisabled, 'SALESFORCE_ENABLED is not true.'
end
end

def perform(*)
raise NotImplementedError, 'Subclasses must implement perform'
end

# TODO Consider implementing private utilities here, e.g. truncate_value
end
end

21 changes: 21 additions & 0 deletions app/jobs/salesforce/school_sync_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module Salesforce
class SchoolSyncJob < SalesforceSyncJob
MODEL_CLASS = Salesforce::School

FIELD_MAPPINGS = {}.freeze

STATUS_MAPPINGS = {}.freeze


def perform(school_id:)
@school = School.find(id: school_id)
sf_school = Salesforce::School.find_or_initialize_by(school_id__c: school_id)

# Make the sf_school match @school.

sf_school.save!
end
end
end
9 changes: 9 additions & 0 deletions app/models/salesforce/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# # frozen_string_literal: true

module Salesforce
class Base < ApplicationRecord
self.abstract_class = true

connects_to database: { writing: :salesforce_connect }
end
end
9 changes: 9 additions & 0 deletions app/models/salesforce/school.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# # frozen_string_literal: true

module Salesforce
class School < Salesforce::Base
self.table_name = 'salesforce.school__c' # TODO Confirm this - placeholder
self.primary_key = :school_id__c

end
end
7 changes: 7 additions & 0 deletions app/models/school.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class School < ApplicationRecord

# TODO: Remove the conditional once the feature flag is retired
after_create :generate_code!, if: -> { FeatureFlags.immediate_school_onboarding? }

# After creation, sync the School to Salesforce.
after_commit :do_salesforce_sync, on: [:create, :update]

def self.find_for_user!(user)
school = Role.find_by(user_id: user.id)&.school || find_by(creator_id: user.id)
Expand Down Expand Up @@ -169,4 +172,8 @@ def format_uk_postal_code
# ensures UK postcodes are always formatted correctly (as the inward code is always 3 chars long)
self.postal_code = "#{cleaned_postal_code[0..-4]} #{cleaned_postal_code[-3..]}"
end

def do_salesforce_sync
Salesforce::SchoolSyncJob.perform_later(school_id: id)
end
end
33 changes: 27 additions & 6 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,35 @@ default: &default
password: <%= ENV.fetch('POSTGRES_PASSWORD', '') %>
pool: <%= ENV.fetch('RAILS_MAX_THREADS', 5) %>

salesforce_connect: &salesforce_connect
adapter: postgresql
encoding: unicode
host: <%= ENV.fetch('SALESFORCE_CONNECT_HOST', 'localhost') %>
username: <%= ENV.fetch('SALESFORCE_CONNECT_USER', '') %>
password: <%= ENV.fetch('SALESFORCE_CONNECT_PASSWORD', '') %>
pool: <%= ENV.fetch('RAILS_MAX_THREADS', 5) %>
database_tasks: false

development:
<<: *default
database: <%= ENV.fetch('POSTGRES_DB', 'choco_cake_development') %>
default:
<<: *default
database: <%= ENV.fetch('POSTGRES_DB', 'choco_cake_development') %>
salesforce_connect:
<<: *salesforce_connect
database: <%= ENV.fetch('SALESFORCE_CONNECT_DB', 'salesforce_development') %>

test:
<<: *default
database: <%= ENV.fetch('POSTGRES_DB', 'choco_cake_test') %>
default:
<<: *default
database: <%= ENV.fetch('POSTGRES_DB', 'choco_cake_test') %>
salesforce_connect:
<<: *salesforce_connect
database: <%= ENV.fetch('SALESFORCE_CONNECT_DB', 'salesforce_development') %>

production:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
default:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
salesforce_connect:
<<: *salesforce_connect
url: <%= ENV.fetch('SALESFORCE_CONNECT_URL', "") %>
2 changes: 1 addition & 1 deletion config/initializers/good_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ def authenticate_admin
# The create_students_job queue is a serial queue that allows only one job at a time.
# DO NOT change the value of create_students_job:1 without understanding the implications
# of processing more than one user creation job at once.
config.good_job.queues = 'create_students_job:1;import_schools_job:1;default:5'
config.good_job.queues = 'create_students_job:1;import_schools_job:1;salesforce_sync:1,default:5'
end
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,29 @@ services:
platform: linux/amd64
command: -u $SMEE_TUNNEL -t http://api:3009/github_webhooks

salesforce_connect:
image: ghcr.io/raspberrypifoundation/heroku-connect
volumes:
- salesforce_connect_data:/var/lib/postgres/data/
environment:
- POSTGRES_DB=salesforce_development
- POSTGRES_CLONE_DB=salesforce_test
- POSTGRES_PASSWORD=password
- POSTGRES_USER=postgres
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -h 127.0.0.1 -U $${POSTGRES_USER} -d $${POSTGRES_DB}",
]
interval: 5s
timeout: 5s
retries: 10
ports:
- "4101:5432"

volumes:
postgres-data:
bundle-data:
node_modules:
salesforce_connect_data: