An open source, stand-alone, customisable public spending data web app.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
14 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. require 'rubygems'
  2. require 'sinatra'
  3. require 'sinatra-helpers/haml/partials'
  4. require 'haml'
  5. require 'lib/models'
  6. PAYMENTS_FILTER_MIN = 1000
  7. helpers do
  8. def commify(amount)
  9. amount.to_s.reverse.gsub(/(\d\d\d)(?=\d)(?!\d*\.)/,'\1,').reverse
  10. end
  11. def yesno(boolean)
  12. boolean == true ? 'Yes' : 'No'
  13. end
  14. def nicedate(d)
  15. d.strftime("%d %b %Y")
  16. end
  17. end
  18. get '/' do
  19. @directorates = Directorate.all( :order => ['name'] )
  20. @payments_count = Payment.count
  21. @suppliers_count = Supplier.count
  22. @services_count = Service.count
  23. haml :home
  24. end
  25. get '/directorates/:slug' do
  26. @directorate = Directorate.first(:slug => params[:slug])
  27. haml :directorate
  28. end
  29. get '/suppliers/:slug.csv' do
  30. @supplier = Supplier.first(:slug => params[:slug])
  31. headers "Content-Disposition" => "attachment;filename=supplier-#{@supplier.slug}.csv",
  32. "Content-Type" => "application/octet-stream"
  33. result = "Date,Ref.,URL,Directorate,Service,Amount ex. VAT\n"
  34. for payment in @supplier.payments
  35. result += "#{payment.d.strftime("%d %b %Y")},#{payment.id},#{payment.url},\"#{payment.service.directorate.name}\",#{payment.service.name},#{sprintf("%0.2f", payment.amount)}\n"
  36. end
  37. result
  38. end
  39. get '/suppliers/:slug' do
  40. @supplier = Supplier.first(:slug => params[:slug])
  41. @total = @supplier.payments.sum(:amount)
  42. @count = @supplier.payments.size # Payment.count(:supplier_id => @supplier.id) ?
  43. @avg = @supplier.payments.avg(:amount)
  44. @max = @supplier.payments.max(:amount)
  45. @min = @supplier.payments.min(:amount)
  46. @d_start = @supplier.payments.min(:d)
  47. @d_end = @supplier.payments.max(:d)
  48. haml :supplier
  49. end
  50. get '/suppliers/?' do
  51. @suppliers = Supplier.all( :order => ['name'] )
  52. haml :suppliers
  53. end
  54. get '/services/:slug/payments.csv' do
  55. @service = Service.first(:slug => params[:slug])
  56. headers "Content-Disposition" => "attachment;filename=service-#{@service.slug}.csv",
  57. "Content-Type" => "application/octet-stream"
  58. result = "Date,Ref.,URL,Directorate,Supplier,Amount ex. VAT\n"
  59. for payment in @service.payments
  60. result += "#{payment.d.strftime("%d %b %Y")},#{payment.id},#{payment.url},\"#{payment.service.directorate.name}\",#{payment.supplier.name},#{sprintf("%0.2f", payment.amount)}\n"
  61. end
  62. result
  63. end
  64. get '/services/:slug.json' do
  65. @service = Service.first(:slug => params[:slug])
  66. headers "Content-Type" => "application/json"
  67. @service.to_json(:relationships => { :payments => { :include => :all }, :directorate => { :include => :all } })
  68. end
  69. get '/services/:slug' do
  70. @service = Service.first(:slug => params[:slug])
  71. @total = @service.payments.sum(:amount)
  72. @count = @service.payments.size
  73. @avg = @service.payments.avg(:amount)
  74. @max = @service.payments.max(:amount)
  75. @min = @service.payments.min(:amount)
  76. @d_start = @service.payments.min(:d)
  77. @d_end = @service.payments.max(:d)
  78. @results = repository(:default).adapter.query("
  79. SELECT s.name AS supplier_name, s.slug AS supplier_slug, SUM(p.amount) AS total
  80. FROM payments p, suppliers s
  81. WHERE p.supplier_id = s.id
  82. AND p.service_id = #{@service.id}
  83. GROUP BY s.name, s.slug
  84. ORDER BY total DESC")
  85. haml :service
  86. end
  87. get '/services/:slug/payments' do
  88. @FILTER_VALUES = %w[ 500 1000 2500 5000 10000 20000 ]
  89. @service = Service.first(:slug => params[:slug])
  90. # payments_filter_min cookie persists user selection of filter value
  91. unless @min = request.cookies["payments_filter_min"]
  92. @min = PAYMENTS_FILTER_MIN
  93. response.set_cookie(
  94. "payments_filter_min",
  95. { :value => @min, :expires => Time.now + (60 * 24 * 60 * 60) }
  96. ) # 60 days
  97. end
  98. @payments = Payment.all(:service_id => @service.id, :amount.gte => @min, :order => [ 'd' ])
  99. @total = @payments.sum(:amount)
  100. haml :servicepayments
  101. end
  102. get '/services/:slug/paymentsdetail' do
  103. @service = Service.first(:slug => params[:slug])
  104. min = PAYMENTS_FILTER_MIN
  105. if params[:min].to_i > 0
  106. min = params[:min].to_i
  107. end
  108. @payments = Payment.all(:service_id => @service.id, :amount.gte => min, :order => [ 'd' ])
  109. @total = @payments.sum(:amount)
  110. haml :servicepaymentsdetail, :layout => false
  111. end
  112. get '/services/?' do
  113. @services = Service.all( :order => ['name'] )
  114. haml :services
  115. end
  116. get '/payments/:id' do
  117. @payment = Payment.get(params[:id])
  118. haml :payment
  119. end
  120. get '/error' do
  121. haml :error
  122. end
  123. get '/about' do
  124. haml :about
  125. end
  126. get '/scoreboard.csv' do
  127. @councils = Council.all( :order => ['name'] )
  128. labels = %w[
  129. id
  130. created_at
  131. updated_at
  132. name
  133. slug
  134. url
  135. data_url
  136. open_licence
  137. machine_readable
  138. start_d
  139. end_d
  140. ]
  141. headers "Content-Disposition" => "attachment;filename=armchair-auditor-scoreboard.csv",
  142. "Content-Type" => "text/csv"
  143. output = ""
  144. for council in @councils
  145. output += "#{council.id},#{council.created_at.strftime("%d %b %Y")},#{council.updated_at.strftime("%d %b %Y")},#{council.name},#{council.slug},#{council.url},#{council.data_url},#{council.open_licence},#{council.machine_readable},#{council.start_d.strftime("%d %b %Y")},#{council.end_d.strftime("%d %b %Y")}\n"
  146. end
  147. labels.join(',') + "\n" + output
  148. end
  149. get '/scoreboard' do
  150. @councils = Council.all( :order => ['name'] )
  151. haml :scoreboard
  152. end
  153. not_found do
  154. haml :not_found
  155. end