I have a page which displays the transaction search results and i have a search filter based on one column(Token) upon clicking this the search criteria should be set and the search params should be passed as a form-data in post method. but currently, it is getting appended to the URL. Kindly, help me
_payment_transaction.html.erb
<div class="block">
<% if @transactions_exceed_limit %>
<div class="row">
<div class="block-title" id="max-fetch-results-message">
<h4 class="text-primary">Your search returned too many results, so only the first <%=
TransactionSearchController::MAX_FETCH_SIZE %> results have been displayed.</h4>
</div>
</div>
<% end %>
<div class="row" style="width:100% !important;">
<div class="col-md-4">
<div class="block-title">
<% if @integratedApi == false %>
<h3><strong> <%= @transactions.count %> results found</strong></h3>
<%else %>
<h3><strong> <%= @total_records %> results found</strong></h3>
<%end %>
</div>
</div>
<div class="col-md-8">
<div id="csvButton">
<%= form_tag(csv_path(params.except('controller', 'action').merge(format: "csv")), method: "post") do %>
<%= submit_tag "Download CSV", class: 'btn btn--charcoal-ghost', id: 'download_csv' %>
<% end %>
</div>
</div>
</div>
<div class="row" style="margin-bottom: 5px">
<hr class="line">
</div>
<div class="row">
<div class="table-responsive tb-responsive tble-responsive">
<table class="table table-condensed table-hover" id="search-result-table" style="margin-left:2%">
<thead>
<tr>
<th>Transaction Id</th>
<th>Order Id</th>
<th>Store Id</th>
<th>Transaction Date</th>
<th>Transaction Type</th>
<th>Tender Type</th>
<th>Token</th>
<th>Amount</th>
<th>Currency</th>
<th>Response </br>Code</th>
</tr>
</thead>
<tbody>
<% if @integratedApi %>
<% @transactions.each do |transaction| %>
<tr>
<td><%= link_to transaction[:paymentTransactionId], details_path(:id=> transaction), {:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal-window'} %></td>
<td><%= transaction[:paymentSessionId]%></td>
<td><%= transaction[:storeId]%></td>
<td><%= transaction[:createTimestamp].in_time_zone(@timezone).strftime('%B %d, %Y - %l:%M %p') %></td>
<td><%= @transaction_types[transaction[:transactionType]] %></td>
<td><%= @tenders[transaction[:tenderType]][1] %></td>
<td><%= link_to transaction[:paymentAcctUniqueId], params.merge(account_id: transaction[:paymentAcctUniqueId], show_results: "true",clickAccount:"Y"), id: "act_id" %></td>
<td><%= PaymentsHelper.amount_with_currency_symbol transaction[:transactionAmount], transaction[:isoCurrencyCode]%></td>
<td><%= transaction[:isoCurrencyCode]%></td>
<td><%=transaction[:responseCode]%></td>
</tr>
<% end %>
<% else %>
<% @transactions.each do |transaction| %>
<tr>
<td><%= link_to transaction['payment_transaction_id'], details_path(payment_transaction_id: transaction['payment_transaction_id']), {:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal-window'} %></td>
<td><%= transaction['payment_session_id'] %></td>
<td><%= transaction['store_id'] %></td>
<td><%= transaction['create_timestamp'].in_time_zone(@timezone).strftime('%B %d, %Y - %l:%M %p') %></td>
<td><%= @transaction_types[transaction['transaction_type']] %></td>
<td><%= @tenders[transaction['tender_type']][1] %></td>
<% if (@tenders[transaction['tender_type']][0]).in?(['PLCC', 'GC', 'CC', 'CBCC']) %>
<td><%= link_to transaction['payment_acct_unique_id'], params.merge(account_id: transaction['payment_acct_unique_id'], show_results: "true",clickAccount:"Y"), id: "act_id" %></td>
<% else %>
<td><%= transaction['payment_acct_unique_id'] %></td>
<% end %>
<% if show_settlement_type? %>
<td><%= PaymentsHelper.settlement_amount_with_currency_symbol transaction['transaction_amount'], transaction['iso_currency_code'],transaction['settlement_type'] %></td>
<% else %>
<td><%= PaymentsHelper.amount_with_currency_symbol transaction['transaction_amount'], transaction['iso_currency_code'] %></td>
<% end %>
<td><%= transaction['iso_currency_code'] %></td>
<% if transaction['transaction_status'] == ('F') %>
<td>Payment Service Error</td>
<% else %>
<td><%= transaction['response_code'] %></td>
<% end %>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<div id="modal-window" class="modal fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"></div>
</div>
Search.html.erb
<script type="text/javascript">
pt_default_time_gap = <%= ENV['PAYPTL_TRANSACTION_SEARCH_DEFAULT_TIME_GAP_IN_DAYS']%>;
pt_max_time_gap = <%= ENV['PAYPTL_TRANSACTION_SEARCH_MAX_TIME_GAP_IN_DAYS']%>;
pt_max_from_date_time_gap = <%= ENV['PAYPTL_TRANSACTION_SEARCH_MAX_TIME_GAP_FROM_CURRENT_DATE_IN_DAYS']%>;
</script>
<% provide(:title, 'Transaction Search') %>
<div id="load"></div>
<% content_for :sub_header do %>
<%= form_tag({controller: "transaction_search", action: "search"}, method: "post", style: "margin-bottom: 20px;", id: "search_crit_form") do %>
<%= render "search_criteria" %>
<div class="row" id="advanced_filters" style="display:none;">
<%= render "transaction_search/advance_filters" %>
</div>
<% end %>
<% end %>
<div id="contents">
<div class="row" style="margin-bottom:5px;margin-top: 15px" id="search_results">
<div class="search_results_pane" id="search_results_table">
<% if @transactions.present? %>
<%= render partial: "transaction_search/payment_transaction", object: @transactions %>
<% else %>
<div class="block">
<div class="block-title" id="emptyResults">
<h2 class="text-primary"><strong>No Results </strong> Found</h2>
</div>
</div>
<% end %>
</div>
</div>
</div>
transaction_search_controller.rb
require 'base64'
require 'rest-client'
require 'xmlrpc'
require 'nokogiri'
require 'date'
require 'will_paginate/array'
class TransactionSearchController < ApplicationController
include PaymentsHelper
include ApplicationHelper
protect_from_forgery except: :details
before_filter :authenticate_user!, :can_view_payments_txns?
before_action :set_store_and_timezone
before_action :tenders_and_transaction_types, only: [:search, :details]
before_action :settlement_status, only: [:details]
DEFAULT_TIME_GAP_IN_DAYS = "#{ENV['PAYPTL_TRANSACTION_SEARCH_DEFAULT_TIME_GAP_IN_DAYS']}".to_i.freeze
DATE_FORMAT = '%Y/%m/%d %H:%M'.freeze
SHOW_MOCK_TRANSACTION = ("#{ENV['PAYPTL_TRANSACTION_SEARCH_EXCLUDE_MOCK_TXS']}" == "true").freeze
PAYMENTS_URI = "#{ENV['PAYPTL_PAYMENT_SERVICE_PROTECT_PAN_URI']}".freeze
PAYMENTS_USERNAME = "#{ENV['PAYPTL_PAYMENT_SERVICE_PROTECT_PAN_USERNAME']}".freeze
PAYMENTS_PASSWORD = "#{ENV['PAYPTL_PAYMENT_SERVICE_PROTECT_PAN_PASSWORD']}".freeze
MAX_FETCH_SIZE = "#{ENV['PAYPTL_TRANSACTION_MAX_FETCH_SIZE']}".to_i.freeze
MAX_FETCH_SIZE_CSV = "#{ENV['PAYPTL_TRANSACTION_MAX_FETCH_SIZE_CSV']}".to_i.freeze
TRANSACTION_SEARCH_REST_API_ENABLED_FLAG = "#{ENV['PAYPTL_TRANSACTION_SEARCH_REST_API_ENABLED_FLAG']}"
PTF_CLIENT_MANAGEMENT_SERVICE_URL = "#{ENV['PAYPTL_PTF_CLIENT_MANAGEMENT_SERVICE_URL']}"
def search
@integratedApi=false
if TRANSACTION_SEARCH_REST_API_ENABLED_FLAG == 'Y'
@integratedApi=true
payload = Hash.new
if params[:per_page].present?
@selected_per_page = params[:per_page]
else
@selected_per_page = 2000
end
params[:page] = params[:page] || 1
payload['storeIds'] = params[:store_ids]
params[:start_date] = params[:start_date] || Time.now.utc.to_date.days_ago(DEFAULT_TIME_GAP_IN_DAYS - 1).beginning_of_day.strftime(DATE_FORMAT)
params[:end_date] = params[:end_date] || Time.now.utc.to_date.end_of_day.strftime(DATE_FORMAT)
payload['startDate'] = params[:start_date]
payload['endDate'] = params[:end_date]
payload['pageNum'] = params[:page]
payload['perPage'] = @selected_per_page
payload['paymentSessionId'] = params[:payment_session_id] if params[:payment_session_id].present?
payload['paymentAcctUniqueId'] = params[:account_id] if params[:account_id].present?
payload['transactionTypes'] = params[:transaction_types] if params[:transaction_types].present?
payload['tenderTypes'] = params[:tender_types] if params[:tender_types].present?
payload['transactionStatuses'] = params[:transaction_statuses] if params[:transaction_statuses].present?
payload['isoCurrencyCode'] = params[:iso_currency_code] if params[:iso_currency_code].present?
payload['transactionAmount'] = params[:transaction_amount] if params[:transaction_amount].present?
@transaction_search_results = get_transaction_search_details(PTF_CLIENT_MANAGEMENT_SERVICE_URL + "/payments/transaction/search", payload)
if @transaction_search_results.present? && @transaction_search_results.kind_of?(Hash) && @transaction_search_results.has_key?(:transactions)
@total_records = @transaction_search_results[:totalCount]
@total_records = @total_records.nil? ? 0 : @total_records.to_i
@transactions = @transaction_search_results[:transactions]
end
else
if @store_list.empty?
flash.now[:danger] = 'No Store Mapped'
end
params[:per_page] = params[:per_page] || 20
params[:page] = params[:page] || 1
params[:start_date] = params[:start_date] || Time.now.utc.to_date.days_ago(DEFAULT_TIME_GAP_IN_DAYS - 1).beginning_of_day.strftime(DATE_FORMAT)
params[:end_date] = params[:end_date] || Time.now.utc.to_date.end_of_day.strftime(DATE_FORMAT)
results
end
end
def get_transaction_search_details(rest_url, payload)
begin
rest_resource = RestClient::Resource.new(rest_url,ENV['PAYPTL_PTF_CLIENT_MANAGEMENT_SERVICE_USER_NAME'], ENV['PAYPTL_PTF_CLIENT_MANAGEMENT_SERVICE_PASSWORD'])
Rails.logger.debug("Calling Transaction Search URL:#{rest_url}\n Payload:#{payload.to_json}")
@transaction_search_response = rest_resource.post payload.to_json, :content_type => 'application/json'
if @transaction_search_response.code == Rack::Utils::SYMBOL_TO_STATUS_CODE[:ok]
return JSON.parse(@transaction_search_response, :symbolize_names => true)
else
Rails.logger.error("Transaction search return status code #{@transaction_search_response.code} for payload #{payload}")
end
rescue => e
Rails.logger.error(e.message)
flash.now[:danger] = 'Unable to fetch data, Please try later'
end
end
def results
start_date = Time.strptime(params[:start_date], DATE_FORMAT).utc.beginning_of_day
end_date = Time.strptime(params[:end_date], DATE_FORMAT).utc.end_of_day
condition = Hash.new
@accountId=params[:account_id]
condition[:store_id] = @store_for_service
condition[:payment_session_id] = params[:payment_session_id] if params[:payment_session_id].present?
condition[:transaction_test_ind] = [0, nil] if !SHOW_MOCK_TRANSACTION
condition[:transaction_type] = params[:transaction_types] if params[:transaction_types].present?
condition[:transaction_amount] = params[:transaction_amount] if params[:transaction_amount].present?
condition[:iso_currency_code] = params[:iso_currency_code] if params[:iso_currency_code].present?
condition[:tender_type] = params[:tender_types] if params[:tender_types].present?
condition[:transaction_status] = params[:transaction_statuses] if params[:transaction_statuses].present?
@page=params[:page]
if(@accountId!=nil && @accountId!='')
condition[:payment_acct_unique_id] = @accountId
if(params[:clickAccount]=='Y')
@page=1
params[:clickAccount]='N'
end
end
condition[:transaction_status] = params[:transaction_statuses] if params[:transaction_statuses].present?
if params[:action] == 'csvexport'
@transactions_export_csv = PaymentTransactionFlat.where(:create_timestamp => start_date..end_date).where(condition).order(create_timestamp: :desc).limit(MAX_FETCH_SIZE_CSV)
else
@transactions = PaymentTransactionFlat.where(:create_timestamp => start_date..end_date).where(condition).order(create_timestamp: :desc).limit(MAX_FETCH_SIZE + 1)
if @transactions.present?
@transactions = @transactions.to_a
if @transactions.count > MAX_FETCH_SIZE
@transactions = @transactions[0..(MAX_FETCH_SIZE - 1)]
@transactions_exceed_limit = true
end
=begin
@transactions = @transactions.paginate(:per_page => params[:per_page], :page => @page, :total_entries => @transactions.count)
=end
end
end
end
def details
@integratedApi=false
if TRANSACTION_SEARCH_REST_API_ENABLED_FLAG == 'Y'
@integratedApi=true
@transaction = params[:id]
else
@transaction = PaymentTransactionFlat.transaction_details(params[:payment_transaction_id])
if @transaction.present?
@settlement = PaymentTransactionFlat.settlement_transaction(@transaction['payment_transaction_id']).first
@response_cc_auth = PaymentTransactionFlat.response_cc_auth(@transaction['payment_transaction_id']).first
if @settlement.present?
@auth_transaction = PaymentTransactionFlat.authorization_transaction(@settlement['auth_pmt_transaction_id']).first
@customer_billing_address = PaymentTransactionFlat.customer_billing_address(@settlement['auth_pmt_transaction_id']).first
@settlement_history = PaymentTransactionFlat.settlement_transaction_history(@settlement['payment_transaction_id'])
end
end
end
end
def retrieve_payload(account_number, tender_class)
builder = Nokogiri::XML::Builder.new do |xml|
xml.ProtectPanRequest('xmlns' => 'http://api.gsicommerce.com/schema/checkout/1.0') do
xml.PaymentAccountNumber_ account_number
xml.TenderClass tender_class
end
end
return builder.to_xml
end
def retrieve_account_number(account_number)
if account_number.present? && account_number =~ /^[0-9]+$/
rest_client = RestClient::Resource.new(PAYMENTS_URI, PAYMENTS_USERNAME, PAYMENTS_PASSWORD)
PaymentsHelper::TENDER_CLASS.each do |key, value|
begin
response = rest_client.post retrieve_payload(account_number, value), :content_type => 'application/xml'
parsed_response = Hash.from_xml(response)
account_number = parsed_response.try(:[], 'ProtectPanReply').try(:[], 'Token') || account_number
break
rescue RestClient::RequestFailed
next
end
end
end
account_number
end
# Code for CSV generation
# Enable the CSV library
require 'csv'
# Action for generating the CSV
def csvexport
respond_to do |format|
format.csv do
send_data export_to_csv(results),
filename: 'transactions.csv',
type: 'text/csv; charset=utf-8; header=present',
disposition: 'attachment'
end
end
end
# Method for generating the csv file
def export_to_csv(records)
# Header names used in CSV file
csv_header = ['Transaction Id', 'Order Id', 'Store Id', 'Transaction Date', 'Transaction Type', 'Tender Type', 'Token', 'Amount', 'Currency', 'Response Code']
CSV.generate do |csv|
csv << csv_header
records.each do |record| # Quick fix for CSV download problem to export only specified columns
csv << [record['payment_transaction_id'], record['payment_session_id'], record['store_id'], record['create_timestamp'].in_time_zone(@timezone).strftime('%B %d, %Y - %l:%M %p'), record['transaction_type'],
record['tender_type'], record['payment_acct_unique_id'],
if record['transaction_amount'].to_s.present?
record['settlement_type'].to_s.casecmp("C")== 0 ? '-$' +
record['transaction_amount'].to_s : '$' + record['transaction_amount'].to_s else ' ' end, record['iso_currency_code'],
record['response_code'] == ('F') ? 'Payment Service Error' : record['response_code']]
end
end
end
def get_store_timezone
render json: ActiveSupport::TimeZone.find_tzinfo(get_timezone(@selected_store)), status: :ok
end
private
def set_store_and_timezone
params[:store_ids] = get_default_store if params[:store_ids].blank?
@selected_store = params[:store_ids]
@store_for_service = replace_with_store_mappings(@selected_store, ApplicationHelper::PAYMENTS_SERVICE)
@timezone = get_timezone @selected_store
zone_map = JSON.parse((ActiveSupport::TimeZone.find_tzinfo @timezone).to_json)
@moment_timezone = zone_map['identifier']
end
def tenders_and_transaction_types
@tenders = Rails.cache.fetch(:payment_tenders) {PaymentRecord.tenders}
@transaction_types = Rails.cache.fetch(:payment_transaction_types) {PaymentRecord.transaction_types}
end
def settlement_status
@settlement_statuses = Rails.cache.fetch(:payment_settlement_statuses) {PaymentRecord.settlement_status}
end
end