I need to sort array of hashes:
resource = [{ 'resource_id' => 34,
'description' => 'NR00123',
'total_gross_amount_cents' => bank_transfer.amount_cents,
'contractor_name' => 'Bogisich Inc' },
{ 'resource_id' => 35,
'description' => bank_transfer.purpose,
'total_gross_amount_cents' => 54321,
'contractor' => 'Bogisich Inc' },
{ 'resource_id' => 36,
'description' => 'Some description 2',
'total_gross_amount_cents' => 0123,
'contractor' => bank_transfer.creditor_name
}
]
By following requirements:
first - match_invoice_number
def match_invoice_number(resource)
bank_transfer.purpose&.include?(resource['description'])
end
second - match_amount
def match_amount(resource)
bank_transfer.amount_cents == resource['total_gross_amount'] || resource['gross_amount_cents']
end
third - match_vendor
def match_vendor(resource)
resource['contractor'].include?(bank_transfer.creditor_name)
end
So at the end resource should be like:
resource = [
{ 'resource_id' => 35,
'description' => bank_transfer.purpose,
'total_gross_amount_cents' => 54_321,
'contractor' => 'Bogisich Inc' },
{ 'resource_id' => 34,
'description' => 'NR00123',
'total_gross_amount_cents' => bank_transfer.amount_cents,
'contractor_name' => 'Bogisich Inc' },
{ 'resource_id' => 36,
'description' => 'Some description 2',
'total_gross_amount_cents' => 0o123,
'contractor' => bank_transfer.creditor_name }
]
I was trying to use select but the end resource looks the same like at the beginning. Here what I use:
def only_suggested(resource)
resource.select do |resource|
collection(resource)
end
end
def collection(resource)
[match_invoice_number(resource), match_amount(resource), match_vendor(resource)]
end
collection(resource) method returns an array which treated as true value when select checks it, so you get your entire collection back. To sort you can use sort_by method. If you need to uplift an item that follows all conditions use all? method:
resource.sort_by do |resource|
collection(resource).all? ? 0 : 1 # To return sortable value
end
If conditions have different priorities:
resource.sort_by do |resource|
if match_invoice_number(resource)
0
elsif match_amount(resource)
1
elsif match_vendor(resource)
2
else
3
end
end
Is it possible to export in xlsx with multiple sheet using gem axlsx. If not please suggest me the other ways.
I want to export the values of #search, #searchg, #clients, #overtimes in different sheets.
#search = Operation.where(:date => params[:from_date].to_datetime..(params[:to_date].to_datetime + 1.day))
#searchg = Guard.where(:status => true).where(:induction_date => params[:from_date].to_datetime..(params[:to_date].to_datetime + 1.day))
#searcht = Guard.where(:status => false).where(:terminate_date => params[:from_date].to_datetime..(params[:to_date].to_datetime + 1.day))
#clients = Client.where(:status => false).where(:terminate_date => params[:from_date].to_datetime..(params[:to_date].to_datetime + 1.day))
#overtimes = Overtime.where(:date => params[:from_date].to_datetime..(params[:to_date].to_datetime + 1.day))
respond_to do |format|
format.js
format.xlsx {render xlsx: 'report', filename: "Operation_reports_#{params[:from_date]}_#{params[:to_date]}.xlsx"}
end
Yep, axlsx supports multiple sheets. In fact, you can see it in the very first code snippet in its readme:
Axlsx::Package.new do |p|
p.workbook.add_worksheet(:name => "Pie Chart") do |sheet|
sheet.add_row ["Simple Pie Chart"]
%w(first second third).each { |label| sheet.add_row [label, rand(24)+1] }
sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,5], :end_at => [10, 20], :title => "example 3: Pie Chart") do |chart|
chart.add_series :data => sheet["B2:B4"], :labels => sheet["A2:A4"], :colors => ['FF0000', '00FF00', '0000FF']
end
end
p.serialize('simple.xlsx')
end
Currently there are multiple transactions with the same txnid. But for each transaction the payment mode is credit card, debit card or net banking.
If the customer has to pay $3000 he might pay that $3000 like $1000 with Credit card, $1000 with Debit Card, $1000 with Net banking.
Currently am displaying all those 3 transactions in 3 rows but with the same txnid. But I want to display those 3 transactions in a single row by mentioning in the payment mode column ($1000- Credit Card, $1000 Debit Card, $1000 Net bank)
Thanks for your help .
transactions.html.erb
<tr>
<th>Merchant Name</th>
<th>Transaction ID</th>
<th>Payment Mode</th>
<th>Amount</th>
<th>Status</th>
<th>Transaction Fee</th>
<th>Discount</th>
<th>Additional Charges</th>
<th>Added On</th>
</tr>
</thead>
<tbody id="details">
<% #all_settlement_details.map(&:txnid).uniq.each do |sd| %>
<tr>
<td><%= sd.merchantname %></td>
<td><%= sd.txnid %></td>
<td><%= get_mode_ui.value(sd.mode) %></td>
<td><%= sd.amount %></td>
<td><%= get_status(sd.status) %></td>
<td><%= sd.mer_service_fee %></td>
<td><%= sd.discount %></td>
<td><%= sd.additional_charges%></td>
<td><%= get_added_on_date sd.addedon %></td>
</tr>
<% end %>
</tbody>
trasactions.helper.rb
INDEX_OPTIONS = {'dashboard' => 'get_dashboard_data', 'merchants' => 'get_merchants', 'transactions' => 'get_transactions',
'admin' => 'get_admin_data', 'profile' => 'get_merchant_data'}
INDEX_PARTIAL = {'dashboard' => 'dashboard', 'merchants' => 'merchant_list', 'transactions' => 'transactions',
'admin' => 'admin', 'profile' => 'merchant_profile'}
AJAX_OPTIONS = {'stat-board' => 'get_stats', 'transactions' => 'get_graph_transactions', 'payment-methods' => 'get_payment_method_graph_data',
'merchants' => 'get_merchant_graph_data', 'merchant_profile' => 'get_merchant_profile_data', 'load_more' => 'load_more',
'merchant_list' => 'get_merchants'}
AJAX_PARTIAL = {'stat-board' => 'stat_board', 'transactions' => 'transactions_graph', 'payment-methods' => 'payment_methods_graph',
'merchants' => 'merchant_graphs', 'load_more' => 'transaction_details', 'merchant_profile' => 'merchant_profile_detail',
'merchant_list' => 'filtered_merchants',}
STATUS={"dropped"=>0,"bounced"=>1,"captured"=>2,"auth"=>3,"failed"=>4,"usercancelled"=>5,"pending"=>6}
MODE={'CC'=>0,'DC'=>1,'NB'=>2,'EMI'=>3,'CASH'=>4,'IVR'=>5,'COD'=>6}
MODE_UI = {'CC'=>'Credit Card','DC'=>'Debit Card','NB'=>'Net Banking','EMI'=>'EMI','CASH'=>'Cash','IVR'=>'IVR','COD'=>'Cash on Delivery'}
PG_MODE = {'Credit Card'=>0,'Debit Card'=>1,'Net Banking'=>2,'EMI'=>3,'Cash'=>4,'IVR'=>5,'Cash on Delivery'=>6,'Others'=>nil}
STATUS_UI={"Dropped"=>0,"Bounced"=>1,"Captured"=>2,"Authenticated"=>3,"Failed"=>4,"User Cancelled"=>5,"Pending"=>6}
CARDTYPE={'domestic'=>1,'international'=>2}
TRANSACTIONS = ["Merchant Name", "Transaction ID", "Payment Mode","Amount","Status","Transaction Fee","Discount","Additional Charges","Added On"]
TXN_SUCCESS_STATUS = [2,3]
TXN_FAILURE_STATUS = [0,1,4,5]
TXN_PENDING_STATUS = 6
PARTNER_PANEL_REDMINE_STATUS_MAPPING = {
16 => "In Process",
3 => "In Process",
69 => "In Process",
11 => "Line of Business Rejected",
14 => "Live",
42 => "In Process",
51 => "In Process",
15 => "In Process",
17 => "In Process",
64 => "In Process",
46 => "In Process",
62 => "Line of Business Rejected",
65 => "In Process",
18 => "Assigned to Sales",
79 => "In Process",
61 => "In Process",
5 => "In Process",
70 => "In Process",
71 => "In Process",
50 => "Line of Business Rejected",
32 => "Contacted",
48 => "In Process",
59 => "In Process",
49 => "In Process",
47 => "In Process",
60 => "In Process",
29 => "Line of Business Rejected",
78 => "Assigned to Sales"
}
PARTNER_PANEL_REDMINE_STATUS_MAPPING_UI = {
"In Process" => "16,3,69,42,51,15,17,64,46,65,79,61,5,70,71,48,59,49,47,60",
"Line of Business Rejected" => "11,62,50,29",
"Assigned to Sales" => "78,18",
"Live" => "14",
"Contacted" => "32"
}
def get_status _status_flag
STATUS.key(_status_flag)
end
def get_mode _mode_flag
MODE.key(_mode_flag)
end
def get_mode_ui
PG_MODE
end
def get_transactions_ui
TRANSACTIONS
end
def get_status_ui
STATUS_UI
end
def get_merchant_status_ui
PARTNER_PANEL_REDMINE_STATUS_MAPPING_UI
end
def status_merchant
PARTNER_PANEL_REDMINE_STATUS_MAPPING
end
def get_added_on_date _date
_date.strftime("%A, %d %B\'%y %H:%M")
end
def link_to_add_issues(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to_function(name, "add_issues(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
end
def link_to_remove_issues(name, f)
f.hidden_field(:_destroy) + link_to_function(name, "remove_issues(this)")
end
def get_issue_object _partner
_partner.issues.blank? ? _partner.class.reflect_on_association(:issues).klass.new : _partner.issues
end
def get_contact_detail_object issue
issue.contact_detail.blank? ? issue.class.reflect_on_association(:contact_detail).klass.new : issue.contact_detail
end
def issue_contact_detail issue, contact_column_name
issue.contact_detail ? issue.contact_detail.send(contact_column_name) : ""
end
def options_for_state(issue)
options_for_select(Setting[:states].split(/\r\n/).sort, issue.state).html_safe
end
# First Landing page for a Partner
def get_dashboard_data
get_stats
get_merchants
end
# Merchant list for a Partner
def get_merchants
_merchant_filter_scope = {'merchant_status' => ["merchant_status", (params[:merchant_status].split(',') rescue nil)],
'merchant_email' => ["merchant_mail", params[:merchant_email]],
'merchant_url' => ["merchant_url", params[:merchant_url]],
'merchant_mid' => ['payu_mid', params[:merchant_mid]],
'merchant_name' => ['merchant_name', params[:merchant_name]],
'order' => ['order_issue', params[:order]]
}
method_array = [['issues'],["page", params[:page]],["per", per_page_option],["date_filter", #start_date, #end_date]]
#partner_merchants = call_scope_methods_dynamically(method_array, _merchant_filter_scope)
end
# Transactions for a Partner
def get_transactions
#get more records to load
load_more
end
# Merchant Profile page for a Partner
def get_merchant_data
get_stats
load_more
end
# Admin page for Partners
def get_admin_data
#partners = Partner.where(partner_admin: false)
end
# Stat Board tab on Dashboard
def get_stats
method_array = [['settlement_details'],['stat_board_details'],['count_as_graph_data']]
method_array << ['merchant_mid', #merchant_mid] if #merchant_mid
method_array = add_date_or_hour_filter method_array
data1 = call_methods(method_array)
method_array << ['group_by_settlements_date']
data2 = call_methods(method_array)
#graph_data = [data1, data2]
end
# Merchant tab on Dashboard
def get_merchant_graph_data
method_array = [['issues']]
method_array = add_date_or_hour_filter method_array
method_array << ['group_by_merchant_date']
data1 = #bank_partner.issues.date_filter(#start_date, #end_date).group_by(&:status_id)
data2 = call_methods(method_array)
#merchant_status_hash = {}
data1.each{|key, value| get_partner_status_hash(get_merchant_status(key), value.count)}
[#merchant_status_hash, data2]
end
def get_merchant_status redmine_status
PARTNER_PANEL_REDMINE_STATUS_MAPPING[redmine_status] || 'In Process'
end
def get_partner_status_hash key, value
#merchant_status_hash.update({key => value}){|k, ov, nv| ov + nv}
end
# Transaction tab on Dashboard
def get_graph_transactions
method_array = [['settlement_details'],['count_as_graph_data']]
method_array << ['merchant_mid', #merchant_mid] if #merchant_mid
method_array = add_date_or_hour_filter method_array
method_array << ['group_by_settlements_date']
#data1 = call_methods(method_array << ["status", TXN_SUCCESS_STATUS])
#data2 = call_methods(method_array << ["status", TXN_FAILURE_STATUS])
#data3 = call_methods(method_array << ["status", TXN_PENDING_STATUS])
[#data1, #data2, #data3]
end
# Payment Method tab on Dashboard
def get_payment_method_graph_data
method_array = [['settlement_details'],["date_filter", #start_date, #end_date],['payment_mode']]
method_array << ['merchant_mid', #merchant_mid] if #merchant_mid
method_array << ['count']
call_methods(method_array)
end
def get_transaction_graph_hash successful, failure, pending
data_array= []
successful_hash = {}
failure_hash = {}
pending_hash = {}
successful.each{|d| successful_hash.merge!({(d.hour rescue d.date) => d.graph_data})}
failure.each{|d| failure_hash.merge!({(d.hour rescue d.date) => d.graph_data})}
pending.each{|d| pending_hash.merge!({(d.hour rescue d.date) => d.graph_data})}
(successful_hash.keys + failure_hash.keys + pending_hash.keys).uniq.each do |datetime|
data_array << {'datetime'=> "#{datetime}",'successful'=> (successful_hash[datetime] || 0) ,'unsuccessful'=> (failure_hash[datetime] || 0) ,'pending'=> (pending_hash[datetime] || 0)}
end
data_array
end
private
def load_more
#all_settlement_details = get_all_settlement_details || []
end
def get_all_settlement_details
# Offset increments by 10 and Limit remains 11
_txn_filter_scope = {'transaction_status' => ["status", (params[:transaction_status].split(',') rescue nil)],
'payment_options' => ["payment_options", (params[:payment_options].split(',') rescue nil)],
'transaction_id' => ['transaction_id', params[:transaction_id]],
'transaction_amount' => ['amount_range', ((params[:transaction_amount].split(',')[0] || 0) rescue nil), ((params[:transaction_amount].split(',')[1] || 100000000) rescue nil)],
'merchant_mid' => ['merchant_mid',params[:merchant_mid]],
'merchant_name' => ['merchant_name', params[:merchant_name]],
'clicks' => ['txn_offset', ((params[:clicks].to_i)*10 rescue 0)]
}
method_array = [['settlement_details'],["date_filter", #start_date, #end_date]]
method_array << ["txn_limit", 11] unless #csv_format
method_array << ['merchant_mid', #merchant_mid] if #merchant_mid
records = call_scope_methods_dynamically(method_array, _txn_filter_scope)
records.empty? ? nil : records
end
# extend Object to introduce the call_methods method
def call_methods(methods)
methods.inject(#bank_partner) do |obj, method|
case method.count
when 3
obj.send(method.first, method[1], method[2])
when 2
obj.send(method.first, method.last)
when 1
obj.send(method.first)
else
obj
end
end
end
def call_scope_methods_dynamically(_method_array, _method_hash)
method_array = _method_array
_dynamic_method_hash = _method_hash
# Add scopes in the methods array to call dynamically
params.each{|key, value| method_array << _dynamic_method_hash[key]}
call_methods(method_array.compact)
end
def add_date_or_hour_filter _method_array
if #start_date == #end_date
#end_date = (Date.parse(#end_date) + 1.day).strftime("%Y/%m/%d")
_method_array << ['hour_filter']
end
_method_array << ["date_filter", #start_date, #end_date]
_method_array
end
My final output should be look like.
Txnid payment mode Amount
23234XS24XS $1000Credit Card, $3000
$1000 Debit Card,
$1000 Net bank
Some one said I need to create a helper method for that. But I am not sure how!
Thanks for your help!
I don't know what all those files you posted are for. You say that you want the following in the db:
"$1000- Credit Card, $1000 Debit Card, $1000 Net bank"
First, you would never write that format to the db. Instead, you would try to use a consistent format, like:
Credit Card:1000,Debit Card:1000,Net Bank:1000
Then you can retrieve that column and store it in a variable:
payment_mode = "Credit Card: 1000, Debit Card: 1000, Net Bank: 1000"
Then you can do:
payments = Hash[
payment_mode
.split(',')
.map{|mode| mode.split(':')}
]
p payments
total = payment_by.values.sum
#total = payments.values.map(&:to_i).inject(:+)
taxnid = 123
first_line = true
puts "Taxnid\tPayment mode\t\tTotal"
payments.each_pair do |type, amount|
if first_line
puts "#{taxnid}\t#{type} #{amount}\t#{total}"
first_line = false
else
puts "\t#{type} #{amount}"
end
end
--output:--
Taxnid Payment mode Total
123 Credit Card 1000 3000
Debit Card 1000
Net Bank 1000
If you actually want to create some html that displays that format, then substitute <td>'s and <tr>'sin the appropriate places:
Im using the Prawn gem to generate a pdf table. I need to set the width of the table to 100%. How can I do this?
Here's my slmun_pdf.rb
class SlmunPdf < Prawn::Document
def initialize(slmunDbs, view, allcount)
if slmunDbs.table_name == "schools"
super(top_margin: 50)
if slmunDbs.size != allcount
#warn = " (Not all Schools)"
else
#all = " All #{slmunDbs.size} Schools"
end
text "Showing#{#all}", size: 18, style: :bold, align: :center, color: "636363"
text "#{#warn}", size: 11, align: :center, color: "858585"
#schools = slmunDbs
#view = view
school_list
end
end
def school_list
move_down 20
table school_list_rows, :cell_style => { :font => "Helvetica", :size => 9, :border_width => 0.5, :borders => [:top, :bottom], :border_color => "B0B0B0", :text_color => "737373"} do
self.row(0).align = :center
row(0).background_color = 'A0B046'
row(0).text_color = "FFFFFF"
self.row_colors = ["DDDDDD", "FFFFFF"]
self.header = true
end
end
def school_list_rows
[["Name", "Contact", "Country", "Pre Registration", "Full Registration", "Assigned Countries", "Total Delegates" ]] +
#schools.map do |school|
countries = ""
len = school.countries.count
school.countries.each_with_index do |country, index|
countries << "#{country.country }"
if index+1 != len
countries << ","
end
end
[school.name, school.contact, school.country, #view.yesno(school.prereg), #view.yesno(school.fullreg), countries, school.delegates.size ]
end
end
end
The existing documentations didn't help. I might be using a different method? I learnt this from rails cast!
You can use the width method of the Prawn::Document::BoundingBox class:
require 'prawn'
require 'prawn/table'
Prawn::Document.generate("hello.pdf") do
table_content = [["This table"], ["covers the"], ["whole page width"]]
table table_content, width: bounds.width
end
I am using Prawn to generate a pdf receipt. Ideally I would like the following format:
Header
Customer Info
Items for order
Total
However when it goes to the second page there is a huge gap on the top from the Header spacing. How can I prevent it from adding the extra spacing on top?
Here is the code generating the receipt below (Sorry there is a lot of code):
class OrderPdf < Prawn::Document
def initialize(order)
super()
#order = order
bounding_box([10, 700], :width => 500) do
logo
end
message
date_shipped
order_number
bounding_box([0, -70], :width => 2000) do
bounding_box([65, 560], :width => 200) do
shipping_address
end
bounding_box([320, 560], :width => 200) do
payment_method
end
bounding_box([25, 450], :width => 500, :position => :center) do
line_items
end
end
end
def logo
image "#{Rails.root}/app/assets/images/letterhead-header.jpg" , :scale => 0.25, :position => :center
end
def message
move_down 20
text "Thanks for shopping with Dwellers. If you have any questions, please email support#dwellers.com"
end
def date_shipped
move_down 10
data = [["Shipment on #{#order.date_to_ship.strftime("%B %d, %Y")}",
"Items: #{#order.order_items.count}",
"Total: #{helpers.humanized_money(Money.new((#order.total_cents), "USD"), {:no_cents_if_whole => false, :symbol => true})}"]]
table data do
cells.style(:borders => [], :background_color => "DDDDDD", :valign => :center)
column(0).font_style = :bold
column(0).width = 400
column(0).size = 18
end
end
def order_number
move_down 10
# order_id = Digest::MD5.hexdigest "#{#order.id}#{#order.date_to_ship}"
text "Order\# #{#order.number}", size: 14, style: :bold
end
def shipping_address
move_down 10
text "Shipping address:", size: 14, style: :bold
indent(20) do
text "#{#order.user.name} #{#order.user.name_last}"
address_fields = #order.user.address.split(",")
text "#{address_fields[0]}"
if !address_fields[1].empty?
text "#{address_fields[1]}"
end
text "#{address_fields[2]}, #{address_fields[3]} #{address_fields[4]}"
end
end
def payment_method
move_down 10
#card = #order.user.card
text "Payment Information:", size: 14, style: :bold
if #card != nil
indent(20) do
text "#{#card[:card_type].capitalize} **** **** **** #{#card[:last_four]}"
billing_address
end
end
end
def billing_address
move_down 10
#billing_address = #order.user.billing_address.split
address_fields = #order.user.billing_address.split(",")
text "#{#card[:name]}"
text "#{address_fields[0]}"
if !address_fields[1].empty?
text "#{address_fields[1]}"
end
text "#{address_fields[2]}, #{address_fields[3]} #{address_fields[4]}"
end
def line_items
move_down 10
text "In this shipment:", size: 14, style: :bold
table line_item_rows + summary do
row(0).font_style = :bold
columns(1..3).align = :left
self.header = true
cells.style(:borders => [])
column(0).width = 380
row(row_heights().length-5).borders = [:bottom]
row(row_heights().length-2..row_heights().length-1).column(1).font_style = :bold
row(row_heights().length-1).column(1..2).size = 14
end
end
def line_item_rows
[["Item names", "Qty", "Price"]] +
#order.order_items.map do |order_item|
product = order_item.item.name + " - " + order_item.item.description
quantity = " x " +order_item.quantity.to_s
[product, quantity, helpers.humanized_money(Money.new((order_item.price_paid_cents), "USD"), {:no_cents_if_whole => false, :symbol => true})]
end
end
def summary
# move_down 15
data = [["", "", ""],
["Subtotal:", "Shipping:", "Total:"],
[helpers.humanized_money(Money.new((#order.subtotal_cents), "USD"), {:no_cents_if_whole => false, :symbol => true}),
helpers.humanized_money(Money.new((#order.shipping_fee_cents), "USD"), {:no_cents_if_whole => false, :symbol => true}),
helpers.humanized_money(Money.new(#order.total_cents, "USD"), {:no_cents_if_whole => false, :symbol => true})]].transpose
end
# Need this to get access to View Helpers, such as number_to_currency
def helpers
ActionController::Base.helpers
end
end
Below is how the receipt looks like.
For your flowing text that is beneath the header, you can use a span rather than a bounding_box, and it will start at the top of the page. There are some examples in the manual, just search for span in there:
http://prawn.majesticseacreature.com/manual.pdf