diff --git a/app/assets/stylesheets/new_design/stats.scss b/app/assets/stylesheets/new_design/stats.scss index 7084571b0..9eb1e5d2d 100644 --- a/app/assets/stylesheets/new_design/stats.scss +++ b/app/assets/stylesheets/new_design/stats.scss @@ -63,6 +63,12 @@ $stat-card-half-horizontal-spacing: 4 * $default-space; width: 200px; } +.stat-card-details { + font-size: 13px; + text-align: center; + font-style: italic; +} + $segmented-control-margin-top: $default-space; .segmented-control { diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 6546c6eda..2f6b5b3a8 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -13,6 +13,10 @@ class StatsController < ApplicationController @dossiers_numbers = dossiers_numbers(dossiers) @satisfaction_usagers = satisfaction_usagers + + @contact_percentage = contact_percentage + @contact_percentage_excluded_tags = Helpscout::UserConversationsAdapter::EXCLUDED_TAGS + @dossiers_states = dossiers_states @procedures_cumulative = cumulative_hash(procedures, :published_at) @@ -160,6 +164,24 @@ class StatsController < ApplicationController end end + def contact_percentage + from = Date.new(2017, 10) + to = Date.today.prev_month + + Helpscout::UserConversationsAdapter.new(from, to) + .reports + .map do |monthly_report| + start_date = monthly_report[:start_date].to_time.localtime + end_date = monthly_report[:end_date].to_time.localtime + replies_count = monthly_report[:conversations_count] + + dossiers_count = Dossier.where(en_construction_at: start_date..end_date).count + + monthly_contact_percentage = replies_count.fdiv(dossiers_count || 1) * 100 + [I18n.l(start_date, format: '%b %y'), monthly_contact_percentage.round(1)] + end + end + def cloned_from_library_procedures_ratio [3.weeks.ago, 2.weeks.ago, 1.week.ago].map do |date| min_date = date.beginning_of_week diff --git a/app/lib/helpscout/api.rb b/app/lib/helpscout/api.rb index fa172b8d4..1b321b166 100644 --- a/app/lib/helpscout/api.rb +++ b/app/lib/helpscout/api.rb @@ -59,6 +59,22 @@ class Helpscout::API end end + def conversations_report(year, month) + Rails.logger.info("[HelpScout API] Retrieving conversations report for #{month}-#{year}…") + + params = { + start: Time.utc(year, month).iso8601, + end: Time.utc(year, month).next_month.iso8601 + } + + response = call_api(:get, 'reports/conversations?' + params.to_query) + if !response.success? + raise StandardError, "Error while fetching conversation report: #{response.status} '#{response.body}'" + end + + parse_response_body(response) + end + private def attachments(file) diff --git a/app/lib/helpscout/user_conversations_adapter.rb b/app/lib/helpscout/user_conversations_adapter.rb new file mode 100644 index 000000000..6b265e13e --- /dev/null +++ b/app/lib/helpscout/user_conversations_adapter.rb @@ -0,0 +1,49 @@ +# Fetch and compute monthly reports about the users conversations on Helpscout +class Helpscout::UserConversationsAdapter + EXCLUDED_TAGS = ['openlab', 'bizdev', 'admin', 'webinaire'] + + def initialize(from, to) + @from = from + @to = to + end + + # Return an array of monthly reports + def reports + @reports ||= (@from..@to) + .group_by { |date| [date.year, date.month] } + .keys + .map { |key| { year: key[0], month: key[1] } } + .map { |interval| report(interval[:year], interval[:month]) } + end + + private + + def report(year, month) + report = fetch_conversations_report(year, month) + + total_conversations = report.dig(:current, :totalConversations) + excluded_conversations = report + .dig(:tags, :top) + .select { |tag| tag[:name]&.in?(EXCLUDED_TAGS) } + .map { |tag| tag[:count] } + .sum + + { + start_date: report.dig(:current, :startDate).to_datetime, + end_date: report.dig(:current, :endDate).to_datetime, + conversations_count: total_conversations - excluded_conversations + } + end + + def fetch_conversations_report(year, month) + if year == Date.today.year && month == Date.today.month + raise ArgumentError, 'The report for the current month will change in the future, and cannot be cached.' + end + + @helpscout_api ||= Helpscout::API.new + + Rails.cache.fetch("helpscout-conversation-report-#{year}-#{month}") do + @helpscout_api.conversations_report(year, month) + end + end +end diff --git a/app/views/stats/index.html.haml b/app/views/stats/index.html.haml index e44fc1174..80b46b8d6 100644 --- a/app/views/stats/index.html.haml +++ b/app/views/stats/index.html.haml @@ -28,6 +28,19 @@ = line_chart @satisfaction_usagers, colors: ["#15AD70", "#F28900", "rgba(161, 0, 5, 0.9)"] + .stat-card.stat-card-half.pull-left + %span.stat-card-title + Pourcentage de contact usagers + + .chart-container + .chart + = line_chart @contact_percentage + + .stat-card-details + %abbr{ title: "À l’exception des conversations taggées #{@contact_percentage_excluded_tags.join(', ')}" } + Nombre de conversations actives dans HelpScout + %span / nombre de dossiers déposés + .stat-card.stat-card-half.pull-left %span.stat-card-title Répartition des dossiers diff --git a/spec/fixtures/cassettes/helpscout_conversations_reports.yml b/spec/fixtures/cassettes/helpscout_conversations_reports.yml new file mode 100644 index 000000000..6fa4c21b8 --- /dev/null +++ b/spec/fixtures/cassettes/helpscout_conversations_reports.yml @@ -0,0 +1,150 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.helpscout.net/v2/oauth2/token + body: + encoding: UTF-8 + string: client_id&client_secret&grant_type=client_credentials + headers: + User-Agent: + - demarches-simplifiees.fr + Expect: + - '' + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - no-store + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 13 Dec 2018 12:49:04 GMT + Pragma: + - no-cache + Content-Length: + - '92' + Connection: + - keep-alive + body: + encoding: UTF-8 + string: '{"token_type":"bearer","access_token":"18mock9b","expires_in":7200} + +' + http_version: + recorded_at: Thu, 13 Dec 2018 12:49:05 GMT +- request: + method: get + uri: https://api.helpscout.net/v2/reports/conversations?end=2017-12-01T00:00:00Z&start=2017-11-01T00:00:00Z + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Authorization: + - Bearer 18mock9b + Content-Type: + - application/json; charset=UTF-8 + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Type: + - application/json;charset=UTF-8 + Correlation-Id: + - a6ee3949-ec16-4b39-92bc-3600adc3f671#144730730 + Date: + - Thu, 13 Dec 2018 12:49:05 GMT + Expires: + - '0' + Pragma: + - no-cache + X-Content-Type-Options: + - nosniff + - nosniff + X-Frame-Options: + - DENY + X-Ratelimit-Limit-Minute: + - '200' + X-Ratelimit-Remaining-Minute: + - '199' + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '5434' + Connection: + - keep-alive + body: + encoding: ASCII-8BIT + string: !binary |- + eyJyZXBsaWVzIjp7ImNvdW50IjoyMTYsInRvcCI6W3sibmFtZSI6Ik1hdXZhaXMgaW50ZXJsb2N1dGV1ciIsImlkIjo3MjczOTYsIm1haWxib3hJZCI6MTI1OTI2LCJjb3VudCI6OSwicGVyY2VudCI6NC4xNjY2NjY2NjY2NjY2NjZ9LHsibmFtZSI6IkRlbWFuZGUgZGUgZMOpbW8sIHN0ZXAgMSIsImlkIjo3MzIxOTQsIm1haWxib3hJZCI6MTI1OTI2LCJjb3VudCI6NSwicGVyY2VudCI6Mi4zMTQ4MTQ4MTQ4MTQ4MTV9LHsibmFtZSI6IkRlbWFuZGUgY29tcHRlIGFkbWluIHBhcnRpY3VsaWVyIC8gZW50cmVwcmlzZSIsImlkIjo3NTExMzAsIm1haWxib3hJZCI6MTI1OTI2LCJjb3VudCI6MywicGVyY2VudCI6MS4zODg4ODg4ODg4ODg4ODg4fSx7Im5hbWUiOiJTdGVwIDIsIG5vdXZlbGxlIHByb2PDqWR1cmUiLCJpZCI6NzMyMTk1LCJtYWlsYm94SWQiOjEyNTkyNiwiY291bnQiOjIsInBlcmNlbnQiOjAuOTI1OTI1OTI1OTI1OTI1OH1dfSwid29ya2Zsb3dzIjp7ImNvdW50IjoyMTYsInRvcCI6W119LCJ0YWdzIjp7ImNvdW50IjoyMTYsInRvcCI6W3siaWQiOjEsImNvdW50IjoyMTYsInBlcmNlbnQiOjEwMC4wfV19LCJjdXN0b21lcnMiOnsiY291bnQiOjIxNiwidG9wIjpbeyJuYW1lIjoiQ29vY2hlIE1hcmllIiwiaWQiOjE1MDIyNDI5MiwiY291bnQiOjEzLCJwZXJjZW50Ijo2LjAxODUxODUxODUxODUxOH0seyJuYW1lIjoiVnJpZ25hdWQgUGhpbGlwcGUiLCJpZCI6MTQ3NjcwOTY2LCJjb3VudCI6MTIsInBlcmNlbnQiOjUuNTU1NTU1NTU1NTU1NTU1fSx7Im5hbWUiOiJDb3Jpbm5lIExhc25lIiwiaWQiOjE0OTY2NTIyNSwiY291bnQiOjcsInBlcmNlbnQiOjMuMjQwNzQwNzQwNzQwNzQwNX0seyJuYW1lIjoiU2VydmljZSBDbGllbnQgTWFpbGpldCIsImlkIjoxNDg0NTI1MjYsImNvdW50Ijo1LCJwZXJjZW50IjoyLjMxNDgxNDgxNDgxNDgxNX0seyJuYW1lIjoiVCZlYWN1dGU7bCZlYWN1dGU7cHJvYyZlYWN1dGU7ZHVyZXMgU2ltcGxpZmkmZWFjdXRlO2VzIiwiaWQiOjE0NzY2ODE0MSwiY291bnQiOjUsInBlcmNlbnQiOjIuMzE0ODE0ODE0ODE0ODE1fSx7Im5hbWUiOiJNb25iZXQtRHVmYXUgRnJhbiZjY2VkaWw7b2lzIChuYXYtR2VucyBEZSBNZXIpIC0gRGR0bSA2NC9kbWwvYW1sIiwiaWQiOjE1MzMwMzk4NiwiY291bnQiOjQsInBlcmNlbnQiOjEuODUxODUxODUxODUxODUxNn0seyJuYW1lIjoiUGhpbGlwcGUgVnJpZ25hdWQiLCJpZCI6MTQ4OTc0MTk5LCJjb3VudCI6MywicGVyY2VudCI6MS4zODg4ODg4ODg4ODg4ODg4fSx7Im5hbWUiOiJkb21pbmlxdWVAY29sbGFydC5mciIsImlkIjoxNDg4MTA4OTcsImNvdW50IjozLCJwZXJjZW50IjoxLjM4ODg4ODg4ODg4ODg4ODh9LHsibmFtZSI6IkxlYmFzdGFyZCBGcmFuY2sgKGFkam9pbnQgQXUgQ2hlZiBEZSBCdXJlYXUpIC0gRGdhbG4vc2FncC9zZHAvYmNzaSIsImlkIjoxNTI5NzA5ODMsImNvdW50IjozLCJwZXJjZW50IjoxLjM4ODg4ODg4ODg4ODg4ODh9LHsibmFtZSI6IkZyYW1hbGlzdGVzIiwiaWQiOjE1MDkwMTMyNCwiY291bnQiOjMsInBlcmNlbnQiOjEuMzg4ODg4ODg4ODg4ODg4OH0seyJuYW1lIjoiUnVmaW4gQXR0aW5nbGkiLCJpZCI6MTQ4ODM1MTAzLCJjb3VudCI6MywicGVyY2VudCI6MS4zODg4ODg4ODg4ODg4ODg4fSx7Im5hbWUiOiJIdW1hIExhdXRlcmZpbmciLCJpZCI6MTQ3ODE0Njc0LCJjb3VudCI6MywicGVyY2VudCI6MS4zODg4ODg4ODg4ODg4ODg4fSx7Im5hbWUiOiJDc2YtU29pc3NvbnMub3JnIiwiaWQiOjE1MzMzNDE5NiwiY291bnQiOjIsInBlcmNlbnQiOjAuOTI1OTI1OTI1OTI1OTI1OH0seyJuYW1lIjoic2FycmlxdWV0LmNocmlzdGlhbkBvcmFuZ2UuZnIiLCJpZCI6MTUxOTAxNDA5LCJjb3VudCI6MiwicGVyY2VudCI6MC45MjU5MjU5MjU5MjU5MjU4fSx7Im5hbWUiOiJmYWJpZW5uZS5jb3F1ZWxsZUBjYWZub3JkLmNuYWZtYWlsLmZyIiwiaWQiOjE1MDU5MzgzOSwiY291bnQiOjIsInBlcmNlbnQiOjAuOTI1OTI1OTI1OTI1OTI1OH0seyJuYW1lIjoiSiZlYWN1dGU7ciZvY2lyYzttZSBMYXVyZW50IiwiaWQiOjE1MDA3NDM4NywiY291bnQiOjIsInBlcmNlbnQiOjAuOTI1OTI1OTI1OTI1OTI1OH0seyJuYW1lIjoiQXVyJmVhY3V0ZTtsaWUgQ2hhYnJvbCIsImlkIjoxNTE1ODM4MjYsImNvdW50IjoyLCJwZXJjZW50IjowLjkyNTkyNTkyNTkyNTkyNTh9LHsibmFtZSI6IlBpZXJyZS1BbGV4aXMgQmFyYmllciIsImlkIjoxNTEyMzkzMTAsImNvdW50IjoyLCJwZXJjZW50IjowLjkyNTkyNTkyNTkyNTkyNTh9LHsibmFtZSI6IktoYWxlZCBLaGVsaWYiLCJpZCI6MTUwMzc0Mzk3LCJjb3VudCI6MiwicGVyY2VudCI6MC45MjU5MjU5MjU5MjU5MjU4fSx7Im5hbWUiOiJMZSBSaHVuIEVsb2RpZSAoY2hlZiBEZSBCdXJlYXUpIC0gRHJpZWEgSWYvc3N0L2RydHIvYmdjMiIsImlkIjoxNDk1NDcyOTEsImNvdW50IjoyLCJwZXJjZW50IjowLjkyNTkyNTkyNTkyNTkyNTh9LHsibmFtZSI6Ik1hcmluYSBMYXVyZSIsImlkIjoxNTQzMjU3MDUsImNvdW50IjoyLCJwZXJjZW50IjowLjkyNTkyNTkyNTkyNTkyNTh9LHsibmFtZSI6IlBsYW1vdWNoZSIsImlkIjoxNDk3MTQ0OTUsImNvdW50IjoyLCJwZXJjZW50IjowLjkyNTkyNTkyNTkyNTkyNTh9LHsibmFtZSI6IlRpcGhhbmllIFRoYXZhdWQiLCJpZCI6MTUyNDM4MDQ3LCJjb3VudCI6MiwicGVyY2VudCI6MC45MjU5MjU5MjU5MjU5MjU4fSx7Im5hbWUiOiJBenVyJmVhY3V0ZTtlbm5lIExvY2F0aW9uIiwiaWQiOjE1MTEzMjA4MywiY291bnQiOjIsInBlcmNlbnQiOjAuOTI1OTI1OTI1OTI1OTI1OH0seyJuYW1lIjoiSXNhYmVsbGUgUmVuYXJkIC8gU2VydmljZSBRdWFsaXQmZWFjdXRlOyIsImlkIjoxNTExMTI1MzcsImNvdW50IjoyLCJwZXJjZW50IjowLjkyNTkyNTkyNTkyNTkyNTh9LHsibmFtZSI6IkNhZmZpZXIgQXVyJmVhY3V0ZTtsaWVuIiwiaWQiOjE0OTY3NzE0OCwiY291bnQiOjIsInBlcmNlbnQiOjAuOTI1OTI1OTI1OTI1OTI1OH0seyJuYW1lIjoiSmFjcXVlbGluZSBHYXJjaWEiLCJpZCI6MTQ5MTk0NDcwLCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJSZW5hcmQgTWFydGluZSIsImlkIjoxNDkwNDg0MDksImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IkZsb3JlbmNlIENhbXBlbm9uIENvbW11bmljYXRpb24iLCJpZCI6MTQ5Mjc0NzA4LCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJjZXNhcmluZS5ndWVpQGFycy5zYW50ZS5mciIsImlkIjoxNDg2Njc5NTgsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IlNlcmdlbnQgQmVydHJhbmQiLCJpZCI6MTQ3OTY3NzY3LCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJDJmVhY3V0ZTtjaWxlIFRhbWJ1cmluaSIsImlkIjoxNDg0OTcxOTcsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IlBoaWxpcHBlIFNhbmNoZXoiLCJpZCI6MTQ5NDkwNjE5LCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJKb2VsbGUgR3VlbHRvbiBKb2d1ZWx0b25AYXBvZ2VpOTQubmV0IiwiaWQiOjE0ODA0MDcxMywiY291bnQiOjEsInBlcmNlbnQiOjAuNDYyOTYyOTYyOTYyOTYyOX0seyJuYW1lIjoiRmxvcmVuY2UgRGV6aWVyZSIsImlkIjoxNDc4NDA5MjYsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IkJlbmphbWluIEhlbmtlbCIsImlkIjoxNDc3MDM2NzcsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6Im1hbnVlbGEubW9udGF5QGNhZnBhcy1kZS1jYWxhaXMuY25hZm1haWwuZnIiLCJpZCI6MTQ4MTU2OTQ4LCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJTZXJ2YW5lIENoYXV2ZWwiLCJpZCI6MTQ4ODUzMjEyLCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJJdmFuIENvbGxvbWJldCIsImlkIjoxNDgxMjcyMTQsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IlNpJmVncmF2ZTtnZSIsImlkIjoxNDg2MjAzMjcsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IkJhIE91bWFyIiwiaWQiOjE0ODM1ODMxNCwiY291bnQiOjEsInBlcmNlbnQiOjAuNDYyOTYyOTYyOTYyOTYyOX0seyJuYW1lIjoiaXNhYmVsbGUubWFydGluQGRyanNjcy5nb3V2LmZyIiwiaWQiOjE0ODY1OTU4NywiY291bnQiOjEsInBlcmNlbnQiOjAuNDYyOTYyOTYyOTYyOTYyOX0seyJuYW1lIjoiY2xhdWRlLnJlbm91QGdhcmFudC1jbmRwLmZyIiwiaWQiOjE0OTMwOTM1NCwiY291bnQiOjEsInBlcmNlbnQiOjAuNDYyOTYyOTYyOTYyOTYyOX0seyJuYW1lIjoiSmVhbi1ZdmVzIENyZXVzb3QiLCJpZCI6MTQ3ODYwOTQxLCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJBbGFpbiBBbmRyZSIsImlkIjoxNDgxMzkxODgsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IkhlcnYmZWFjdXRlOyBTaW9uIiwiaWQiOjE0NzgyMTk2NywiY291bnQiOjEsInBlcmNlbnQiOjAuNDYyOTYyOTYyOTYyOTYyOX0seyJuYW1lIjoiTWljaCZlZ3JhdmU7bGUgU3BhY2sgLyBTdCZlYWN1dGU7IFNpc3RyYSIsImlkIjoxNDg4Mzk4NjAsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9LHsibmFtZSI6IlJlbmFyZCBPbGl2aWVyIiwiaWQiOjE0ODQ4OTQ3OSwiY291bnQiOjEsInBlcmNlbnQiOjAuNDYyOTYyOTYyOTYyOTYyOX0seyJuYW1lIjoiU3lsdmllIEdhYnJpZWwiLCJpZCI6MTQ3ODUyMzI1LCJjb3VudCI6MSwicGVyY2VudCI6MC40NjI5NjI5NjI5NjI5NjI5fSx7Im5hbWUiOiJCb2lzc29uIFRob21hcyIsImlkIjoxNDc4MTQ3OTUsImNvdW50IjoxLCJwZXJjZW50IjowLjQ2Mjk2Mjk2Mjk2Mjk2Mjl9XX0sImJ1c2llc3REYXkiOnsiZGF5Ijo0LCJob3VyIjowLCJjb3VudCI6NDZ9LCJmaWx0ZXJUYWdzIjpbXSwiYnVzeVRpbWVFbmQiOjE1LCJidXN5VGltZVN0YXJ0IjoxMywidGFnSWRzIjpbIjEiXSwiY3VycmVudCI6eyJzdGFydERhdGUiOiIyMDE3LTExLTAxVDAwOjAwOjAwWiIsImVuZERhdGUiOiIyMDE3LTEyLTAxVDAwOjAwOjAwWiIsInRvdGFsQ29udmVyc2F0aW9ucyI6MjE2LCJjb252ZXJzYXRpb25zQ3JlYXRlZCI6MTc4LCJuZXdDb252ZXJzYXRpb25zIjoxNzgsImN1c3RvbWVycyI6MTUwLCJtZXNzYWdlc1JlY2VpdmVkIjoyOTMsImNvbnZlcnNhdGlvbnNQZXJEYXkiOjZ9LCJjdXN0b21GaWVsZHMiOnsiZmllbGRzIjpbXSwiY291bnQiOjB9fQ== + http_version: + recorded_at: Thu, 13 Dec 2018 12:49:05 GMT +- request: + method: get + uri: https://api.helpscout.net/v2/reports/conversations?end=2018-01-01T00:00:00Z&start=2017-12-01T00:00:00Z + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - demarches-simplifiees.fr + Authorization: + - Bearer 18mock9b + Content-Type: + - application/json; charset=UTF-8 + Expect: + - '' + response: + status: + code: 200 + message: '' + headers: + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Type: + - application/json;charset=UTF-8 + Correlation-Id: + - 9b1a2413-9d2a-4605-9791-b191ea62b838#53820636 + Date: + - Thu, 13 Dec 2018 12:49:05 GMT + Expires: + - '0' + Pragma: + - no-cache + X-Content-Type-Options: + - nosniff + - nosniff + X-Frame-Options: + - DENY + X-Ratelimit-Limit-Minute: + - '200' + X-Ratelimit-Remaining-Minute: + - '198' + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '5622' + Connection: + - keep-alive + body: + encoding: ASCII-8BIT + string: !binary |- + eyJyZXBsaWVzIjp7ImNvdW50IjoxNDEsInRvcCI6W3sibmFtZSI6Ik1hdXZhaXMgaW50ZXJsb2N1dGV1ciIsImlkIjo3MjczOTYsIm1haWxib3hJZCI6MTI1OTI2LCJjb3VudCI6MTYsInBlcmNlbnQiOjExLjM0NzUxNzczMDQ5NjQ1NH0seyJuYW1lIjoiRGVtYW5kZSBjb21wdGUgYWRtaW4gcGFydGljdWxpZXIgLyBlbnRyZXByaXNlIiwiaWQiOjc1MTEzMCwibWFpbGJveElkIjoxMjU5MjYsImNvdW50Ijo4LCJwZXJjZW50Ijo1LjY3Mzc1ODg2NTI0ODIyN30seyJuYW1lIjoiRGVtYW5kZSBkZSBkw6ltbywgc3RlcCAxIiwiaWQiOjczMjE5NCwibWFpbGJveElkIjoxMjU5MjYsImNvdW50Ijo1LCJwZXJjZW50IjozLjU0NjA5OTI5MDc4MDE0Mn0seyJuYW1lIjoiVXNhZ2VyIGluc2NyaXQgbidhcnJpdmUgcGFzIMOgIGTDqXBvc2VyIGRlIGRvc3NpZXIgW09MRF0iLCJpZCI6NzgyODU2LCJtYWlsYm94SWQiOjEyNTkyNiwiY291bnQiOjUsInBlcmNlbnQiOjMuNTQ2MDk5MjkwNzgwMTQyfSx7Im5hbWUiOiJJbCBzZW1ibGVyYWl0IHF1ZSB2b3VzIGF5ZXogcmVuY29udHLDqSBkZXMgZXJyZXVycywgcHJvYmzDqG1lIHLDqXNvbHUiLCJpZCI6NzI2MTc3LCJtYWlsYm94SWQiOjEyNTkyNiwiY291bnQiOjIsInBlcmNlbnQiOjEuNDE4NDM5NzE2MzEyMDU2OH1dfSwid29ya2Zsb3dzIjp7ImNvdW50IjoxNDEsInRvcCI6W119LCJ0YWdzIjp7ImNvdW50IjoxNDEsInRvcCI6W3siaWQiOjEsImNvdW50IjoxNDEsInBlcmNlbnQiOjEwMC4wfV19LCJjdXN0b21lcnMiOnsiY291bnQiOjE0MSwidG9wIjpbeyJuYW1lIjoiQ29vY2hlIE1hcmllIiwiaWQiOjE1MDIyNDI5MiwiY291bnQiOjcsInBlcmNlbnQiOjQuOTY0NTM5MDA3MDkyMTk5fSx7Im5hbWUiOiJUJmVhY3V0ZTtsJmVhY3V0ZTtwcm9jJmVhY3V0ZTtkdXJlcyBTaW1wbGlmaSZlYWN1dGU7ZXMiLCJpZCI6MTQ3NjY4MTQxLCJjb3VudCI6NSwicGVyY2VudCI6My41NDYwOTkyOTA3ODAxNDJ9LHsibmFtZSI6IlNlcnZpY2UgQ2xpZW50IE1haWxqZXQiLCJpZCI6MTQ4NDUyNTI2LCJjb3VudCI6NCwicGVyY2VudCI6Mi44MzY4Nzk0MzI2MjQxMTM2fSx7Im5hbWUiOiJWcmlnbmF1ZCBQaGlsaXBwZSIsImlkIjoxNDc2NzA5NjYsImNvdW50Ijo0LCJwZXJjZW50IjoyLjgzNjg3OTQzMjYyNDExMzZ9LHsibmFtZSI6IkZyeWRtYW4gTGlvbmVsIC0gRGdpdG0vc2Fncy9hZzIiLCJpZCI6MTU0NjkwMTI2LCJjb3VudCI6MiwicGVyY2VudCI6MS40MTg0Mzk3MTYzMTIwNTY4fSx7Im5hbWUiOiJGaWNoaWVycyBGb25jaWVycyBEcmllYSAtIERyaWVhIElmL3NjZXAvIElmL3NjZXAvcGlkL2NpZyIsImlkIjoxNTY4MDMzNTUsImNvdW50IjoyLCJwZXJjZW50IjoxLjQxODQzOTcxNjMxMjA1Njh9LHsibmFtZSI6IkJsYW5jYXJkIERlIExlcnkgSm9oYW5uYSIsImlkIjoxNTYwMTUzNTUsImNvdW50IjoyLCJwZXJjZW50IjoxLjQxODQzOTcxNjMxMjA1Njh9LHsibmFtZSI6IkRhZ3VlcnJlIiwiaWQiOjE1NTQ1NzY1NiwiY291bnQiOjIsInBlcmNlbnQiOjEuNDE4NDM5NzE2MzEyMDU2OH0seyJuYW1lIjoiQXVyJmVhY3V0ZTtsaWUgQ2hhYnJvbCIsImlkIjoxNTE1ODM4MjYsImNvdW50IjoyLCJwZXJjZW50IjoxLjQxODQzOTcxNjMxMjA1Njh9LHsibmFtZSI6IkImZWFjdXRlO2F0cmljZSBQaWVyaSIsImlkIjoxNDk2OTIwMjYsImNvdW50IjoyLCJwZXJjZW50IjoxLjQxODQzOTcxNjMxMjA1Njh9LHsibmFtZSI6IkxlIFJodW4gRWxvZGllIChjaGVmIERlIEJ1cmVhdSkgLSBEcmllYSBJZi9zc3QvZHJ0ci9iZ2MyIiwiaWQiOjE0OTU0NzI5MSwiY291bnQiOjIsInBlcmNlbnQiOjEuNDE4NDM5NzE2MzEyMDU2OH0seyJuYW1lIjoiSXNzYW0gR2hhbmVtIiwiaWQiOjE1NTExOTE4NCwiY291bnQiOjIsInBlcmNlbnQiOjEuNDE4NDM5NzE2MzEyMDU2OH0seyJuYW1lIjoiTWFyaW5hIExhdXJlIiwiaWQiOjE1NDMyNTcwNSwiY291bnQiOjIsInBlcmNlbnQiOjEuNDE4NDM5NzE2MzEyMDU2OH0seyJuYW1lIjoiTGF1cmllIFBvaW50ZWF1IiwiaWQiOjE1NDY2NDA5NiwiY291bnQiOjIsInBlcmNlbnQiOjEuNDE4NDM5NzE2MzEyMDU2OH0seyJuYW1lIjoiRnJhbWFsaXN0ZXMiLCJpZCI6MTUwOTAxMzI0LCJjb3VudCI6MiwicGVyY2VudCI6MS40MTg0Mzk3MTYzMTIwNTY4fSx7Im5hbWUiOiJBbmRyaWV1IEFsZXhhbmRyZSIsImlkIjoxNTgwNzYxMzMsImNvdW50IjoyLCJwZXJjZW50IjoxLjQxODQzOTcxNjMxMjA1Njh9LHsibmFtZSI6IkNhZmZpZXIgQXVyJmVhY3V0ZTtsaWVuIiwiaWQiOjE0OTY3NzE0OCwiY291bnQiOjIsInBlcmNlbnQiOjEuNDE4NDM5NzE2MzEyMDU2OH0seyJuYW1lIjoiRmxhaGF1dCBTdCZlYWN1dGU7cGhhbmUgKGFkam9pbnQgQXUgRGlyZWN0ZXVyKSAgNzgvZGlyIiwiaWQiOjE1MTg0ODk2OSwiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH0seyJuYW1lIjoicG9zdG1hc3RlckBvdXRsb29rLmNvbSIsImlkIjoxNDg4MTI1NzQsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6Im5icmlhdWx0QHZpbGxlLW1lcnUuZnIiLCJpZCI6MTQ3OTg3MDkxLCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJNaWNoYWVsIE1hZ2FsaGFlcyIsImlkIjoxNTQ2OTU1NzgsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IlNlcmdlbnQgQmVydHJhbmQiLCJpZCI6MTQ3OTY3NzY3LCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJNYWlyaWUgRGUgUHImZWFjdXRlO2F1eCIsImlkIjoxNTI5OTI0NTQsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IlNpbW9uIExlaGVyaWNleSIsImlkIjoxNDgxMzAyNjQsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IkFubmUgQ2hldnJvdWxldCIsImlkIjoxNTQzMTg3NjMsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6Ik1haXNvbiBEZXMgRW50cmVwcmlzZXMgTGliJmVhY3V0ZTtyYWxlcyBNZWwiLCJpZCI6MTU1Mjc5NDQ1LCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJGciZlYWN1dGU7ZCZlYWN1dGU7cmljIEJhcm5vaW4iLCJpZCI6MTU1NDc5OTE0LCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJEdWZvdXIgQ2FtaWxsZSAtIERnYWxuL2RodXAvZmU1IiwiaWQiOjE1Mzg3NTc0MSwiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH0seyJuYW1lIjoiSW52b2ljZXMgQWNjb3VudCIsImlkIjoxNTU0ODI1NTgsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IlJvbWFpbiBDdWNjaWEiLCJpZCI6MTU1Mzk3NDY2LCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJIdWd1ZXMgVmlsY29zcXVpIiwiaWQiOjE1MzI5NzgzNywiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH0seyJuYW1lIjoiUmVuYXJkIEZhYmllbm5lIiwiaWQiOjE1NTIyNjA0NiwiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH0seyJuYW1lIjoiQ29udGFjdCIsImlkIjoxNTU2ODE4ODUsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6InBvbHZpbGxlQGJldGh1bmVicnVheS5mciIsImlkIjoxNTQzNDM5NzgsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6Im9saXZpZXIudmVybWVyc2NoQHJpdmFsaXMuZnIiLCJpZCI6MTU1NDAxMzkyLCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJKJmVhY3V0ZTtyJm9jaXJjO21lIFN0ZWlnZXIgLSBNZXNzb3J0aWVzY2UiLCJpZCI6MTUyOTgyOTY4LCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJDZWRyaWMgTmV2ZXUiLCJpZCI6MTU0NjgzNjk5LCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJQb3J0IEJydW5vIiwiaWQiOjE1Mzg0ODA0MSwiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH0seyJuYW1lIjoiTGVjb2ludGUgSnVsaWV0dGUiLCJpZCI6MTQ4NjYyNzYzLCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJkb21pbmlxdWVAY29sbGFydC5mciIsImlkIjoxNDg4MTA4OTcsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6Ikd1aWxsYXVtZSBDcmFpdCIsImlkIjoxNTU0NDQ3MzEsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IkNoYW5lYWMgR3VpbGxhdW1lIFByZWY2MCIsImlkIjoxNTMzNDI3NjIsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IkxlYmFzdGFyZCBGcmFuY2sgKGFkam9pbnQgQXUgQ2hlZiBEZSBCdXJlYXUpIC0gRGdhbG4vc2FncC9zZHAvYmNzaSIsImlkIjoxNTI5NzA5ODMsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IkF1ciZlYWN1dGU7bGllIiwiaWQiOjE1MDkyOTg3NCwiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH0seyJuYW1lIjoiUGFzY2FsZSBNaXNzeSIsImlkIjoxNTQ3NDQ1ODksImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IlJhY2hpZCBCb3VkZ3VpZyIsImlkIjoxNTUzMTU5MDAsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IkZhYmllbm5lIEJvdXZlcmVzc2UiLCJpZCI6MTU0MzMxNDYyLCJjb3VudCI6MSwicGVyY2VudCI6MC43MDkyMTk4NTgxNTYwMjg0fSx7Im5hbWUiOiJCb2lzc29uIFRob21hcyIsImlkIjoxNDc4MTQ3OTUsImNvdW50IjoxLCJwZXJjZW50IjowLjcwOTIxOTg1ODE1NjAyODR9LHsibmFtZSI6IkZsYW5keSBOaWNvbGUtTSAtIERyZWFsIEF1dmVyZ25lL3NlYnIvbmF0IiwiaWQiOjE1NDQ4NTY5OSwiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH0seyJuYW1lIjoiU3QmZWFjdXRlO3BoYW5pZSBCb3NzYXJkIiwiaWQiOjE1NDMyMzA5NiwiY291bnQiOjEsInBlcmNlbnQiOjAuNzA5MjE5ODU4MTU2MDI4NH1dfSwiYnVzaWVzdERheSI6eyJkYXkiOjUsImhvdXIiOjAsImNvdW50Ijo0MH0sImZpbHRlclRhZ3MiOltdLCJidXN5VGltZVN0YXJ0IjoxNCwiYnVzeVRpbWVFbmQiOjE2LCJjdXN0b21GaWVsZHMiOnsiZmllbGRzIjpbXSwiY291bnQiOjB9LCJjdXJyZW50Ijp7InN0YXJ0RGF0ZSI6IjIwMTctMTItMDFUMDA6MDA6MDBaIiwiZW5kRGF0ZSI6IjIwMTgtMDEtMDFUMDA6MDA6MDBaIiwidG90YWxDb252ZXJzYXRpb25zIjoxNDEsImNvbnZlcnNhdGlvbnNDcmVhdGVkIjoxMjYsIm5ld0NvbnZlcnNhdGlvbnMiOjEyNiwiY3VzdG9tZXJzIjoxMTIsIm1lc3NhZ2VzUmVjZWl2ZWQiOjE5NiwiY29udmVyc2F0aW9uc1BlckRheSI6NH0sInRhZ0lkcyI6WyIxIl19 + http_version: + recorded_at: Thu, 13 Dec 2018 12:49:05 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/lib/helpscout/user_conversations_adapter_spec.rb b/spec/lib/helpscout/user_conversations_adapter_spec.rb new file mode 100644 index 000000000..126b92590 --- /dev/null +++ b/spec/lib/helpscout/user_conversations_adapter_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe Helpscout::UserConversationsAdapter do + describe '#reports', vcr: { cassette_name: 'helpscout_conversations_reports' } do + let(:from) { Date.new(2017, 11) } + let(:to) { Date.new(2017, 12) } + + before { Rails.cache.clear } + + subject { described_class.new(from, to) } + + it 'returns one report result per month' do + expect(subject.reports.count).to eq 2 + end + + it 'populates each report with data' do + expect(subject.reports.first[:conversations_count]).to be > 0 + expect(subject.reports.first[:start_date]).to eq Time.utc(2017, 11) + expect(subject.reports.first[:end_date]).to eq Time.utc(2017, 12) + + expect(subject.reports.last[:conversations_count]).to be > 0 + expect(subject.reports.last[:start_date]).to eq Time.utc(2017, 12) + expect(subject.reports.last[:end_date]).to eq Time.utc(2018, 01) + end + end +end