From 16c3573cbc088147a70f20557fa45a30429d10b9 Mon Sep 17 00:00:00 2001 From: franpb14 Date: Thu, 14 Dec 2023 21:40:30 +0100 Subject: [PATCH 1/2] transfers in activeadmin and import from csv --- app/admin/transfer.rb | 40 +++++++++++++++++ app/services/transfer_importer.rb | 75 +++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 app/admin/transfer.rb create mode 100644 app/services/transfer_importer.rb diff --git a/app/admin/transfer.rb b/app/admin/transfer.rb new file mode 100644 index 00000000..86007874 --- /dev/null +++ b/app/admin/transfer.rb @@ -0,0 +1,40 @@ +ActiveAdmin.register Transfer do + action_item :upload_csv, only: :index do + link_to I18n.t("active_admin.users.upload_from_csv"), action: "upload_csv" + end + + collection_action :upload_csv do + render "admin/csv/upload_csv" + end + + collection_action :import_csv, method: :post do + errors = TransferImporter.call(params[:dump][:organization_id], params[:dump][:file]) + flash[:error] = errors.join("
").html_safe if errors.present? + + redirect_to action: :index + end + + index do + id_column + column :post + column :reason + column :source do |transfer| + acc = transfer.movements.find_by('amount < 0').account.accountable + acc.class.name == "Member" ? acc.user : acc + end + column :destination do |transfer| + acc = transfer.movements.find_by('amount > 0').account.accountable + acc.class.name == "Member" ? acc.user : acc + end + column :amount do |transfer| + transfer.movements.find_by('amount > 0').amount + end + column :created_at do |transfer| + l transfer.created_at.to_date, format: :long + end + column :organization do |transfer| + transfer.movements.first.account.organization + end + actions + end +end diff --git a/app/services/transfer_importer.rb b/app/services/transfer_importer.rb new file mode 100644 index 00000000..4f2a27b0 --- /dev/null +++ b/app/services/transfer_importer.rb @@ -0,0 +1,75 @@ +# Used in the Admin section to import transfers +# to a specific organization, from a CSV file. + +require "csv" + +class TransferImporter + Row = Struct.new( + :source_id, + :source_type, + :destination_id, + :destination_type, + :amount, + :reason, + :post_id + ) do + def transfer_from_row(organization_id, errors) + source = find_account(source_id, source_type, organization_id, errors, 'source') + destination = find_account(destination_id, destination_type, organization_id, errors, 'destination') + return unless source && destination + + Transfer.new( + source: source, + destination: destination, + amount: amount, + reason: reason, + post_id: post_id, + ) + end + + private + + def find_account(id, type, organization_id, errors, direction) + acc = if type.downcase == 'organization' + Organization.find(organization_id).account + else + Member.find_by(member_uid: id, organization_id: organization_id)&.account + end + + unless acc + errors.push(account_id: id, errors: "#{direction}_id #{id} not found in organization #{organization_id}") + return false + end + acc + end + end + + class << self + def call(organization_id, csv_data) + data = csv_data.read + errors = [] + + CSV.parse(data, headers: false) do |data_row| + row = Row.new( + data_row[0], + data_row[1], + data_row[2], + data_row[3], + data_row[4], + data_row[5], + data_row[6] + ) + process_row(row, organization_id, errors) + end + + errors + end + + def process_row(row, organization_id, errors) + transfer = row.transfer_from_row(organization_id, errors) + return if !transfer || transfer.save + + errors.push(account_id: row.source_id, errors: transfer.errors.full_messages) + end + end +end From d6ecb2c56f1e4198583a0a495ac22e3fa50c8820 Mon Sep 17 00:00:00 2001 From: franpb14 Date: Mon, 18 Dec 2023 20:51:26 +0100 Subject: [PATCH 2/2] created_at added --- app/services/transfer_importer.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/services/transfer_importer.rb b/app/services/transfer_importer.rb index 4f2a27b0..93acbc13 100644 --- a/app/services/transfer_importer.rb +++ b/app/services/transfer_importer.rb @@ -10,6 +10,7 @@ class TransferImporter :destination_id, :destination_type, :amount, + :created_at, :reason, :post_id ) do @@ -22,6 +23,7 @@ def transfer_from_row(organization_id, errors) source: source, destination: destination, amount: amount, + created_at: created_at, reason: reason, post_id: post_id, ) @@ -57,7 +59,8 @@ def call(organization_id, csv_data) data_row[3], data_row[4], data_row[5], - data_row[6] + data_row[6], + data_row[7] ) process_row(row, organization_id, errors) end