Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/745 fetch people search entries from ptime #748

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
138fab7
Add first approach for fetching people from ptime API
ManuelMoeri Jul 4, 2024
7f6abdd
Add helper and write test for fetching employee data
ManuelMoeri Jul 4, 2024
ea3d4e5
Finish test and fix logic in displaying people
ManuelMoeri Jul 5, 2024
3a6b7c0
Implement correct routing of person and fix a problem in the docker s…
ManuelMoeri Jul 5, 2024
c25e18c
Possibly fix docker compose file
ManuelMoeri Jul 8, 2024
4385c4a
Fix tests and implement logic for sorting people
ManuelMoeri Jul 8, 2024
202006a
Implement logic for fallback and cleanup helper method
ManuelMoeri Jul 9, 2024
1dc3065
Improve fallback logic by making it more readable and shorter
ManuelMoeri Jul 9, 2024
1267736
Implement first approach on calling the ptime api after 5 minutes
ManuelMoeri Jul 10, 2024
512593b
Improve logic of 5 minutes request and change client.rb
ManuelMoeri Jul 11, 2024
c9e9825
Add logic to load site correctly and remove unnecessary code
ManuelMoeri Jul 12, 2024
39acf6e
Fix logic of rendering people and cleanup code
ManuelMoeri Jul 15, 2024
d967660
Add tests for person_helper
ManuelMoeri Jul 17, 2024
c657e8f
Add ptime_helpers to cleanup code
ManuelMoeri Jul 17, 2024
bcb3ebe
Fix tests
ManuelMoeri Jul 17, 2024
456f27b
Fix last test and remove pry
ManuelMoeri Jul 17, 2024
4718e92
Fix test and add comment
ManuelMoeri Jul 18, 2024
bf771aa
Generalize window resizing of capybara
ManuelMoeri Jul 18, 2024
189ab80
Cleanup code and add comments
ManuelMoeri Jul 19, 2024
2e2ae6b
Add one more test for client.rb
ManuelMoeri Jul 19, 2024
766e942
Reverse test from last commit
ManuelMoeri Jul 19, 2024
aa36e82
change location of helper
kcinay055679 Jul 25, 2024
4153a5b
set ptime stubing global
kcinay055679 Jul 25, 2024
87d84d8
clean up ptime client specs
kcinay055679 Jul 25, 2024
96391b2
create json file for fixtures
kcinay055679 Jul 25, 2024
cce291b
use hashes instead of strings for json keys create global ptime stub …
kcinay055679 Jul 25, 2024
d3bb9c3
use custom ptime stubbing method everywhere
kcinay055679 Jul 25, 2024
dd96900
fix tests after always using [:data]
kcinay055679 Jul 25, 2024
0d1c4ff
clean up ptime client
kcinay055679 Jul 25, 2024
7550234
improve structure of people search
kcinay055679 Jul 25, 2024
552cf7d
Client isn't longer controlled by random env vars
kcinay055679 Jul 25, 2024
d9c02be
simplify ptime_helpers
kcinay055679 Jul 25, 2024
44d76bd
clean up PR
kcinay055679 Jul 26, 2024
71db98a
Clean up Skills db fallback logic
kcinay055679 Jul 26, 2024
3a7997a
improve readability by using more helper
kcinay055679 Jul 26, 2024
d19bd8e
clean up
kcinay055679 Jul 26, 2024
57ad58a
add client test
kcinay055679 Jul 29, 2024
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
8 changes: 0 additions & 8 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ GEM
crass (1.0.6)
cssbundling-rails (1.4.0)
railties (>= 6.0.0)
daemons (1.4.1)
database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.1.0)
Expand All @@ -134,11 +133,6 @@ GEM
database_cleaner-core (2.0.1)
date (3.3.4)
deep_merge (1.2.2)
delayed_job (4.1.11)
activesupport (>= 3.0, < 8.0)
delayed_job_active_record (4.1.8)
activerecord (>= 3.0, < 8.0)
delayed_job (>= 3.0, < 5)
devise (4.9.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
Expand Down Expand Up @@ -484,9 +478,7 @@ DEPENDENCIES
config
countries
cssbundling-rails
daemons
database_cleaner
delayed_job_active_record
devise
dotenv
faker
Expand Down
14 changes: 7 additions & 7 deletions app/domain/ptime/assign_employee_ids.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,25 @@ def map_employees(should_map)
mapped_people_count = 0

@ptime_employees.each do |ptime_employee|
ptime_employee_firstname = ptime_employee['attributes']['firstname']
ptime_employee_lastname = ptime_employee['attributes']['lastname']
ptime_employee_firstname = ptime_employee[:attributes][:firstname]
ptime_employee_lastname = ptime_employee[:attributes][:lastname]
ptime_employee_name = "#{ptime_employee_firstname} #{ptime_employee_lastname}"
ptime_employee_email = ptime_employee['attributes']['email']
ptime_employee_email = ptime_employee[:attributes][:email]
matched_skills_people = Person.where(ptime_employee_id: nil)
.where(name: ptime_employee_name)
.where(email: ptime_employee_email)

if matched_skills_people.empty?
unmatched_entries << { name: ptime_employee_name, id: ptime_employee['id'] }
unmatched_entries << { name: ptime_employee_name, id: ptime_employee[:id] }
elsif matched_skills_people.one?
if should_map
matched_skills_person = matched_skills_people.first
matched_skills_person.ptime_employee_id = ptime_employee['id']
matched_skills_person.ptime_employee_id = ptime_employee[:id]
matched_skills_person.save!
end
mapped_people_count += 1
else
ambiguous_entries << { name: ptime_employee_name, id: ptime_employee['id'] }
ambiguous_entries << { name: ptime_employee_name, id: ptime_employee[:id] }
end
end

Expand All @@ -60,7 +60,7 @@ def map_employees(should_map)

def fetch_data
puts 'Fetching required data...'
@ptime_employees = Ptime::Client.new.get('employees', { per_page: 1000 })['data']
@ptime_employees = Ptime::Client.new.request(:get, 'employees', { per_page: 1000 })
@skills_people = Person.all
puts 'Successfully fetched data'
end
Expand Down
49 changes: 26 additions & 23 deletions app/domain/ptime/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,41 @@ def initialize
@base_url = "#{ENV.fetch('PTIME_BASE_URL')}/api/v1/"
end

def get(endpoint, params = {})
request(:get, @base_url + endpoint, params)
def request(method, endpoint, params = {})
path = @base_url + endpoint

if last_ptime_error_more_than_5_minutes_ago?
send_request_and_parse_response(method, path, params)
else
raise CustomExceptions::PTimeClientError, 'Error'
end
end

private

def request(method, path, params = nil)
path = "#{path}?#{URI.encode_www_form(params)}"
response = RestClient.send(method, path, headers)
JSON.parse(response.body)
rescue RestClient::BadRequest => e
msg = response_error_message(e)
e.message = msg if msg.present?
raise e
end
def last_ptime_error_more_than_5_minutes_ago?
last_request_time = ENV.fetch('LAST_PTIME_ERROR', nil)
return true if last_request_time.nil?

def response_error_message(exception)
JSON.parse(exception.response.body).dig('error', 'message')
rescue JSON::ParserError # rescue only JSON parsing errors
nil
last_request_time.to_datetime <= 5.minutes.ago
end

def headers
{
authorization: "Basic #{basic_token}",
content_type: :json,
accept: :json
}
def ptime_request(method, url)
RestClient::Request.new(
:method => method,
:url => url,
:user => ENV.fetch('PTIME_API_USERNAME'),
:password => ENV.fetch('PTIME_API_PASSWORD'),
:headers => { :accept => :json, :content_type => :json }
)
end

def basic_token
Base64.encode64("#{ENV.fetch('PTIME_API_USERNAME')}:#{ENV.fetch('PTIME_API_PASSWORD')}")
def send_request_and_parse_response(method, url, params)
url += "?#{params.to_query}" if method == :get && params.present?
response = ptime_request(method, url).execute
JSON.parse(response.body, symbolize_names: true)[:data]
rescue RestClient::ExceptionWithResponse
raise CustomExceptions::PTimeClientError, 'Error'
end
end
end
12 changes: 6 additions & 6 deletions app/domain/ptime/update_people_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ class UpdatePeopleData

# rubocop:disable Metrics
def run
ptime_employees = Ptime::Client.new.get('employees', { per_page: 1000 })['data']
ptime_employees = Ptime::Client.new.request(:get, 'employees', { per_page: 1000 })
ptime_employees.each do |ptime_employee|
ptime_employee_firstname = ptime_employee['attributes']['firstname']
ptime_employee_lastname = ptime_employee['attributes']['lastname']
ptime_employee_firstname = ptime_employee[:attributes][:firstname]
ptime_employee_lastname = ptime_employee[:attributes][:lastname]
ptime_employee_name = "#{ptime_employee_firstname} #{ptime_employee_lastname}"

skills_person = Person.find_by(ptime_employee_id: ptime_employee['id'])
skills_person = Person.find_by(ptime_employee_id: ptime_employee[:id])
skills_person ||= Person.new

skills_person.name = ptime_employee_name
skills_person.ptime_employee_id ||= ptime_employee['id']
ptime_employee['attributes'].each do |key, value|
skills_person.ptime_employee_id ||= ptime_employee[:id]
ptime_employee[:attributes].each do |key, value|
if key.to_sym.in?(ATTRIBUTE_MAPPING.keys)
skills_person[ATTRIBUTE_MAPPING[key.to_sym]] = value
end
Expand Down
5 changes: 5 additions & 0 deletions app/exceptions/custom_exceptions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module CustomExceptions

class PTimeClientError < StandardError; end

end
4 changes: 4 additions & 0 deletions app/helpers/auth_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ def find_person_by_auth_user
def devise?
AuthConfig.keycloak? || Rails.env.test?
end

def ptime_available?
ActiveModel::Type::Boolean.new.cast(ENV.fetch('PTIME_API_ACCESSIBLE', true))
end
end
33 changes: 33 additions & 0 deletions app/helpers/person_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,37 @@ def not_rated_default_skills(person)
certificate: false, core_competence: false })
end
end

def sorted_people
fetch_ptime_or_skills_data.sort_by { |e| e.first.downcase }
end

def fetch_ptime_or_skills_data
all_skills_people = Person.all.map { |p| [p.name, person_path(p)] }
return all_skills_people unless ptime_available?

ptime_employees = Ptime::Client.new.request(:get, 'employees', { per_page: 1000 })
build_dropdown_data(ptime_employees)
rescue CustomExceptions::PTimeClientError
ENV['LAST_PTIME_ERROR'] = DateTime.current.to_s
all_skills_people
end

def build_dropdown_data(ptime_employees)
ptime_employees.map do |ptime_employee|
ptime_employee_name = append_ptime_employee_name(ptime_employee)
skills_person = Person.find_by(ptime_employee_id: ptime_employee[:id])
ptime_employee_id = ptime_employee[:id]
already_exists = ptime_employee_id.in?(Person.pluck(:ptime_employee_id))
path = new_person_path(ptime_employee_id: ptime_employee_id)
path = person_path(skills_person) if already_exists

[ptime_employee_name, path]
end
end

# Once https://github.com/puzzle/skills/issues/744 is merged there should be no need for this
def append_ptime_employee_name(ptime_employee)
"#{ptime_employee[:attributes][:firstname]} #{ptime_employee[:attributes][:lastname]}"
end
end
4 changes: 2 additions & 2 deletions app/helpers/select_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

module SelectHelper
def select_when_availabale(obj)
selected = obj ? obj.id : ''
prompt = obj ? false : true
selected = obj.present? ? polymorphic_path(obj) : ''
prompt = obj.nil?
{ selected: selected, prompt: prompt, disabled: '' }
end

Expand Down
2 changes: 1 addition & 1 deletion app/javascript/controllers/dropdown_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export default class extends Controller {
}

handleChange(event) {
window.location.href = event.target.dataset.value + event.target.value;
window.location.href = event.target.value;
}
}
2 changes: 1 addition & 1 deletion app/views/people/_search.html.haml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%div.d-flex.align-items-center.justify-content-between
%div.d-flex.col-9.gap-3
%span.col-6{"data-controller": "dropdown"}
= collection_select :person_id, :person, Person.all.sort_by {|p| p.name.downcase }, :id, :name, select_when_availabale(person), {data:{"dropdown-target": "dropdown" , action: "change->dropdown#handleChange", value: "/people/"}}
= select :person_id, :person, options_for_select(sorted_people, select_when_availabale(person)), {prompt: person.nil?}, {data: { "dropdown-target" => "dropdown", action: "change->dropdown#handleChange"}}
%div.d-flex.align-items-center.text-gray
= "#{t 'profile.updated_at'}: #{@person&.last_updated_at.strftime("%d.%m.%Y")}" if @person&.last_updated_at
%a.d-flex.justify-content-between#new-person-button{href: "/people/new"}
Expand Down
5 changes: 0 additions & 5 deletions bin/delayed_job

This file was deleted.

2 changes: 0 additions & 2 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,5 @@ class Application < Rails::Application

config.assets.enabled = true
config.assets.paths << Rails.root.join("uploads")

config.active_job.queue_adapter = :delayed_job
end
end
22 changes: 0 additions & 22 deletions db/migrate/20240701085558_create_delayed_jobs.rb

This file was deleted.

17 changes: 1 addition & 16 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2024_07_01_085558) do
ActiveRecord::Schema[7.0].define(version: 2024_06_24_122411) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -77,21 +77,6 @@
t.datetime "updated_at", precision: nil, null: false
end

create_table "delayed_jobs", force: :cascade do |t|
t.integer "priority", default: 0, null: false
t.integer "attempts", default: 0, null: false
t.text "handler", null: false
t.text "last_error"
t.datetime "run_at"
t.datetime "locked_at"
t.datetime "failed_at"
t.string "locked_by"
t.string "queue"
t.datetime "created_at"
t.datetime "updated_at"
t.index ["priority", "run_at"], name: "delayed_jobs_priority"
end

create_table "departments", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ services:
/bin/bash -c "
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - &&
apt-get install -y nodejs &&
npm install -g yarn && bin/assets &&
npm install -g yarn && yarn add nodemon esbuild && bin/assets &&
sleep infinity"
volumes:
- ./:/myapp
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"autoprefixer": "^10.4.17",
"bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.3",
"esbuild": "^0.20.0",
"nodemon": "^3.0.3",
"esbuild": "^0.23.0",
"nodemon": "^3.1.4",
"postcss": "^8.4.33",
"postcss-cli": "^11.0.0",
"sass": "^1.70.0",
Expand Down
Loading