# frozen_string_literal: true require "json" require "net/http" require "provider/adapters/adapter" class Provider module Adapters # Bank of Thailand. Fetches daily average commercial bank exchange rates # for 19 currencies against the Thai baht (THB). Uses mid_rate (midpoint # of buying transfer and selling). Some currencies are quoted per 100 or # 1,000 units — the adapter normalises to per-unit rates. # Requires BOT_API_KEY environment variable. class BOT < Adapter BASE_URL = "https://gateway.api.bot.or.th/Stat-ExchangeRate/v2/DAILY_AVG_EXG_RATE/" class << self def api_key = ENV["BOT_API_KEY"] || raise(Adapter::Unavailable, "no API key") def backfill_range = 30 # API enforces max 31-day period per request end def fetch(after: nil, upto: nil) uri = URI(BASE_URL) uri.query = URI.encode_www_form( start_period: after.strftime("%Y-%m-%d"), end_period: (upto || Date.today).strftime("%Y-%m-%d"), ) response = Net::HTTP.get_response(uri, { "Authorization" => self.class.api_key, "Accept" => "application/json", }) parse(response.body) end def parse(body) data = JSON.parse(body).dig("result", "data", "data_detail") return [] unless data data.filter_map do |record| mid = record["mid_rate"] next if mid.nil? || mid.to_s.empty? rate = Float(mid) next if rate.zero? currency = record["currency_id"] unit = extract_unit(record["currency_name_eng"]) rate /= unit if unit > 1 { date: Date.parse(record["period"]), base: currency, quote: "THB", rate: } end end private def extract_unit(name) case name when /\(100 /i then 100 when /\(1,000 /i then 1_000 else 1 end end end end end