paperless_to_xero 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Matt Patterson
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,3 +1,4 @@
1
+ require "rubygems"
1
2
  require 'rake'
2
3
  require 'rake/rdoctask'
3
4
  gem 'rspec'
@@ -39,101 +40,30 @@ namespace :spec do
39
40
  end
40
41
  end
41
42
 
42
- require "rubygems"
43
- require "rake/gempackagetask"
44
-
45
- # This builds the actual gem. For details of what all these options
46
- # mean, and other ones you can add, check the documentation here:
47
- #
48
- # http://rubygems.org/read/chapter/20
49
- #
50
- spec = Gem::Specification.new do |s|
51
-
52
- # Change these as appropriate
53
- s.name = "paperless_to_xero"
54
- s.version = PaperlessToXero::Version()
55
- s.summary = "Convert Paperless CSV exports to Xero invoice import CSV"
56
- s.description = File.read('README.rdoc')
57
- s.author = "Matt Patterson"
58
- s.email = "matt@reprocessed.org"
59
- s.homepage = "http://reprocessed.org/"
60
-
61
- s.has_rdoc = true
62
- s.extra_rdoc_files = %w(README.rdoc)
63
- s.rdoc_options = %w(--main README.rdoc)
64
-
65
- # Add any extra files to include in the gem
66
- s.files = %w(Rakefile README.rdoc) + Dir.glob("{bin,spec,lib}/**/*")
67
- s.executables = FileList["bin/**"].map { |f| File.basename(f) }
68
-
69
- s.require_paths = ["lib"]
70
-
71
- # If you want to depend on other gems, add them here, along with any
72
- # relevant versions
73
-
74
- s.add_development_dependency("rspec") # add any other gems for testing/development
43
+ begin
44
+ require 'jeweler'
45
+ Jeweler::Tasks.new do |s|
46
+ s.name = "paperless_to_xero"
47
+ s.summary = "Convert Paperless CSV exports to Xero invoice import CSV"
48
+ s.description = File.read('README.rdoc')
49
+ s.authors = ["Matt Patterson"]
50
+ s.email = "matt@reprocessed.org"
51
+ s.homepage = "http://github.com/fidothe/paperless_to_xero/"
52
+
53
+ s.extra_rdoc_files = %w(README.rdoc)
54
+ s.rdoc_options = %w(--main README.rdoc)
75
55
 
76
- # If you want to publish automatically to rubyforge, you'll may need
77
- # to tweak this, and the publishing task below too.
78
- s.rubyforge_project = "paperless_to_xero"
79
- end
56
+ s.require_paths = ["lib"]
80
57
 
81
- # This task actually builds the gem. We also regenerate a static
82
- # .gemspec file, which is useful if something (i.e. GitHub) will
83
- # be automatically building a gem for this project. If you're not
84
- # using GitHub, edit as appropriate.
85
- Rake::GemPackageTask.new(spec) do |pkg|
86
- pkg.gem_spec = spec
87
-
88
- # Generate the gemspec file for github.
89
- file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
90
- File.open(file, "w") {|f| f << spec.to_ruby }
91
- end
58
+ # If you want to depend on other gems, add them here, along with any
59
+ # relevant versions
92
60
 
93
- desc 'Clear out RDoc and generated packages'
94
- task :clean => [:clobber_rdoc, :clobber_package] do
95
- rm "#{spec.name}.gemspec"
96
- end
61
+ s.add_development_dependency("rspec") # add any other gems for testing/development
97
62
 
98
- # If you want to publish to RubyForge automatically, here's a simple
99
- # task to help do that. If you don't, just get rid of this.
100
- # Be sure to set up your Rubyforge account details with the Rubyforge
101
- # gem; you'll need to run `rubyforge setup` and `rubyforge config` at
102
- # the very least.
103
- begin
104
- require "rake/contrib/sshpublisher"
105
- namespace :rubyforge do
106
-
107
- desc "Release gem and RDoc documentation to RubyForge"
108
- task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
109
-
110
- namespace :release do
111
- desc "Release a new version of this gem"
112
- task :gem => [:package] do
113
- require 'rubyforge'
114
- rubyforge = RubyForge.new
115
- rubyforge.configure
116
- rubyforge.login
117
- rubyforge.userconfig['release_notes'] = spec.summary
118
- path_to_gem = File.join(File.dirname(__FILE__), "pkg", "#{spec.name}-#{spec.version}.gem")
119
- puts "Publishing #{spec.name}-#{spec.version.to_s} to Rubyforge..."
120
- rubyforge.add_release(spec.rubyforge_project, spec.name, spec.version.to_s, path_to_gem)
121
- end
122
-
123
- desc "Publish RDoc to RubyForge."
124
- task :docs => [:rdoc] do
125
- config = YAML.load(
126
- File.read(File.expand_path('~/.rubyforge/user-config.yml'))
127
- )
128
-
129
- host = "#{config['username']}@rubyforge.org"
130
- remote_dir = "/var/www/gforge-projects/coop_to_ofx/" # Should be the same as the rubyforge project name
131
- local_dir = 'rdoc'
132
-
133
- Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
134
- end
135
- end
63
+ # If you want to publish automatically to rubyforge, you'll may need
64
+ # to tweak this, and the publishing task below too.
65
+ s.rubyforge_project = "paperless_to_xero"
136
66
  end
137
67
  rescue LoadError
138
- puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
68
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
139
69
  end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.2.0
@@ -1,8 +1,12 @@
1
1
  require 'csv'
2
2
  require 'date'
3
+ require 'paperless_to_xero/errors'
3
4
 
4
5
  module PaperlessToXero
6
+ PAPERLESS_HEADER_ROW = ["Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"]
5
7
  class Converter
8
+ VAT_RATE_CHANGE_2008_12_01 = Date.parse('2008-12-01')
9
+ VAT_RATE_CHANGE_2010_01_01 = Date.parse('2010-01-01')
6
10
  attr_reader :input_path, :output_path
7
11
 
8
12
  def initialize(input_path, output_path)
@@ -13,12 +17,17 @@ module PaperlessToXero
13
17
  @invoices ||= []
14
18
  end
15
19
 
20
+ def verify_header_row!(row)
21
+ raise UnknownHeaderRow unless row == PaperlessToXero::PAPERLESS_HEADER_ROW
22
+ end
23
+
16
24
  def parse
17
25
  input_csv = CSV.read(input_path)
18
- # remove Paperless header row
19
- input_csv.shift
26
+ # verify Paperless header row
27
+ verify_header_row!(input_csv.shift)
20
28
 
21
- input_csv.each do |row|
29
+ input_csv.each_with_index do |row, index|
30
+ line_number = index + 1
22
31
  date, merchant, paperless_currency, amount, vat, category, payment_method, notes_field, description, reference, status, *extras = row
23
32
  negative = amount.index('--') == 0
24
33
  category = category[0..2] unless category.nil?
@@ -30,17 +39,25 @@ module PaperlessToXero
30
39
  total_vat = vat.nil? ? "0.00" : vat
31
40
  invoice = PaperlessToXero::Invoice.new(extract_date(date), merchant, reference, amount, total_vat, inc_vat?(notes), extract_currency(notes))
32
41
  if extras.empty?
33
- invoice.add_item(description, amount, vat, category, extract_vat_note(vat, notes))
42
+ begin
43
+ invoice.add_item(description, amount, vat, category, extract_vat_note(invoice.date, vat, notes))
44
+ rescue
45
+ raise BadItem.new(line_number, row, "Couldn't process this item")
46
+ end
34
47
  else
35
- raise RangeError, "input CSV row is badly formatted" unless extras.size % 6 == 0
48
+ raise IncorrectNumberOfColumns.new(line_number, row, "Extra items are badly formatted") unless extras.size % 6 == 0
36
49
  items = chunk_extras(extras)
37
50
  items.each do |item|
38
- description, paperless_currency, amount, unknown, category, notes_field = item
39
- category = category[0..2]
40
- notes = extract_notes(notes_field)
41
- vat_amount = extract_vat_amount(notes)
42
- vat_note = extract_vat_note(vat_amount, notes)
43
- invoice.add_item(description, amount, vat_amount, category, vat_note)
51
+ begin
52
+ description, paperless_currency, amount, unknown, category, notes_field = item
53
+ category = category[0..2]
54
+ notes = extract_notes(notes_field)
55
+ vat_amount = extract_vat_amount(notes)
56
+ vat_note = extract_vat_note(invoice.date, vat_amount, notes)
57
+ invoice.add_item(description, amount, vat_amount, category, vat_note)
58
+ rescue
59
+ raise BadItem.new(line_number, row, "Couldn't process this item")
60
+ end
44
61
  end
45
62
  end
46
63
  invoices << invoice
@@ -117,7 +134,7 @@ module PaperlessToXero
117
134
  nil
118
135
  end
119
136
 
120
- def extract_vat_note(vat_amount, notes)
137
+ def extract_vat_note(date, vat_amount, notes)
121
138
  notes.each do |item|
122
139
  return item if item.match(/^VAT/)
123
140
  end
@@ -128,7 +145,8 @@ module PaperlessToXero
128
145
  when nil
129
146
  'No VAT'
130
147
  else
131
- 'VAT - 15%'
148
+ return 'VAT - 15%' if date >= VAT_RATE_CHANGE_2008_12_01 && date < VAT_RATE_CHANGE_2010_01_01
149
+ 'VAT - 17.5%'
132
150
  end
133
151
  end
134
152
  end
@@ -0,0 +1,15 @@
1
+ module PaperlessToXero
2
+ class UnknownHeaderRow < StandardError; end
3
+ class RowError < StandardError
4
+ def initialize(line_number, row, explanation = "")
5
+ @line_number, @row, @explanation = line_number, row, explanation
6
+ end
7
+
8
+ def to_s
9
+ "Error processing line #{@line_number.to_s}: #{@explanation}. Row was #{@row.inspect}"
10
+ end
11
+ end
12
+
13
+ class IncorrectNumberOfColumns < RowError; end
14
+ class BadItem < RowError; end
15
+ end
@@ -17,6 +17,7 @@ module PaperlessToXero
17
17
  '21.5% (Ireland, VAT on expenses)' => 1.215.to_d,
18
18
  '15% (EU VAT ID)' => 1.15.to_d,
19
19
  '15% (VAT on expenses)' => 1.15.to_d,
20
+ '17.5% (VAT on expenses)' => 1.175.to_d,
20
21
  'Zero Rated Expenses' => 0,
21
22
  '15% (Luxembourg, VAT on expenses)' => 1.15.to_d
22
23
  }
@@ -76,6 +77,8 @@ module PaperlessToXero
76
77
  '15% (EU VAT ID)'
77
78
  when 'VAT - 15%'
78
79
  '15% (VAT on expenses)'
80
+ when 'VAT - 17.5%'
81
+ '17.5% (VAT on expenses)'
79
82
  when 'VAT - 0%'
80
83
  'Zero Rated Expenses'
81
84
  when 'No VAT'
@@ -0,0 +1,91 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{paperless_to_xero}
8
+ s.version = "1.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matt Patterson"]
12
+ s.date = %q{2010-02-27}
13
+ s.default_executable = %q{paperless_to_xero}
14
+ s.description = %q{= Paperless-to-Xero
15
+
16
+ A simple translator which takes a CSV file from Mariner's Paperless receipt/document management software and makes a Xero accounts payable invoice CSV, for import into Xero.
17
+
18
+ Formatting in Paperless is very important, so you probably want to wait until I've written the docs}
19
+ s.email = %q{matt@reprocessed.org}
20
+ s.executables = ["paperless_to_xero"]
21
+ s.extra_rdoc_files = [
22
+ "README.rdoc"
23
+ ]
24
+ s.files = [
25
+ "MIT-LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "bin/paperless_to_xero",
30
+ "lib/paperless_to_xero.rb",
31
+ "lib/paperless_to_xero/converter.rb",
32
+ "lib/paperless_to_xero/decimal_helpers.rb",
33
+ "lib/paperless_to_xero/errors.rb",
34
+ "lib/paperless_to_xero/invoice.rb",
35
+ "lib/paperless_to_xero/invoice_item.rb",
36
+ "lib/paperless_to_xero/version.rb",
37
+ "paperless_to_xero.gemspec",
38
+ "spec/fixtures/dodgy-header.csv",
39
+ "spec/fixtures/end_to_end-input.csv",
40
+ "spec/fixtures/end_to_end-output.csv",
41
+ "spec/fixtures/multi-ex-vat.csv",
42
+ "spec/fixtures/multi-foreign.csv",
43
+ "spec/fixtures/multi-item-mixed_vat_and_exempt.csv",
44
+ "spec/fixtures/multi-item.csv",
45
+ "spec/fixtures/single-1000.csv",
46
+ "spec/fixtures/single-basic.csv",
47
+ "spec/fixtures/single-dkk.csv",
48
+ "spec/fixtures/single-foreign.csv",
49
+ "spec/fixtures/single-no-vat.csv",
50
+ "spec/fixtures/single-vat-2008-11-30.csv",
51
+ "spec/fixtures/single-vat-2008-12-01.csv",
52
+ "spec/fixtures/single-vat-2009-12-31.csv",
53
+ "spec/fixtures/single-vat-2009.csv",
54
+ "spec/fixtures/single-vat-2010-01-01.csv",
55
+ "spec/fixtures/single-vat-pre-2008-12.csv",
56
+ "spec/fixtures/single-zero_rated.csv",
57
+ "spec/paperless_to_xero/converter_spec.rb",
58
+ "spec/paperless_to_xero/errors_spec.rb",
59
+ "spec/paperless_to_xero/invoice_item_spec.rb",
60
+ "spec/paperless_to_xero/invoice_spec.rb",
61
+ "spec/spec.opts",
62
+ "spec/spec_helper.rb"
63
+ ]
64
+ s.homepage = %q{http://github.com/fidothe/paperless_to_xero/}
65
+ s.rdoc_options = ["--main", "README.rdoc"]
66
+ s.require_paths = ["lib"]
67
+ s.rubyforge_project = %q{paperless_to_xero}
68
+ s.rubygems_version = %q{1.3.6}
69
+ s.summary = %q{Convert Paperless CSV exports to Xero invoice import CSV}
70
+ s.test_files = [
71
+ "spec/paperless_to_xero/converter_spec.rb",
72
+ "spec/paperless_to_xero/errors_spec.rb",
73
+ "spec/paperless_to_xero/invoice_item_spec.rb",
74
+ "spec/paperless_to_xero/invoice_spec.rb",
75
+ "spec/spec_helper.rb"
76
+ ]
77
+
78
+ if s.respond_to? :specification_version then
79
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
80
+ s.specification_version = 3
81
+
82
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
83
+ s.add_development_dependency(%q<rspec>, [">= 0"])
84
+ else
85
+ s.add_dependency(%q<rspec>, [">= 0"])
86
+ end
87
+ else
88
+ s.add_dependency(%q<rspec>, [">= 0"])
89
+ end
90
+ end
91
+
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 26/01/2009,"Fastlane Cabs","£","4.50",,"493 - Travel National","Cash",,"Taxi in Nottingham","2009-01-26-03",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 23/07/2009,"Post Office","£","3.55","0.29","425 - Postage, Freight & Courier","Credit Card",,,"2009-07-23-03",,"Envelopes","£","2.19",,"429 - General Expenses","0.29; VAT - 15%","Postage","£","1.36",,"425 - Postage, Freight & Courier","VAT - 0%"
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 30/11/2008,"Apple Store, Regent Street","£","117.50","17.50","429 - General Expenses","Debit Card",,"Phone case","2008-11-30-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 01/12/2008,"Apple Store, Regent Street","£","115","15","429 - General Expenses","Debit Card",,"Phone case","2008-12-01-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 31/12/2009,"Apple Store, Regent Street","£","115","15","429 - General Expenses","Debit Card",,"Phone case","2009-12-31-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 01/06/2009,"Apple Store, Regent Street","£","115","15","429 - General Expenses","Debit Card",,"Phone case","2009-06-01-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 01/01/2010,"Apple Store, Regent Street","£","117.50","17.50","429 - General Expenses","Debit Card",,"Phone case","2010-01-01-05",
@@ -0,0 +1,2 @@
1
+ "Date","Merchant","Currency","Amount","Tax","Category","Payment Method","Notes","Description","Reference #","Status"
2
+ 18/05/2008,"Apple Store, Regent Street","£","117.50","17.50","429 - General Expenses","Debit Card",,"Phone case","2008-05-18-05",
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
  require 'tempfile'
3
3
 
4
4
  Spec::Matchers.define :have_detail_matching do |key, value|
@@ -48,6 +48,13 @@ describe PaperlessToXero::Converter do
48
48
  end
49
49
  end
50
50
 
51
+ describe "checking the header row" do
52
+ it "should raise an UnknownHeaderRow error if it doesn't recognise the header..." do
53
+ @converter.stubs(:input_path).returns(fixture_path('dodgy-header'))
54
+ lambda { @converter.parse }.should raise_error(PaperlessToXero::UnknownHeaderRow)
55
+ end
56
+ end
57
+
51
58
  describe "single item inputs" do
52
59
  it "should able to create an invoice for a basic single-item invoice" do
53
60
  @converter.stubs(:input_path).returns(fixture_path('single-basic'))
@@ -133,6 +140,110 @@ describe PaperlessToXero::Converter do
133
140
  ]
134
141
  )
135
142
  end
143
+
144
+ describe "UK VAT rate changes" do
145
+ describe "pre 2008-12 17.5% VAT" do
146
+ it "correctly handles days in that VAT rate" do
147
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-pre-2008-12'))
148
+ @converter.parse
149
+
150
+ verify_invoice_details(
151
+ :invoice => {:date => Date.parse('2008-05-18'), :merchant => 'Apple Store, Regent Street',
152
+ :reference_id => '2008-05-18-05', :inc_vat_total => '117.50', :vat_total => '17.50',
153
+ :ex_vat_total => '100.00', :currency => 'GBP'},
154
+ :vat_inclusive => true,
155
+ :line_items => [
156
+ {:description => 'Phone case', :category => '429', :vat_type => '17.5% (VAT on expenses)',
157
+ :vat_inclusive_amount => '117.50', :vat_exclusive_amount => '100.00', :vat_amount => '17.50'}
158
+ ]
159
+ )
160
+ end
161
+
162
+ it "correctly handles the last day of that VAT rate" do
163
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2008-11-30'))
164
+ @converter.parse
165
+
166
+ verify_invoice_details(
167
+ :invoice => {:date => Date.parse('2008-11-30'), :merchant => 'Apple Store, Regent Street',
168
+ :reference_id => '2008-11-30-05', :inc_vat_total => '117.50', :vat_total => '17.50',
169
+ :ex_vat_total => '100.00', :currency => 'GBP'},
170
+ :vat_inclusive => true,
171
+ :line_items => [
172
+ {:description => 'Phone case', :category => '429', :vat_type => '17.5% (VAT on expenses)',
173
+ :vat_inclusive_amount => '117.50', :vat_exclusive_amount => '100.00', :vat_amount => '17.50'}
174
+ ]
175
+ )
176
+ end
177
+ end
178
+
179
+ describe "2009's 15% VAT rate" do
180
+ it "correctly handles the first day of that VAT rate" do
181
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2008-12-01'))
182
+ @converter.parse
183
+
184
+ verify_invoice_details(
185
+ :invoice => {:date => Date.parse('2008-12-01'), :merchant => 'Apple Store, Regent Street',
186
+ :reference_id => '2008-12-01-05', :inc_vat_total => '115.00', :vat_total => '15.00',
187
+ :ex_vat_total => '100.00', :currency => 'GBP'},
188
+ :vat_inclusive => true,
189
+ :line_items => [
190
+ {:description => 'Phone case', :category => '429', :vat_type => '15% (VAT on expenses)',
191
+ :vat_inclusive_amount => '115.00', :vat_exclusive_amount => '100.00', :vat_amount => '15.00'}
192
+ ]
193
+ )
194
+ end
195
+
196
+ it "correctly handles days in that VAT rate" do
197
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2009'))
198
+ @converter.parse
199
+
200
+ verify_invoice_details(
201
+ :invoice => {:date => Date.parse('2009-06-01'), :merchant => 'Apple Store, Regent Street',
202
+ :reference_id => '2009-06-01-05', :inc_vat_total => '115.00', :vat_total => '15.00',
203
+ :ex_vat_total => '100.00', :currency => 'GBP'},
204
+ :vat_inclusive => true,
205
+ :line_items => [
206
+ {:description => 'Phone case', :category => '429', :vat_type => '15% (VAT on expenses)',
207
+ :vat_inclusive_amount => '115.00', :vat_exclusive_amount => '100.00', :vat_amount => '15.00'}
208
+ ]
209
+ )
210
+ end
211
+
212
+ it "correctly handles the last day of that VAT rate" do
213
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2009-12-31'))
214
+ @converter.parse
215
+
216
+ verify_invoice_details(
217
+ :invoice => {:date => Date.parse('2009-12-31'), :merchant => 'Apple Store, Regent Street',
218
+ :reference_id => '2009-12-31-05', :inc_vat_total => '115.00', :vat_total => '15.00',
219
+ :ex_vat_total => '100.00', :currency => 'GBP'},
220
+ :vat_inclusive => true,
221
+ :line_items => [
222
+ {:description => 'Phone case', :category => '429', :vat_type => '15% (VAT on expenses)',
223
+ :vat_inclusive_amount => '115.00', :vat_exclusive_amount => '100.00', :vat_amount => '15.00'}
224
+ ]
225
+ )
226
+ end
227
+ end
228
+
229
+ describe "2010-01-01's return to 17.5% VAT" do
230
+ it "correctly handles the first day of that VAT rate" do
231
+ @converter.stubs(:input_path).returns(fixture_path('single-vat-2010-01-01'))
232
+ @converter.parse
233
+
234
+ verify_invoice_details(
235
+ :invoice => {:date => Date.parse('2010-01-01'), :merchant => 'Apple Store, Regent Street',
236
+ :reference_id => '2010-01-01-05', :inc_vat_total => '117.50', :vat_total => '17.50',
237
+ :ex_vat_total => '100.00', :currency => 'GBP'},
238
+ :vat_inclusive => true,
239
+ :line_items => [
240
+ {:description => 'Phone case', :category => '429', :vat_type => '17.5% (VAT on expenses)',
241
+ :vat_inclusive_amount => '117.50', :vat_exclusive_amount => '100.00', :vat_amount => '17.50'}
242
+ ]
243
+ )
244
+ end
245
+ end
246
+ end
136
247
  end
137
248
 
138
249
  describe "multi-item inputs" do
@@ -192,6 +303,24 @@ describe PaperlessToXero::Converter do
192
303
  ]
193
304
  )
194
305
  end
306
+
307
+ it "should be able to cope with an multi-line invoice with mixed VAT and VAT-exempt lines" do
308
+ @converter.stubs(:input_path).returns(fixture_path('multi-item-mixed_vat_and_exempt'))
309
+ @converter.parse
310
+
311
+ verify_invoice_details(
312
+ :invoice => {:date => Date.parse('2009-07-23'), :merchant => 'Post Office',
313
+ :reference_id => '2009-07-23-03', :inc_vat_total => '3.55', :vat_total => '0.29',
314
+ :ex_vat_total => '3.26', :currency => 'GBP'},
315
+ :vat_inclusive => false,
316
+ :line_items => [
317
+ {:description => 'Envelopes', :category => '429', :vat_type => '15% (VAT on expenses)',
318
+ :vat_inclusive_amount => '2.19', :vat_exclusive_amount => '1.90', :vat_amount => '0.29'},
319
+ {:description => 'Postage', :category => '425', :vat_type => 'Zero Rated Expenses',
320
+ :vat_inclusive_amount => '1.36', :vat_exclusive_amount => '1.36', :vat_amount => '0.00'}
321
+ ]
322
+ )
323
+ end
195
324
  end
196
325
 
197
326
  describe "end-to-end" do
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe PaperlessToXero::RowError do
4
+ it "should be able to be instantiated with the line number, row contents and error message" do
5
+ PaperlessToXero::RowError.new(1, ["thing", "other thing"], "Bad thing happened").should be_instance_of(PaperlessToXero::RowError)
6
+ end
7
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe PaperlessToXero::InvoiceItem do
4
4
  describe "the creation basics" do
@@ -144,6 +144,7 @@ describe PaperlessToXero::InvoiceItem do
144
144
  'VAT - Luxembourg' => '15% (Luxembourg, VAT on expenses)',
145
145
  'VAT - EU' => '15% (EU VAT ID)',
146
146
  'VAT - EU - EU372000063' => '15% (EU VAT ID)',
147
+ 'VAT - 17.5%' => '17.5% (VAT on expenses)',
147
148
  'VAT - 15%' => '15% (VAT on expenses)',
148
149
  'VAT - 0%' => 'Zero Rated Expenses',
149
150
  'VAT' => '15% (VAT on expenses)',
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe PaperlessToXero::Invoice do
4
4
  describe "the creation basics" do
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paperless_to_xero
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 2
8
+ - 0
9
+ version: 1.2.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Matt Patterson
@@ -9,19 +14,21 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-07-22 00:00:00 +01:00
13
- default_executable:
17
+ date: 2010-02-27 00:00:00 +00:00
18
+ default_executable: paperless_to_xero
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: rspec
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
23
29
  version: "0"
24
- version:
30
+ type: :development
31
+ version_requirements: *id001
25
32
  description: |-
26
33
  = Paperless-to-Xero
27
34
 
@@ -36,33 +43,46 @@ extensions: []
36
43
  extra_rdoc_files:
37
44
  - README.rdoc
38
45
  files:
39
- - Rakefile
46
+ - MIT-LICENSE
40
47
  - README.rdoc
48
+ - Rakefile
49
+ - VERSION
41
50
  - bin/paperless_to_xero
51
+ - lib/paperless_to_xero.rb
52
+ - lib/paperless_to_xero/converter.rb
53
+ - lib/paperless_to_xero/decimal_helpers.rb
54
+ - lib/paperless_to_xero/errors.rb
55
+ - lib/paperless_to_xero/invoice.rb
56
+ - lib/paperless_to_xero/invoice_item.rb
57
+ - lib/paperless_to_xero/version.rb
58
+ - paperless_to_xero.gemspec
59
+ - spec/fixtures/dodgy-header.csv
42
60
  - spec/fixtures/end_to_end-input.csv
43
61
  - spec/fixtures/end_to_end-output.csv
44
62
  - spec/fixtures/multi-ex-vat.csv
45
63
  - spec/fixtures/multi-foreign.csv
64
+ - spec/fixtures/multi-item-mixed_vat_and_exempt.csv
46
65
  - spec/fixtures/multi-item.csv
47
66
  - spec/fixtures/single-1000.csv
48
67
  - spec/fixtures/single-basic.csv
49
68
  - spec/fixtures/single-dkk.csv
50
69
  - spec/fixtures/single-foreign.csv
51
70
  - spec/fixtures/single-no-vat.csv
71
+ - spec/fixtures/single-vat-2008-11-30.csv
72
+ - spec/fixtures/single-vat-2008-12-01.csv
73
+ - spec/fixtures/single-vat-2009-12-31.csv
74
+ - spec/fixtures/single-vat-2009.csv
75
+ - spec/fixtures/single-vat-2010-01-01.csv
76
+ - spec/fixtures/single-vat-pre-2008-12.csv
52
77
  - spec/fixtures/single-zero_rated.csv
53
78
  - spec/paperless_to_xero/converter_spec.rb
79
+ - spec/paperless_to_xero/errors_spec.rb
54
80
  - spec/paperless_to_xero/invoice_item_spec.rb
55
81
  - spec/paperless_to_xero/invoice_spec.rb
56
82
  - spec/spec.opts
57
83
  - spec/spec_helper.rb
58
- - lib/paperless_to_xero/converter.rb
59
- - lib/paperless_to_xero/decimal_helpers.rb
60
- - lib/paperless_to_xero/invoice.rb
61
- - lib/paperless_to_xero/invoice_item.rb
62
- - lib/paperless_to_xero/version.rb
63
- - lib/paperless_to_xero.rb
64
84
  has_rdoc: true
65
- homepage: http://reprocessed.org/
85
+ homepage: http://github.com/fidothe/paperless_to_xero/
66
86
  licenses: []
67
87
 
68
88
  post_install_message:
@@ -75,20 +95,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
95
  requirements:
76
96
  - - ">="
77
97
  - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
78
100
  version: "0"
79
- version:
80
101
  required_rubygems_version: !ruby/object:Gem::Requirement
81
102
  requirements:
82
103
  - - ">="
83
104
  - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
84
107
  version: "0"
85
- version:
86
108
  requirements: []
87
109
 
88
110
  rubyforge_project: paperless_to_xero
89
- rubygems_version: 1.3.4
111
+ rubygems_version: 1.3.6
90
112
  signing_key:
91
113
  specification_version: 3
92
114
  summary: Convert Paperless CSV exports to Xero invoice import CSV
93
- test_files: []
94
-
115
+ test_files:
116
+ - spec/paperless_to_xero/converter_spec.rb
117
+ - spec/paperless_to_xero/errors_spec.rb
118
+ - spec/paperless_to_xero/invoice_item_spec.rb
119
+ - spec/paperless_to_xero/invoice_spec.rb
120
+ - spec/spec_helper.rb