diff --git a/app/admin/category.rb b/app/admin/category.rb index aff17356..009b14c1 100644 --- a/app/admin/category.rb +++ b/app/admin/category.rb @@ -7,6 +7,9 @@ actions end + filter :created_at + filter :updated_at + form do |f| f.inputs do f.input :name diff --git a/app/admin/organization.rb b/app/admin/organization.rb index c54442bc..62f85c35 100644 --- a/app/admin/organization.rb +++ b/app/admin/organization.rb @@ -69,6 +69,8 @@ def destroy filter :phone filter :city, as: :select, collection: -> { Organization.pluck(:city).uniq } filter :neighborhood + filter :created_at + filter :updated_at permit_params :name, :email, :web, :phone, :city, :neighborhood, :address, :description, :public_opening_times, :logo diff --git a/app/admin/petition.rb b/app/admin/petition.rb index fefe30e5..9a1bcab4 100644 --- a/app/admin/petition.rb +++ b/app/admin/petition.rb @@ -11,6 +11,8 @@ end end + filter :organization filter :status, as: :select, collection: -> { Petition.statuses } filter :created_at + filter :updated_at end diff --git a/app/admin/post.rb b/app/admin/post.rb index 39ad8d60..c0d0e505 100644 --- a/app/admin/post.rb +++ b/app/admin/post.rb @@ -57,4 +57,5 @@ filter :is_group filter :active filter :created_at + filter :updated_at end diff --git a/app/admin/transfer.rb b/app/admin/transfer.rb new file mode 100644 index 00000000..7857e142 --- /dev/null +++ b/app/admin/transfer.rb @@ -0,0 +1,42 @@ +ActiveAdmin.register Transfer do + includes :post, movements: { account: [:accountable, :organization] } + + actions :index, :destroy + + 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 "From - To" do |transfer| + accounts_from_movements(transfer, with_links: true).join(" #{glyph(:arrow_right)} ").html_safe + end + column :amount do |transfer| + seconds_to_hm(transfer.movements.first.amount.abs) + 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 + + filter :reason + filter :created_at +end diff --git a/app/admin/user.rb b/app/admin/user.rb index 032375bc..060f9e84 100644 --- a/app/admin/user.rb +++ b/app/admin/user.rb @@ -35,6 +35,7 @@ filter :phone filter :postcode filter :locale + filter :created_at form do |f| f.semantic_errors *f.object.errors.keys diff --git a/app/services/transfer_importer.rb b/app/services/transfer_importer.rb new file mode 100644 index 00000000..93acbc13 --- /dev/null +++ b/app/services/transfer_importer.rb @@ -0,0 +1,78 @@ +# 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, + :created_at, + :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, + created_at: created_at, + 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], + data_row[7] + ) + 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