class PortalScraper::Accounts::Client
Constants
- CODE_TO_COUNTRY_MAPPING
- IS_POSTAL_CODE_DOM
- MINIMUM_AMOUNT
- PROPOSITION_INDEX
Attributes
app_id[RW]
secret[RW]
Public Class Methods
new(app_id = nil, secret = nil)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 16 def initialize(app_id = nil, secret = nil) @app_id = app_id || config.app_id @secret = secret || config.secret raise BadRootUrl unless config.root_url =~ URI::DEFAULT_PARSER.make_regexp end
Public Instance Methods
create_account(user)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 69 def create_account(user) login app.get(url_for('/appTiersCreation.do')) do |create_page| create_page.form_with(name: /(create|creation)/i) do |form| form.fields.each { |f| try_form_fields(form, [f.name], user[f.name.to_sym]) } if user[:codeInsee].present? form['commune'] = user[:codeInsee] form['libCommune'] = user[:ville] else fill_commune(app, form, user[:codePostal], parse_city_name(user[:ville])) end fill_address(form, user[:numeroVoie]) fill_birth_place(form, user[:paysNaissance]) form['modeContact'] = '' form['creerTiers'] = 'Créer' form.submit result_page = app.post(url_for('/appTiersCreation.do'), { confirmer: 'Confirmer' }) if result_page.uri.path =~ /error.do/ return { error: 'Missing data' } else ref = result_page.search('td.ZMSG').text.split(':')[1].strip return { client_ref: ref } end end end nil rescue => e { error: e.message } end
create_proposition(client_ref)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 99 def create_proposition(client_ref) login app.get(url_for('/appRecherche.do')) do |search_user_page| search_user_page.form_with(name: /(frmCritRech)/i) do |form| form['idTiers'] = client_ref result_page = form.click_button result_page.links.find { |l| l.text.strip == client_ref }.click app.get(url_for('/propositionList.do')) return { proposition_ref: proposition } end end nil end
scrap_accounts_balance() { |account_data| ... }
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 22 def scrap_accounts_balance login accounts_data = { accounts: [] } user_page = app.post(url_for('/appRecherche.do'), { nom: '', prenom: '', chercher: 'Chercher' }) loop do user_page.links_with(href: /appTiersDetail.do/).each do |link| account = link.click selected_link = nil opened_on, balance = nil, 0.to_d account.links_with(css: 'table#contrat td a').each do |account_link| row = account_link.node.ancestors('tr') next unless row.at('td[1]').text.strip == 'Compte épargne rémunéré' row_date = parse_date(row.at('td[2]')) next unless opened_on.nil? || opened_on < row_date selected_link = account_link opened_on = row_date balance = parse_number(row.at('td[5]')) end next unless selected_link transfers = scrap_transfers(selected_link) account_data = { client_ref: find_table_value(account, 'Identifiant tiers'), balance: balance, opened_on: opened_on, transfers: transfers, } if block_given? yield(account_data) else accounts_data[:accounts] << account_data end end break unless user_page.search('.pg_next').present? # Need to fetch the first page as you cannot navigate from client back to research page app.post(url_for('/appRecherche.do'), { nom: '', prenom: '', chercher: 'Chercher' }) user_page = app.get(user_page.search('a.pg_next').first['href']) end accounts_data end
Private Instance Methods
app()
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 115 def app @app ||= Mechanize.new end
config()
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 189 def config PortalScraper.config end
fill_address(form, address)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 171 def fill_address(form, address) address, additional_information = address.split("\n") form['numeroVoie'] = address if additional_information form['lieudit'] = additional_information end end
fill_birth_place(form, country_code)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 179 def fill_birth_place(form, country_code) form['paysNaissance'] = country_code form['libPaysNaissance'] = CODE_TO_COUNTRY_MAPPING.dig(country_code, 'name') form['territoireNaissance'] = CODE_TO_COUNTRY_MAPPING.dig(country_code, 'category') end
fill_commune(app, form, postal_code, city)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 160 def fill_commune(app, form, postal_code, city) app.post(url_for('/tiersCommunes.do'), { codPos: postal_code }).tap do |mappings| cities = mappings.search('td.t').map { |c| { code: c.parent.search('a.PL_LST').text.strip, name: c.text.strip } } matched_city = cities.find(-> { cities.first }) { |c| c[:name].include?(city) } raise "City '#{city}' and postcode '#{postal_code}' not found" unless matched_city form['commune'] = matched_city[:code] form['libCommune'] = matched_city[:name] end form['territoireRes'] = IS_POSTAL_CODE_DOM.dig(postal_code[0..2], 'category') || 0 end
find_table_value(node, column_name)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 185 def find_table_value(node, column_name) node.search('td.CA_LABEL').find { |column| column.text.strip == column_name }.parent.search('td.CA_LIB').text.strip end
login()
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 123 def login raise BadLoginUrl if config.login_url.nil? app.get(url_for(config.login_url)) do |login_page| form = login_page.form_with(name: /login/i) || login_page.forms[0] try_form_fields(form, %w(username login), app_id) try_form_fields(form, %w(password secret), secret) form.submit end app.get(url_for(config.token_url)) unless config.token_url.nil? end
proposition()
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 134 def proposition proposition_page = app.get(url_for('/propositionDetail.do'), { idx: PROPOSITION_INDEX }) proposition_form = proposition_page.form_with(name: /proposition/i) try_form_fields(proposition_form, %w(montant amount), MINIMUM_AMOUNT) proposition_form['regimeFiscal'] = 'I' proposition_form.click_button app.get(url_for('/propositionCreate.do')) confirmation_page = app.get(url_for('/propositionConfirm.do')) if confirmation_page.uri.path =~ /error.do/ return { error: 'Missing data' } end text = confirmation_page.search('td.ZMSG').text.strip proposition_ref = text.match('\d{9}')[0] app.get(url_for('/propositionImprimer.do')) proposition_ref end
scrap_transfers(account_link)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 193 def scrap_transfers(account_link) transfers_page = account_link.click transfers_page.search('table#operation tbody tr').map do |transfer_row| { operation_date: parse_date(transfer_row.search('td[1]')), nature: transfer_row.search('td[2]').text.strip.gsub(/[\n,\t,'']/, ''), value_date: parse_date(transfer_row.search('td[3]')), debit: parse_number(transfer_row.search('td[4]')), credit: parse_number(transfer_row.search('td[5]')), } end end
try_form_fields(form, fields, value)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 151 def try_form_fields(form, fields, value) fields.each do |field| if form.has_field?(field) form[field] = value break end end end
url_for(path)
click to toggle source
# File lib/portal_scraper/accounts/client.rb, line 119 def url_for(path) [config.root_url, path].join end