Last active
September 7, 2022 06:53
-
-
Save sulmanweb/a3407dcc9cd7fddb42e251055d20f247 to your computer and use it in GitHub Desktop.
Export User Transactions in CSV and upload to Active Storage or send as attachment in email #rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# app/services/export_services/export_transaction_service.rb | |
# Example: | |
# ExportServices::ExportTransactionService.new({ user: User,last}).call | |
# ExportServices::ExportTransactionService.new({ user: User.last, from_date: '2022-01-01', to_date: '2022-09-01'}).call | |
module ExportServices | |
# ExportTransactionService | |
class ExportTransactionService | |
# initialize the service with user, from_date and to_date and setting transactions accordingly | |
def initialize(params) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength | |
@user = params[:user] | |
@from_date = params[:from_date] ? params[:from_date].to_date : 10.years.ago # -Infinity | |
@to_date = params[:to_date] ? params[:to_date].to_date : Time.zone.now | |
@transactions = @user.transactions.where(transaction_date: @from_date..@to_date) | |
.joins(:account, :category).kept.order(transaction_date: :desc) | |
end | |
# service work when call method is called | |
def call | |
return if @transactions.length.zero? | |
generate_csv_file | |
# export_to_storage | |
send_email | |
end | |
# This method creates a temp CSV file and fills data based on initialized transactions | |
def generate_csv_file # rubocop:disable Metrics/AbcSize, Metrics/MethodLength | |
@tempfile = Tempfile.new(["export_#{Time.zone.now.strftime('%Y%m%d%H%M%S')}_#{@user.id}", '.csv']).tap do |file| | |
CSV.open(file, 'wb') do |csv| | |
# CSV Header Row | |
csv << %w[Date Description Type Amount Currency Category Account] | |
# CSV Rows, each row representing a transaction | |
@transactions.find_each do |transaction| | |
csv << [ | |
transaction.transaction_date.to_date.to_s, | |
transaction.description, | |
transaction.transaction_type == 'income' ? 'Income' : 'Expense', | |
transaction.value.to_f.round(2), | |
transaction.account.currency.code, | |
transaction.category.name, | |
transaction.account.name, | |
] | |
end | |
end | |
end | |
end | |
# Thios method adds the tempfile to ActiveStorage and hence to S3 service if attached | |
# I have attached s3 to production environment | |
# returns url of the uploaded CSV File | |
def export_to_storage # rubocop:disable Metrics/AbcSize, Metrics/MethodLength | |
# Document Model `has_attached_file :doc` and `user has_many :documents` and `document belongs_to :user` | |
document = Document.new(user: @user) | |
document.doc.attach( | |
io: @tempfile, | |
filename: @tempfile.path.split('/').last, | |
content_type: 'application/csv' | |
) | |
document.save! | |
@file_url = if Rails.env.production? | |
# returns s3 public url | |
Rails.application.routes.url_helpers.rails_public_blob_url(@document.doc) | |
else | |
# return local url | |
Rails.application.routes.url_helpers.rails_blob_url(@document.doc) | |
end | |
end | |
# This method sends email with temp file attached | |
# https://gist.github.com/sulmanweb/eab697301cf8209572c5a95af6543b3a | |
# https://sulmanweb.com/send-emails-using-sendgrid-sdk-for-ruby-on-rails-using-dynamic-sendgrid-email-templates/ | |
def send_email # rubocop:disable Metrics/MethodLength | |
EmailJob.new.perform( | |
@user.id, | |
{ name: @user.name }, | |
ENV.fetch('EXPORT_TEMPLATE', nil), | |
[ | |
{ | |
file: @tempfile.path, | |
type: 'application/csv', | |
name: @tempfile.path.split('/').last, | |
content_id: 'export_file' | |
} | |
] | |
) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment