| @@ -4,6 +4,8 @@ require 'sinatra-helpers/haml/partials' | |||||
| require 'haml' | require 'haml' | ||||
| require 'lib/models' | require 'lib/models' | ||||
| SETTING = Setting.first # Could also do this with Sinatra filters before/do | |||||
| PAYMENTS_FILTER_MIN = 1000 | PAYMENTS_FILTER_MIN = 1000 | ||||
| helpers do | helpers do | ||||
| @@ -157,6 +159,7 @@ get '/about' do | |||||
| end | end | ||||
| get '/scoreboard.csv' do | get '/scoreboard.csv' do | ||||
| halt 404 | |||||
| @councils = Council.all( :order => ['name'] ) | @councils = Council.all( :order => ['name'] ) | ||||
| labels = %w[ | labels = %w[ | ||||
| id | id | ||||
| @@ -181,6 +184,7 @@ get '/scoreboard.csv' do | |||||
| end | end | ||||
| get '/scoreboard' do | get '/scoreboard' do | ||||
| halt 404 | |||||
| @councils = Council.all( :order => ['name'] ) | @councils = Council.all( :order => ['name'] ) | ||||
| haml :scoreboard | haml :scoreboard | ||||
| end | end | ||||
| @@ -1,5 +1,5 @@ | |||||
| require 'lib/models' | require 'lib/models' | ||||
| require 'csv' | |||||
| require 'fastercsv' | |||||
| # Before running this script with a CSV file, prepare it so: | # Before running this script with a CSV file, prepare it so: | ||||
| # - There is only a single line of column headings on the first line of the file | # - There is only a single line of column headings on the first line of the file | ||||
| @@ -44,7 +44,7 @@ if date_format != 'DMY' && date_format != 'MDY' | |||||
| exit | exit | ||||
| end | end | ||||
| CSV::Reader.parse(File.open(ARGV[0], 'rb')) do |row| | |||||
| FasterCSV.foreach(ARGV[0]) do |row| | |||||
| count += 1 | count += 1 | ||||
| @@ -70,8 +70,11 @@ CSV::Reader.parse(File.open(ARGV[0], 'rb')) do |row| | |||||
| end | end | ||||
| directorate = Directorate.first_or_create(:name => directorate_name) | directorate = Directorate.first_or_create(:name => directorate_name) | ||||
| directorate.save | |||||
| service = Service.first_or_create(:name => service_name, :directorate => directorate) | service = Service.first_or_create(:name => service_name, :directorate => directorate) | ||||
| service.save | |||||
| supplier = Supplier.first_or_create(:name => supplier_name) | supplier = Supplier.first_or_create(:name => supplier_name) | ||||
| supplier.save | |||||
| dt = row[columns['Updated']].strip.split('/') | dt = row[columns['Updated']].strip.split('/') | ||||
| @@ -6,8 +6,6 @@ require 'dm-aggregates' | |||||
| require 'dm-serializer' | require 'dm-serializer' | ||||
| require 'dm-migrations' | require 'dm-migrations' | ||||
| SITE_URL = 'http://armchairauditor.co.uk/' | |||||
| class Payment | class Payment | ||||
| include DataMapper::Resource | include DataMapper::Resource | ||||
| @@ -17,14 +15,14 @@ class Payment | |||||
| property :service_id, Integer, :required => true | property :service_id, Integer, :required => true | ||||
| property :supplier_id, Integer, :required => true | property :supplier_id, Integer, :required => true | ||||
| property :amount, BigDecimal, :precision => 10, :scale => 2, :required => true # ex VAT | property :amount, BigDecimal, :precision => 10, :scale => 2, :required => true # ex VAT | ||||
| property :d, Date, :required => true # "Updated" in RBWM CSV files | |||||
| property :d, Date, :required => true # transaction date | |||||
| belongs_to :service | belongs_to :service | ||||
| belongs_to :supplier | belongs_to :supplier | ||||
| has 1, :directorate, { :through => :service } | has 1, :directorate, { :through => :service } | ||||
| def url | def url | ||||
| SITE_URL + "payments/" + @id.to_s | |||||
| SETTING.site_url + "payments/" + @id.to_s | |||||
| end | end | ||||
| end | end | ||||
| @@ -111,5 +109,20 @@ class Council | |||||
| end | end | ||||
| end | end | ||||
| # This is a singleton. We only use the first row in the settings table. | |||||
| class Setting | |||||
| include DataMapper::Resource | |||||
| property :id, Serial | |||||
| property :site_name, String, :length => 255, :required => true | |||||
| property :site_tagline, String, :length => 255 | |||||
| property :site_url, String, :length => 255 | |||||
| property :org_name, String, :length => 255 | |||||
| property :org_url, String, :length => 255 | |||||
| property :data_url, String, :length => 255 | |||||
| end | |||||
| DataMapper.setup(:default, ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/db.sqlite3") | DataMapper.setup(:default, ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/db.sqlite3") | ||||
| DataMapper.auto_upgrade! | DataMapper.auto_upgrade! | ||||
| @@ -18,7 +18,20 @@ input | |||||
| background-color: #fff; | background-color: #fff; | ||||
| } | } | ||||
| .tagline | |||||
| { | |||||
| color: #777; | |||||
| font-size: 60%; | |||||
| padding-left: 20px; | |||||
| } | |||||
| .alpha | |||||
| { | |||||
| font-size: 40%; | |||||
| text-transform: uppercase; | |||||
| vertical-align: top; | |||||
| line-height: 100%; | |||||
| } | |||||
| #main | #main | ||||
| { | { | ||||
| @@ -2,6 +2,6 @@ | |||||
| %h3 Comments | %h3 Comments | ||||
| %p.highlight | %p.highlight | ||||
| This is an independent website. | This is an independent website. | ||||
| %a{ :href => "http://www.rbwm.gov.uk/" }< | |||||
| Windsor and Maidenhead Council | |||||
| %a{ :href => "#{SETTING.org_url}" }< | |||||
| = SETTING.org_name | |||||
| might not see your comments here or reply to them. | might not see your comments here or reply to them. | ||||
| @@ -6,11 +6,15 @@ | |||||
| %p.right — Eric Pickles, Communities & Local Government Secretary, 5 June 2010 | %p.right — Eric Pickles, Communities & Local Government Secretary, 5 June 2010 | ||||
| <!-- http://news.bbc.co.uk/1/hi/politics/10241522.stm --> | |||||
| <!-- Source: http://news.bbc.co.uk/1/hi/politics/10241522.stm --> | |||||
| %p | |||||
| This site is made with | |||||
| %a{ :href => "#{SETTING.data_url}" }< | |||||
| spending data from the | |||||
| = SETTING.org_name | |||||
| and is entirely indepdendent of the council. The council did not commission or pay for this website. | |||||
| -# | |||||
| %img{ :src => "http://www.gravatar.com/avatar/4a92f0a6447839dc0a9a2b850fe9ed86?s=80&d=http%3A%2F%2Fgithub.com%2Fimages%2Fgravatars%2Fgravatar-80.png", :alt => "Adrian Short", :width => 80, :height => 80 } | |||||
| %p.vcard | %p.vcard | ||||
| This website was designed and written by | This website was designed and written by | ||||
| %a.fn.url{ :href => 'http://adrianshort.co.uk' }< | %a.fn.url{ :href => 'http://adrianshort.co.uk' }< | ||||
| @@ -21,14 +25,8 @@ | |||||
| and | and | ||||
| %a.url{ :href => "http://twitter.com/adrianshort" }< | %a.url{ :href => "http://twitter.com/adrianshort" }< | ||||
| follow me on Twitter. | follow me on Twitter. | ||||
| %p.highlight | |||||
| This site is made with | |||||
| %a{ :href => 'http://www.rbwm.gov.uk/web/finance_payments_to_suppliers.htm' }< | |||||
| the Royal Borough of Windsor and Maidenhead's spending data | |||||
| and is entirely indepdendent of the council. The council did not commission or pay for this website. | |||||
| %p.highlight | |||||
| %p | |||||
| All the data here is open data. It's free for you to use and republish, including commercially, | All the data here is open data. It's free for you to use and republish, including commercially, | ||||
| %a{ :href => "http://data.gov.uk/terms-and-conditions" } | %a{ :href => "http://data.gov.uk/terms-and-conditions" } | ||||
| under the same terms as data.gov.uk. | under the same terms as data.gov.uk. | ||||
| @@ -7,7 +7,7 @@ | |||||
| .clear | .clear | ||||
| .grid_6 | .grid_6 | ||||
| %h2 Council Directorates | |||||
| %h2 Council Services | |||||
| - for directorate in @directorates | - for directorate in @directorates | ||||
| %p | %p | ||||
| @@ -20,7 +20,10 @@ | |||||
| Armchair Auditor lets you see how your council spends your money. | Armchair Auditor lets you see how your council spends your money. | ||||
| %p | %p | ||||
| For the Royal Borough of Windsor and Maidenhead we've got: | |||||
| For the | |||||
| %a{ :href => "#{SETTING.org_url}" }< | |||||
| = SETTING.org_name | |||||
| we've got: | |||||
| %ul | %ul | ||||
| %li | %li | ||||
| %a{ :href => "/services" } | %a{ :href => "/services" } | ||||
| @@ -2,42 +2,39 @@ | |||||
| !!! | !!! | ||||
| %html | %html | ||||
| %head | %head | ||||
| %title= @page_title ? @page_title + " - Armchair Auditor" : "Armchair Auditor" | |||||
| %title= @page_title ? @page_title + " - " + SETTING.site_name : SETTING.site_name | |||||
| %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/style.css' } | %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/style.css' } | ||||
| -# | |||||
| %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/breadcrumb/breadcrumb.css' } | |||||
| %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/print.css', :media => 'print' } | %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/print.css', :media => 'print' } | ||||
| %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/grid.css' } | %link{ :rel => 'stylesheet', :type => 'text/css', :href => '/grid.css' } | ||||
| %script{:type => 'text/javascript', :src => 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'} | |||||
| %script{:type => 'text/javascript', :src => 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'} | |||||
| %script{:type => 'text/javascript', :src => '/js/jquery.cookie.js'} | %script{:type => 'text/javascript', :src => '/js/jquery.cookie.js'} | ||||
| <script type="text/javascript"> | |||||
| var _gaq = _gaq || []; | |||||
| _gaq.push(['_setAccount', 'UA-3042981-18']); | |||||
| _gaq.push(['_trackPageview']); | |||||
| (function() { | |||||
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | |||||
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | |||||
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | |||||
| })(); | |||||
| </script> | |||||
| :javascript | |||||
| var _gaq = _gaq || []; | |||||
| _gaq.push(['_setAccount', 'UA-3042981-18']); | |||||
| _gaq.push(['_trackPageview']); | |||||
| (function() { | |||||
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | |||||
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | |||||
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | |||||
| })(); | |||||
| %body | %body | ||||
| .container_12 | .container_12 | ||||
| .grid_12 | .grid_12 | ||||
| %p.highlight.hidden This is a demonstration website of "alpha" quality — don't rely on this data. | |||||
| %h1.logo | %h1.logo | ||||
| Armchair Auditor | |||||
| %sup | |||||
| %span{ :style => "font-size: 40%; text-transform: uppercase; vertical-align: top; line-height: 100%;" } | |||||
| Alpha | |||||
| %span{ :style => "color: #777; font-size: 60%; padding-left: 20px;" } | |||||
| Royal Borough of Windsor & Maidenhead Spending | |||||
| = SETTING.site_name | |||||
| -# | |||||
| %span.tagline | |||||
| = SETTING.site_tagline | |||||
| #nav.noprint | #nav.noprint | ||||
| %a{ :href => '/' } Home | %a{ :href => '/' } Home | ||||
| %a{ :href => '/services' } Services | %a{ :href => '/services' } Services | ||||
| %a{ :href => '/suppliers' } Suppliers | %a{ :href => '/suppliers' } Suppliers | ||||
| %a{ :href => '/scoreboard' } Scoreboard | |||||
| -# | |||||
| %a{ :href => '/scoreboard' } Scoreboard | |||||
| %a{ :href => '/about' } About | %a{ :href => '/about' } About | ||||
| = yield | = yield | ||||
| .clear | .clear | ||||
| @@ -45,7 +42,7 @@ | |||||
| .grid_12.top_border | .grid_12.top_border | ||||
| %p | %p | ||||
| An independent website | An independent website | ||||
| %a{ :href => 'http://twitter.com/AdrianShort' }< | |||||
| %a{ :href => 'http://twitter.com/adrianshort' }< | |||||
| designed by Adrian Short | designed by Adrian Short | ||||
| | | ||||
| %a{ :href => 'http://twitter.com/ArmchairAuditor' }< | %a{ :href => 'http://twitter.com/ArmchairAuditor' }< | ||||