From f3627dfa96e7a27ce706fa1dcc49a7122e133084 Mon Sep 17 00:00:00 2001 From: Cory McDonald Date: Thu, 19 Sep 2019 16:32:59 -0500 Subject: [PATCH] Create Uphold Report (#2219) * Create Uphold Report * UpholdReport -> UpholdStatusReport * Tests pass * Apply suggestions from code review Co-Authored-By: Albert Wang * Apply suggestions from code review Co-Authored-By: Albert Wang * Apply suggestions from code review Co-Authored-By: Albert Wang * Rename relevant files from uphold_reports to uphold_status_reports (#2240) * KYC report route fix (#2241) * Fix route to use uphold_status_report --- app/assets/stylesheets/admin/style.scss | 3 +- .../admin/uphold_status_reports_controller.rb | 30 +++++++++++++++++++ .../publishers/uphold_controller.rb | 15 ++++++++++ app/models/uphold_connection.rb | 5 ++-- app/models/uphold_status_report.rb | 3 ++ app/views/admin/publishers/_uphold.html.slim | 8 ++++- app/views/admin/shared/_sidebar.html.slim | 1 + .../uphold_status_reports/index.html.slim | 22 ++++++++++++++ config/routes.rb | 2 ++ ...90910163930_create_uphold_status_report.rb | 13 ++++++++ db/schema.rb | 11 +++++++ 11 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 app/controllers/admin/uphold_status_reports_controller.rb create mode 100644 app/models/uphold_status_report.rb create mode 100644 app/views/admin/uphold_status_reports/index.html.slim create mode 100644 db/migrate/20190910163930_create_uphold_status_report.rb diff --git a/app/assets/stylesheets/admin/style.scss b/app/assets/stylesheets/admin/style.scss index fa726d4738..3f70c00f2e 100644 --- a/app/assets/stylesheets/admin/style.scss +++ b/app/assets/stylesheets/admin/style.scss @@ -14,7 +14,7 @@ grid-gap: 32px; align-items: center; } - + // Bootstrap overrides. Could be refined .btn-default { color: $braveGray-2 !important; @@ -58,7 +58,6 @@ bottom: 0; background: $braveGray-2; margin: 60px 0 0 0; - padding: 24px 0; overflow: auto; .sidebar-menu { diff --git a/app/controllers/admin/uphold_status_reports_controller.rb b/app/controllers/admin/uphold_status_reports_controller.rb new file mode 100644 index 0000000000..c46e86ee70 --- /dev/null +++ b/app/controllers/admin/uphold_status_reports_controller.rb @@ -0,0 +1,30 @@ +require 'csv' + +module Admin + class UpholdStatusReportsController < AdminController + def index + @uphold_status_reports = UpholdStatusReport. + group('(EXTRACT(YEAR FROM created_at))::integer'). + group('(EXTRACT(MONTH FROM created_at))::integer'). + order('2 DESC, 3 DESC').count + end + + def show + date = DateTime.strptime(params[:id], "%Y-%m") + start_date = date.at_beginning_of_month + end_date = date.at_end_of_month + + uphold_status_reports = UpholdStatusReport.where("created_at >= :start AND created_at <= :finish", start: start_date, finish: end_date) + + generated = [] + generated << ["publisher id", "publisher created at", "uphold id", "uphold connected time"].to_csv + + uphold_status_reports.each do |report| + generated << [report.publisher_id, report.publisher.created_at, report.uphold_id, report.created_at].to_csv + end + + send_data generated.join(''), filename: "uphold-#{params[:id]}.csv" + end + end +end + diff --git a/app/controllers/publishers/uphold_controller.rb b/app/controllers/publishers/uphold_controller.rb index 63d4bb7373..f2c96274fb 100644 --- a/app/controllers/publishers/uphold_controller.rb +++ b/app/controllers/publishers/uphold_controller.rb @@ -76,6 +76,9 @@ def create ExchangeUpholdCodeForAccessTokenJob.perform_now(publisher_id: current_publisher.id) + connection.reload + create_uphold_report!(connection) + redirect_to(home_publishers_path) rescue UpholdError, Faraday::Error => e Rails.logger.info("Uphold Error: #{e.message}") @@ -95,6 +98,18 @@ def destroy class UpholdError < StandardError; end + def create_uphold_report!(connection) + uphold_id = connection.uphold_details&.id + return if uphold_id.blank? + # Return if we've already created a report for this id + return if UpholdStatusReport.find_by(uphold_id: uphold_id).present? + + UpholdStatusReport.create( + publisher: current_publisher, + uphold_id: uphold_id + ) + end + def validate_uphold!(connection) # Ensure the uphold_state_token has been set. If not send back to try again raise UpholdError.new, t('.missing_state') if connection&.uphold_state_token.blank? && !connection.uphold_verified? diff --git a/app/models/uphold_connection.rb b/app/models/uphold_connection.rb index 264c7b2f35..e11a3d0677 100644 --- a/app/models/uphold_connection.rb +++ b/app/models/uphold_connection.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class UpholdConnection < ActiveRecord::Base - has_paper_trail only: [:is_member, :uphold_id, :address, :status, :default_currency] + has_paper_trail only: [:is_member, :member_at, :uphold_id, :address, :status, :default_currency] UPHOLD_CODE_TIMEOUT = 5.minutes UPHOLD_ACCESS_PARAMS_TIMEOUT = 2.hours @@ -100,7 +100,7 @@ def uphold_client def uphold_details @user ||= uphold_client.user.find(self) rescue Faraday::ClientError => e - if e.response[:status] == 401 + if e.response&.dig(:status) == 401 Rails.logger.info("#{e.response[:body]} for uphold connection #{id}") update(uphold_access_parameters: nil) nil @@ -169,6 +169,7 @@ def sync_from_uphold! update( is_member: uphold_information.memberAt.present?, + member_at: uphold_information.memberAt, status: uphold_information.status, uphold_id: uphold_information.id, country: uphold_information.country diff --git a/app/models/uphold_status_report.rb b/app/models/uphold_status_report.rb new file mode 100644 index 0000000000..b4813d34e3 --- /dev/null +++ b/app/models/uphold_status_report.rb @@ -0,0 +1,3 @@ +class UpholdStatusReport < ApplicationRecord + belongs_to :publisher +end diff --git a/app/views/admin/publishers/_uphold.html.slim b/app/views/admin/publishers/_uphold.html.slim index 9765ba01c7..8ed41a43fc 100644 --- a/app/views/admin/publishers/_uphold.html.slim +++ b/app/views/admin/publishers/_uphold.html.slim @@ -26,7 +26,13 @@ h3.text-dark.d-flex.align-items-center td User has completed KYC td span class=(@publisher.uphold_connection.is_member? ? 'text-success' : 'text-danger') - = @publisher.uphold_connection.is_member? ? fa_icon("check", text: "Yes") : fa_icon("times", text: "No") + - if @publisher.uphold_connection.is_member? + = fa_icon("check", text: "Yes") + span.text-muted + span.mx-2= " – " + = @publisher.uphold_connection.member_at.strftime("%B %d, %Y %k:%M %Z") + - else + = fa_icon("times", text: "No") tr td Uphold ID td= link_to_if @publisher.uphold_connection.uphold_id, @publisher.uphold_connection.uphold_id, admin_publishers_path(q: @publisher.uphold_connection.uphold_id) diff --git a/app/views/admin/shared/_sidebar.html.slim b/app/views/admin/shared/_sidebar.html.slim index ae15a27e41..30f7dbc48a 100644 --- a/app/views/admin/shared/_sidebar.html.slim +++ b/app/views/admin/shared/_sidebar.html.slim @@ -48,3 +48,4 @@ aside = nav_link "FAQs", admin_faq_categories_path = nav_link "Payout Reports", admin_payout_reports_path = nav_link "Referral Promo", admin_unattached_promo_registrations_path + = nav_link "Uphold Reports", admin_uphold_status_reports_path diff --git a/app/views/admin/uphold_status_reports/index.html.slim b/app/views/admin/uphold_status_reports/index.html.slim new file mode 100644 index 0000000000..869300ec2c --- /dev/null +++ b/app/views/admin/uphold_status_reports/index.html.slim @@ -0,0 +1,22 @@ +.panel-heading + h4 Uphold Reports + +div + .font-weight-bold How this works: + p Anytime a publisher connects their uphold account we create an entry in our database that logs this. If an uphold id has already been reported we do not create an entry. This data is then aggregated and grouped by month and displayed here. + +table.table + thead + tr + td Period + td Number of users + td + tbody + - @uphold_status_reports.each do |report| + tr + td + - date = report.as_json.first + = Date::MONTHNAMES[date.second] + = " #{date.first}" + td= report.as_json.second + td= link_to("Download", admin_uphold_status_report_path(date.join('-')), class:'btn btn-default') diff --git a/config/routes.rb b/config/routes.rb index e338a5bd2c..539e2f0b1f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -250,6 +250,8 @@ end resources :promo_campaigns, only: %i(create) root to: "dashboard#index" # <--- Root route + + resources :uphold_status_reports, only: [:index, :show] end resources :errors, only: [], path: "/" do diff --git a/db/migrate/20190910163930_create_uphold_status_report.rb b/db/migrate/20190910163930_create_uphold_status_report.rb new file mode 100644 index 0000000000..9d5e8ca082 --- /dev/null +++ b/db/migrate/20190910163930_create_uphold_status_report.rb @@ -0,0 +1,13 @@ +class CreateUpholdStatusReport < ActiveRecord::Migration[5.2] + def change + add_column :uphold_connections, :member_at, :datetime + + create_table :uphold_status_reports, id: :uuid, default: -> { "uuid_generate_v4()"}, force: :cascade do |t| + t.belongs_to :publisher, index: true, type: :uuid + t.uuid :uphold_id, index: true + t.timestamps + end + + add_index :uphold_status_reports, :created_at + end +end diff --git a/db/schema.rb b/db/schema.rb index 5364e43e45..a36704857c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -529,9 +529,20 @@ t.string "country" t.string "default_currency" t.datetime "default_currency_confirmed_at" + t.datetime "member_at" t.index ["publisher_id"], name: "index_uphold_connections_on_publisher_id", unique: true end + create_table "uphold_status_reports", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t| + t.uuid "publisher_id" + t.uuid "uphold_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["created_at"], name: "index_uphold_status_reports_on_created_at" + t.index ["publisher_id"], name: "index_uphold_status_reports_on_publisher_id" + t.index ["uphold_id"], name: "index_uphold_status_reports_on_uphold_id" + end + create_table "user_authentication_tokens", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t| t.string "encrypted_authentication_token" t.string "encrypted_authentication_token_iv"