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.
 
 
 
 

171 line
4.5 KiB

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