| @@ -19,7 +19,7 @@ end | |||
| get '/directorates/:slug' do | |||
| @directorate = Directorate.first(:slug => params[:slug]) | |||
| @total = @directorate.payments.sum(:amount) | |||
| # @total = @directorate.payments.sum(:amount) | |||
| haml :directorate | |||
| end | |||
| @@ -42,6 +42,10 @@ end | |||
| get '/suppliers/:slug' do | |||
| @supplier = Supplier.first(:slug => params[:slug]) | |||
| @total = @supplier.payments.sum(:amount) | |||
| @count = @supplier.payments.size | |||
| @avg = @supplier.payments.avg(:amount) | |||
| @max = @supplier.payments.max(:amount) | |||
| @min = @supplier.payments.min(:amount) | |||
| haml :supplier | |||
| end | |||
| @@ -0,0 +1,110 @@ | |||
| require 'lib/models' | |||
| require 'csv' | |||
| # 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 are no spaces before or after the column headings | |||
| # - The column headings correspond with the key names in the columns{} hash below | |||
| # - The data starts on line 2 | |||
| columns = | |||
| { | |||
| 'Directorate' => nil, | |||
| 'Updated' => nil, | |||
| 'Service' => nil, | |||
| 'Supplier' => nil, | |||
| 'Amount' => nil | |||
| } | |||
| directorate_replacements = | |||
| [ | |||
| [ "Childrens Services", "Children's Services" ], | |||
| [ "Policy,Performance and Planning", "Policy, Performance and Planning" ] | |||
| ] | |||
| service_replacements = | |||
| [ | |||
| [ "Corporate Performance and Developmt", "Corporate Performance and Development" ], | |||
| [ "ISB", "ISB - Individual Schools Budget" ], | |||
| [ "Library and Information Services", "Libraries and Information Services" ], | |||
| [ "On Street Parking", "On-Street Parking" ] | |||
| ] | |||
| count = 0 | |||
| if ARGV[0].nil? | |||
| puts "Specify the filename of the CSV file to import on the command line" | |||
| exit | |||
| end | |||
| date_format = ARGV[1].upcase | |||
| if date_format != 'DMY' && date_format != 'MDY' | |||
| puts "Specify the date format as DMY or MDY as the second argument on the command line" | |||
| exit | |||
| end | |||
| CSV::Reader.parse(File.open(ARGV[0], 'rb')) do |row| | |||
| count += 1 | |||
| if (count > 1) # skip first line that doesn't contain data | |||
| p row | |||
| directorate_name = row[columns['Directorate']].strip.gsub(/&/, "and") | |||
| service_name = row[columns['Service']].strip.gsub(/&/, "and") | |||
| supplier_name = row[columns['Supplier']].strip.gsub(/&/, "and") | |||
| for replacement in directorate_replacements | |||
| if directorate_name == replacement[0] | |||
| directorate_name = replacement[1] | |||
| end | |||
| end | |||
| for replacement in service_replacements | |||
| if service_name == replacement[0] | |||
| service_name = replacement[1] | |||
| end | |||
| end | |||
| directorate = Directorate.first_or_create(:name => directorate_name) | |||
| service = Service.first_or_create(:name => service_name, :directorate => directorate) | |||
| supplier = Supplier.first_or_create(:name => supplier_name) | |||
| dt = row[columns['Updated']].strip.split('/') | |||
| # Date.new takes YMD params | |||
| if date_format == 'DMY' | |||
| d = Date.new(dt[2].to_i, dt[1].to_i, dt[0].to_i) | |||
| elsif date_format == 'MDY' | |||
| d = Date.new(dt[2].to_i, dt[0].to_i, dt[1].to_i) | |||
| elsif date_format == 'YMD' | |||
| d = Date.new(dt[0].to_i, dt[1].to_i, dt[2].to_i) | |||
| end | |||
| payment = Payment.first_or_new( | |||
| 'service' => service, | |||
| 'supplier' => supplier, | |||
| 'amount' => row[columns['Amount']].strip.gsub(/,/, ''), | |||
| 'd' => d | |||
| ) | |||
| unless payment.save | |||
| puts "ERROR: Failed to save payment" | |||
| payment.errors.each do |e| | |||
| puts e | |||
| end | |||
| end | |||
| else | |||
| # Get the column headings | |||
| position = 0 | |||
| for column in row | |||
| columns[column] = position | |||
| position += 1 | |||
| end | |||
| puts columns.inspect | |||
| end | |||
| end | |||
| @@ -1,45 +0,0 @@ | |||
| require 'lib/models' | |||
| require 'csv' | |||
| count = 0 | |||
| CSV::Reader.parse(File.open('data/2009Q4.csv', 'rb')) do |row| | |||
| # 2009Q4 Columns: | |||
| # 0: Directorate | |||
| # 1: Updated | |||
| # 2: TransNo | |||
| # 3: Service | |||
| # 4: Cost Centre | |||
| # 5: Supplier Name | |||
| # 6: Amount excl vat | |||
| # 7: Type | |||
| count += 1 | |||
| if (count > 4) # skip first four lines that don't contain data | |||
| p row | |||
| directorate = Directorate.first_or_create(:name => row[0].strip) | |||
| service = Service.first_or_create(:name => row[3].strip) | |||
| supplier = Supplier.first_or_create(:name => row[5].strip) | |||
| payment = Payment.first_or_create( | |||
| 'trans_no' => row[2], | |||
| 'directorate' => directorate, | |||
| 'service' => service, | |||
| 'supplier' => supplier, | |||
| 'cost_centre' => row[4].strip, | |||
| 'amount' => row[6].strip.gsub(/,/, ''), | |||
| 'd' => row[1], | |||
| 'tyype' => row[7].strip | |||
| ) | |||
| unless payment.save | |||
| puts "ERROR: Failed to save payment" | |||
| payment.errors.each do |e| | |||
| puts e | |||
| end | |||
| end | |||
| end | |||
| end | |||
| @@ -1,39 +0,0 @@ | |||
| require 'lib/models' | |||
| require 'csv' | |||
| count = 0 | |||
| # 2010Q1: 0-Directorate,1-Updated,2-Service,3-Supplier Name,4-Amount excl vat £,5-Type | |||
| CSV::Reader.parse(File.open('data/2010Q1.csv', 'rb')) do |row| | |||
| count += 1 | |||
| if (count > 4) # skip first four lines that don't contain data | |||
| p row | |||
| directorate = Directorate.first_or_create(:name => row[0].strip) | |||
| service = Service.first_or_create(:name => row[2].strip) | |||
| supplier = Supplier.first_or_create(:name => row[3].strip) | |||
| dt = row[1].strip.split('/') | |||
| payment = Payment.first_or_create( | |||
| 'directorate' => directorate, | |||
| 'service' => service, | |||
| 'supplier' => supplier, | |||
| 'amount' => row[4].strip.gsub(/,/, ''), | |||
| 'd' => Date.new(dt[2].to_i, dt[1].to_i, dt[0].to_i), | |||
| 'tyype' => row[5].strip | |||
| ) | |||
| unless payment.save | |||
| puts "ERROR: Failed to save payment" | |||
| payment.errors.each do |e| | |||
| puts e | |||
| end | |||
| end | |||
| end | |||
| end | |||
| @@ -10,19 +10,17 @@ class Payment | |||
| include DataMapper::Resource | |||
| property :id, Serial | |||
| property :trans_no, Integer, :required => false # "TransNo" in RBWM CSV files | |||
| property :directorate_id, Integer, :required => true | |||
| property :created_at, DateTime | |||
| property :updated_at, DateTime | |||
| property :service_id, Integer, :required => true | |||
| property :supplier_id, Integer, :required => true | |||
| property :cost_centre, String, :required => false | |||
| property :amount, BigDecimal, :precision => 10, :scale => 2, :required => true # ex VAT | |||
| property :d, Date, :required => true # "Updated" in RBWM CSV files | |||
| property :tyype, String, :required => true # Capital or Revenue | |||
| belongs_to :directorate | |||
| belongs_to :service | |||
| belongs_to :supplier | |||
| has 1, :directorate, { :through => :service } | |||
| def url | |||
| SITE_URL + "payments/" + @id.to_s | |||
| end | |||
| @@ -32,44 +30,60 @@ end | |||
| class Directorate | |||
| include DataMapper::Resource | |||
| property :id, Serial | |||
| property :name, String, :length => 255, :required => true | |||
| property :slug, String, :length => 255 | |||
| property :id, Serial | |||
| property :created_at, DateTime | |||
| property :updated_at, DateTime | |||
| property :name, String, :length => 255, :required => true | |||
| property :slug, String, :length => 255 | |||
| has n, :payments, :order => ['d'] | |||
| has n, :payments, :through => :services, :order => ['d'] | |||
| has n, :services, :order => ['name'] | |||
| has n, :suppliers, :through => :services, :order => ['name'] | |||
| def self.slugify(name) | |||
| name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase | |||
| end | |||
| before :save, :slugify | |||
| def slugify | |||
| @slug = @name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase | |||
| end | |||
| end | |||
| class Service | |||
| include DataMapper::Resource | |||
| property :id, Serial | |||
| property :name, String, :length => 255, :required => true | |||
| property :slug, String, :length => 255 | |||
| property :id, Serial | |||
| property :created_at, DateTime | |||
| property :updated_at, DateTime | |||
| property :directorate_id, Integer, :required => true | |||
| property :name, String, :length => 255, :required => true | |||
| property :slug, String, :length => 255 | |||
| has n, :payments, :order => ['d'] | |||
| has n, :suppliers, :through => :payments, :order => ['name'] | |||
| belongs_to :directorate | |||
| def self.slugify(name) | |||
| name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase | |||
| end | |||
| before :save, :slugify | |||
| def slugify | |||
| @slug = @name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase | |||
| end | |||
| end | |||
| class Supplier | |||
| include DataMapper::Resource | |||
| property :id, Serial | |||
| property :name, String, :length => 255, :required => true | |||
| property :slug, String, :length => 255 | |||
| property :id, Serial | |||
| property :created_at, DateTime | |||
| property :updated_at, DateTime | |||
| property :name, String, :length => 255, :required => true | |||
| property :slug, String, :length => 255 | |||
| has n, :payments, :order => ['d'] | |||
| has n, :services, :through => :payments, :order => ['name'] | |||
| def self.slugify(name) | |||
| name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase | |||
| before :save, :slugify | |||
| def slugify | |||
| @slug = @name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase | |||
| end | |||
| end | |||
| @@ -1,16 +0,0 @@ | |||
| require 'lib/models' | |||
| for supplier in Supplier.all | |||
| supplier.slug = Supplier.slugify(supplier.name) | |||
| supplier.save! | |||
| end | |||
| for service in Service.all | |||
| service.slug = Service.slugify(service.name) | |||
| service.save! | |||
| end | |||
| for directorate in Directorate.all | |||
| directorate.slug = Directorate.slugify(directorate.name) | |||
| directorate.save! | |||
| end | |||
| @@ -1,4 +1,5 @@ | |||
| .grid_12 | |||
| %ul#breadcrumb | |||
| %li.home | |||
| %a{ :href => '/'} Home | |||
| @@ -9,33 +10,22 @@ | |||
| %h2= @page_title = @directorate.name + " Directorate" | |||
| %table | |||
| %tr | |||
| %th Date | |||
| %th Ref. | |||
| %th Service | |||
| %th Supplier | |||
| %th.right £ | |||
| - for payment in @directorate.payments | |||
| %tr | |||
| %td= payment.d.strftime("%d %b %Y") | |||
| %td | |||
| %a{ :href => "/payments/#{payment.id}" } | |||
| = payment.id | |||
| %td | |||
| %a{ :href => '/services/' + payment.service.slug } | |||
| = payment.service.name | |||
| %td | |||
| %a{ :href => '/suppliers/' + payment.supplier.slug } | |||
| = payment.supplier.name | |||
| %td.right= sprintf("%0d", payment.amount) | |||
| %tr | |||
| %td | |||
| %td | |||
| %td | |||
| %strong TOTAL | |||
| %td.right= sprintf("%0d", @total) | |||
| %td | |||
| .clear | |||
| .grid_6 | |||
| %h3 Services | |||
| - for service in @directorate.services | |||
| %p | |||
| %a{ :href => "/services/#{service.slug}" } | |||
| = service.name | |||
| .grid_6 | |||
| %h3 Suppliers | |||
| - for supplier in @directorate.suppliers | |||
| %p | |||
| %a{ :href => "/suppliers/#{supplier.slug}" } | |||
| = supplier.name | |||
| @@ -26,8 +26,6 @@ | |||
| %tr | |||
| %td Transaction Number | |||
| %td= @payment.trans_no.nil? ? "unknown" : @payment.trans_no | |||
| %tr | |||
| %td Type | |||
| %td= @payment.tyype | |||
| @@ -7,17 +7,40 @@ | |||
| %li | |||
| = @service.name | |||
| %h2= @page_title = @service.name + " (Service)" | |||
| %h2= @page_title = @service.name | |||
| %p | |||
| A service in the | |||
| %a{ :href => '/directorates/' + @service.directorate.slug } | |||
| = @service.directorate.name | |||
| Directorate | |||
| %p.noprint.download | |||
| %a{ :href => "/services/#{@service.slug}.csv" } | |||
| Download data as CSV | |||
| %h3 Summary | |||
| %table | |||
| %tr | |||
| %th.right Payments | |||
| %th.right Max £ | |||
| %th.right Min £ | |||
| %th.right Average £ | |||
| %tr | |||
| %td.right= @count | |||
| %td.right= sprintf("%0d", @max) | |||
| %td.right= sprintf("%0d", @min) | |||
| %td.right= sprintf("%0d", @avg) | |||
| %h3 Payments to Suppliers | |||
| %table | |||
| %tr | |||
| %th Date | |||
| %th Ref. | |||
| %th Directorate | |||
| %th Supplier | |||
| %th.right £ | |||
| @@ -27,9 +50,6 @@ | |||
| %td.right | |||
| %a{ :href => "/payments/#{payment.id}" } | |||
| = payment.id | |||
| %td | |||
| %a{ :href => '/directorates/' + payment.directorate.slug } | |||
| = payment.directorate.name | |||
| %td | |||
| %a{ :href => '/suppliers/' + payment.supplier.slug } | |||
| = payment.supplier.name | |||
| @@ -38,21 +58,9 @@ | |||
| %tr | |||
| %td | |||
| %td | |||
| %td | |||
| %td | |||
| %strong TOTAL | |||
| %td.right= sprintf("%0d", @total) | |||
| %table | |||
| %tr | |||
| %th.right Count | |||
| %th.right Max | |||
| %th.right Min | |||
| %th.right Average | |||
| %tr | |||
| %td.right= @count | |||
| %td.right= sprintf("%0d", @max) | |||
| %td.right= sprintf("%0d", @min) | |||
| %td.right= sprintf("%0d", @avg) | |||
| @@ -9,9 +9,31 @@ | |||
| %h2= @page_title = @supplier.name + " (Supplier)" | |||
| %p.noprint | |||
| %a{ :href => "http://www.google.co.uk/search?q=#{@supplier.name}" } | |||
| Search Google for | |||
| = @supplier.name | |||
| %p.noprint.download | |||
| %a{ :href => "/suppliers/#{@supplier.slug}.csv" } | |||
| Download data as CSV | |||
| %h3 Summary | |||
| %table | |||
| %tr | |||
| %th.right Payments | |||
| %th.right Max £ | |||
| %th.right Min £ | |||
| %th.right Average £ | |||
| %tr | |||
| %td.right= @count | |||
| %td.right= sprintf("%0d", @max) | |||
| %td.right= sprintf("%0d", @min) | |||
| %td.right= sprintf("%0d", @avg) | |||
| %h3 Payments from the Council | |||
| %table | |||
| %tr | |||