# frozen_string_literal: true require 'date' require 'time' require 'arbetsformedlingen/api/request' require 'arbetsformedlingen/api/results/matchning_result' module Arbetsformedlingen module API # API client for matchning class MatchningClient attr_reader :request # Initialize client def initialize(request: Request.new) @request = request end # rubocop:disable Metrics/LineLength # Find matching ads from API # @return [MatchningResult] the result. # @param area_id [String] Area ID. # @param county_id [String] County ID. # @param municipality_id [String] Municipality ID. # @param occupation_id [String] Occupation ID. # @param keywords [String] Keywords. # @param page [Integer] Page ID. # @param page_size [Integer] Page size ID. # @param occupation_group_id [String] Occupation_group ID. # @param employment_type [String] Employment type ID. # @param occupation_field_id [String] Occupation field ID. # @param published_after [Time, Date, String] Published after ID (ISO8601 format: YYYY-MM-DDThh:mm:ssTZD). # @param organization_number [String] Organization_number ID. # @example Get ads within county # client.ads(county: id) # @example Get ads within municipality # client.ads(municipality: id) # @example Get ads with keyword # client.ads(keywrods: 'ruby') # @example Get ads with keyword on page 3 and with a page size of 10 # client.ads(keywrods: 'ruby', page: 3, page_size: 10) # @example Get ads with keyword and organsiation numer # client.ads(keywrods: 'ruby', organization_number: org_no) # rubocop:enable Metrics/LineLength def ads( # one of these must be present county_id: nil, municipality_id: nil, occupation_id: nil, keywords: nil, # optional page: 1, page_size: 30, area_id: nil, occupation_group_id: nil, employment_type: nil, occupation_field_id: nil, published_after: nil, organization_number: nil ) one_of_required = [county_id, municipality_id, occupation_id, keywords] if one_of_required.all?(&:nil?) error_message = 'One of: county_id, municipality_id, occupation_id, keywords is required' # rubocop:disable Metrics/LineLength raise ArgumentError, error_message end # TODO: Should we validate the IDs passed? What if they're invalid? Do we crash? # # Currently when an invalid value is passed MatchningResult::build returns # => KeyError: key not found: "matchningslista" # which isn't really helpful.. query = { lanid: county_id, kommunid: municipality_id, yrkesid: occupation_id, nyckelord: santize_keywords_query(keywords), sida: page, antalrader: page_size, omradeid: area_id, yrkesgruppid: occupation_group_id, anstallningstyp: santize_employment_type_query(employment_type), yrkesomradeid: occupation_field_id, sokdatum: normalize_date_to_iso8601(published_after), organisationsnummer: organization_number, } response = request.get('matchning', query: query) MatchningResult.build(response) end private # @raise [ArgumentError] raises error if passed invalid value def normalize_date_to_iso8601(date_time_or_string) return unless date_time_or_string time = date_time_or_string time = time.to_time if time.is_a?(Date) time = Time.parse(time) if time.is_a?(String) time.iso8601 end def santize_employment_type_query(employment_type) # Sökkriterier anställningstyp. # Värdena ska ligga mellan 1 och 3. # 1 är XXX (EJ DOKUMENTERAT) # 2 är somarjobb / feriejobb # 3 är utlandsjobb # TODO: The question is what we do if an invalid parameter is passed # should we crash? employment_type end def santize_keywords_query(keywords) # # Sökord kan separeras eller kombineras med något av följande exempel: # mellanslag (" ") # # [Example] # /matchning?nyckelord="bagare""test" # /matchning?nyckelord="bagare"OR"test" /matchning?nyckelord="automatisk"AND"test" # Valid characters # abcdefghijklmnopqrstuvwxyzåäö0123456789: ,.-" # TODO: What do we do if invalid characters are passed? Crash? keywords end end end end