An open source, stand-alone, customisable public spending data web app.
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
há 14 anos
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