uomi 0.2.15 → 0.2.16
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.
- data/Gemfile +3 -2
- data/lib/uomi.rb +12 -9
- data/lib/uomi/credit_note.rb +40 -9
- data/lib/uomi/version.rb +1 -1
- data/spec/lib/uomi/credit_note_spec.rb +121 -18
- data/uomi.gemspec +1 -0
- metadata +112 -93
data/Gemfile
CHANGED
data/lib/uomi.rb
CHANGED
@@ -9,18 +9,21 @@ module Uomi
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.generate_invoice(&block)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
ActiveRecord::Base.transaction do
|
13
|
+
invoice = Invoice.new
|
14
|
+
invoice.instance_eval(&block)
|
15
|
+
invoice.save!
|
16
|
+
invoice
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.generate_credit_note(&block)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
ActiveRecord::Base.transaction do
|
22
|
+
credit_note = CreditNote.new
|
23
|
+
credit_note.instance_eval(&block)
|
24
|
+
credit_note.save!
|
25
|
+
credit_note
|
26
|
+
end
|
24
27
|
end
|
25
28
|
|
26
29
|
end
|
data/lib/uomi/credit_note.rb
CHANGED
@@ -2,21 +2,21 @@ module Uomi
|
|
2
2
|
class CreditNote < Invoice
|
3
3
|
alias_attribute :receipt_number, :invoice_number
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
has_many :credit_note_invoices, dependent: :destroy
|
6
|
+
has_many :invoices, through: :credit_note_invoices
|
7
7
|
has_many :credit_note_credit_transactions, dependent: :destroy
|
8
8
|
|
9
9
|
def issue(issued_at = Time.now)
|
10
10
|
self.issued_at = issued_at
|
11
11
|
create_initial_transaction!
|
12
|
-
record_transaction_against_invoice!
|
12
|
+
record_transaction_against_invoice! unless self.invoices.blank?
|
13
13
|
record_credit_notes!
|
14
|
+
record_transaction!
|
14
15
|
end
|
15
16
|
|
16
17
|
def record_transaction_against_invoice!
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
invoice = invoices.first
|
19
|
+
validate(invoice: invoice, amount: self.total)
|
20
20
|
invoice.add_credit_transaction(amount: total)
|
21
21
|
invoice.save!
|
22
22
|
CreditNoteCreditTransaction.create!(transaction: invoice.transactions.last, credit_note_id: self.id)
|
@@ -24,10 +24,10 @@ module Uomi
|
|
24
24
|
|
25
25
|
def credit(options={})
|
26
26
|
add_line_item(
|
27
|
-
invoiceable: options[:line_item].invoiceable,
|
27
|
+
invoiceable: options[:line_item].andand.invoiceable,
|
28
28
|
amount: options[:amount] || 0,
|
29
29
|
tax: options[:tax] || 0,
|
30
|
-
description: options[:description] || "Credit note against #{options[:line_item].description}" #?
|
30
|
+
description: options[:description] || "Credit note against #{options[:line_item].andand.description}" #?
|
31
31
|
)
|
32
32
|
end
|
33
33
|
|
@@ -35,11 +35,17 @@ module Uomi
|
|
35
35
|
raise RuntimeError, "You must allocate a credit note against an invoice" if invoice.blank?
|
36
36
|
raise RuntimeError, "You must allocate a credit note against an issued invoice" unless invoice.issued?
|
37
37
|
|
38
|
-
self.
|
38
|
+
self.credit_note_invoices << CreditNoteInvoice.new(invoice_id: invoice.id)
|
39
39
|
self.buyer = invoice.buyer
|
40
40
|
self.seller = invoice.seller
|
41
41
|
end
|
42
42
|
|
43
|
+
def record_transaction!
|
44
|
+
unless self.invoices.blank?
|
45
|
+
add_debit_transaction(amount: total)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
43
49
|
def record_credit_notes!
|
44
50
|
line_items.each do |line_item|
|
45
51
|
invoiceable = line_item.invoiceable
|
@@ -66,5 +72,30 @@ module Uomi
|
|
66
72
|
|
67
73
|
save!
|
68
74
|
end
|
75
|
+
|
76
|
+
def validate(options={})
|
77
|
+
raise RuntimeError, "You must allocate this credit against an invoice" if options[:invoice].blank?
|
78
|
+
raise RuntimeError, "You must allocate this credit against a Uomi Invoice" unless options[:invoice].is_a?(Uomi::Invoice)
|
79
|
+
raise RuntimeError, "You cannot allocate nothing to the invoice" if (options[:amount].blank? || options[:amount].zero?)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Refund section
|
83
|
+
|
84
|
+
def refund(&block)
|
85
|
+
instance_eval(&block)
|
86
|
+
save!
|
87
|
+
end
|
88
|
+
|
89
|
+
def set_balance_off(options={})
|
90
|
+
validate(options)
|
91
|
+
invoice = options[:invoice]
|
92
|
+
|
93
|
+
invoice.add_credit_transaction(amount: options[:amount])
|
94
|
+
against_invoice(invoice)
|
95
|
+
invoice.save!
|
96
|
+
|
97
|
+
self.add_debit_transaction(amount: options[:amount])
|
98
|
+
CreditNoteCreditTransaction.create!(transaction: invoice.transactions.last, credit_note_id: self.id)
|
99
|
+
end
|
69
100
|
end
|
70
101
|
end
|
data/lib/uomi/version.rb
CHANGED
@@ -60,11 +60,9 @@ describe Uomi::CreditNote do
|
|
60
60
|
against_invoice invoice
|
61
61
|
end
|
62
62
|
|
63
|
-
@
|
64
|
-
end
|
63
|
+
@credit_note.issue!
|
65
64
|
|
66
|
-
|
67
|
-
@credit_note.should be_issued
|
65
|
+
@invoice.reload
|
68
66
|
end
|
69
67
|
|
70
68
|
it "should have a receipt number" do
|
@@ -81,7 +79,7 @@ describe Uomi::CreditNote do
|
|
81
79
|
end
|
82
80
|
|
83
81
|
it "should know if it is linked to an invoice" do
|
84
|
-
@credit_note.
|
82
|
+
@credit_note.invoices.should == [@invoice]
|
85
83
|
end
|
86
84
|
|
87
85
|
it "should be linked to the credit transaction paid against the invoice" do
|
@@ -103,6 +101,124 @@ describe Uomi::CreditNote do
|
|
103
101
|
@credit_note.seller.sellerable.should == @invoice_seller
|
104
102
|
end
|
105
103
|
|
104
|
+
it "should set the balance to 0 if applied against an invoice" do
|
105
|
+
@credit_note.balance.should == 0
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should mark the credit note as settled" do
|
109
|
+
@credit_note.should be_settled
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
context "Ad Hoc Credit Note not applied to any invoices" do
|
115
|
+
before(:each) do
|
116
|
+
@credit_note = Uomi::generate_credit_note do
|
117
|
+
credit amount: 5000, description: 'Description'
|
118
|
+
credit amount: 2000, description: 'Another Description'
|
119
|
+
end
|
120
|
+
@credit_note.issue!
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should generate a credit note to the value of 70.00" do
|
124
|
+
@credit_note.total.should == 7000
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should have a balance of 70.00" do
|
128
|
+
@credit_note.balance.should == 7000
|
129
|
+
end
|
130
|
+
|
131
|
+
context "Applying credit note to multiple invoices" do
|
132
|
+
before(:each) do
|
133
|
+
@invoice1 = Uomi::generate_invoice do
|
134
|
+
line_item description: "Line Item 1", amount: 5000, line_item_type_id: 1
|
135
|
+
end
|
136
|
+
@invoice1.issue!
|
137
|
+
|
138
|
+
@invoice2 = Uomi::generate_invoice do
|
139
|
+
line_item description: "Line Item 1", amount: 2000, line_item_type_id: 1
|
140
|
+
end
|
141
|
+
@invoice2.issue!
|
142
|
+
end
|
143
|
+
|
144
|
+
context "Apply credit to invoice 1 and 2" do
|
145
|
+
before(:each) do
|
146
|
+
inv = @invoice1
|
147
|
+
|
148
|
+
@credit_note.refund do
|
149
|
+
set_balance_off invoice: inv, amount: 5000
|
150
|
+
end
|
151
|
+
|
152
|
+
@credit_note.reload
|
153
|
+
@invoice1.reload
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should set a credit note against an invoice" do
|
157
|
+
@invoice1.credit_notes.should == [@credit_note]
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should settle the invoice" do
|
161
|
+
@invoice1.should be_settled
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should set the balance on the credit note to 20" do
|
165
|
+
@credit_note.balance.should == 2000
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should have created a debit transaction on the credit note to the value of 50.00" do
|
169
|
+
@credit_note.debit_transactions.last.amount.should == 5000
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should have created a credit transaction against the invoice for 50.00" do
|
173
|
+
@invoice1.credit_transactions.last.amount.should == 5000
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should know which invoice the credit note has transacted against" do
|
177
|
+
t = @credit_note.credit_note_credit_transactions.last
|
178
|
+
t.transaction.invoice.should == @invoice1
|
179
|
+
end
|
180
|
+
|
181
|
+
context "apply 20-00 to invoice 2" do
|
182
|
+
before(:each) do
|
183
|
+
inv = @invoice2
|
184
|
+
|
185
|
+
@credit_note.refund do
|
186
|
+
set_balance_off invoice: inv, amount: 2000
|
187
|
+
end
|
188
|
+
|
189
|
+
@credit_note.reload
|
190
|
+
@invoice2.reload
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should set a credit note against an invoice1 and invoice 2" do
|
194
|
+
@invoice1.credit_notes.should == [@credit_note]
|
195
|
+
@invoice2.credit_notes.should == [@credit_note]
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should settle the invoice" do
|
199
|
+
@invoice2.should be_settled
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should settle the credit note" do
|
203
|
+
@credit_note.balance.should == 0
|
204
|
+
@credit_note.should be_settled
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should have created a debit transaction on the credit note to the value of 50.00" do
|
208
|
+
@credit_note.debit_transactions.last.amount.should == 2000
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should have created a credit transaction against the invoice for 50.00" do
|
212
|
+
@invoice2.credit_transactions.last.amount.should == 2000
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should know which invoice the credit note has transacted against" do
|
216
|
+
t = @credit_note.credit_note_credit_transactions.last
|
217
|
+
t.transaction.invoice.should == @invoice2
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
106
222
|
end
|
107
223
|
|
108
224
|
context "When applying credits to the invoiceables" do
|
@@ -119,19 +235,6 @@ describe Uomi::CreditNote do
|
|
119
235
|
end
|
120
236
|
|
121
237
|
end
|
122
|
-
|
123
|
-
context "trying to create a standalone credit note" do
|
124
|
-
|
125
|
-
it "should raise an error if no invoice is specified" do
|
126
|
-
expect {Uomi::generate_credit_note do
|
127
|
-
line_items.each do |line_item|
|
128
|
-
credit amount: 500, description: "Credit note for Line Item #{line_item.id}", tax: 0
|
129
|
-
end
|
130
|
-
decorate_with tenant_name: "Peter"
|
131
|
-
end}.to raise_error(RuntimeError, "You must allocate a credit note against an invoice")
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
238
|
end
|
136
239
|
|
137
240
|
end
|
data/uomi.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_dependency "activerecord", "~> 3.0"
|
23
23
|
s.add_dependency "i18n"
|
24
24
|
s.add_dependency "workflow", '= 0.8.7'
|
25
|
+
s.add_dependency "andand"
|
25
26
|
|
26
27
|
s.add_development_dependency 'combustion', '~> 0.3.1'
|
27
28
|
s.add_development_dependency 'database_cleaner', '~> 1.2.0'
|
metadata
CHANGED
@@ -1,121 +1,132 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: uomi
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 16
|
9
|
+
version: 0.2.16
|
6
10
|
platform: ruby
|
7
|
-
authors:
|
11
|
+
authors:
|
8
12
|
- Douglas Anderson
|
9
13
|
- Jeffrey van Aswegen
|
10
14
|
autorequire:
|
11
15
|
bindir: bin
|
12
16
|
cert_chain: []
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
|
18
|
+
date: 2014-09-16 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
16
22
|
name: activesupport
|
17
|
-
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
|
-
requirements:
|
20
|
-
- - ! '>='
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '0'
|
23
|
-
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
25
|
none: false
|
27
|
-
requirements:
|
28
|
-
- -
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
|
31
|
-
-
|
32
|
-
|
33
|
-
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
|
-
requirements:
|
36
|
-
- - ~>
|
37
|
-
- !ruby/object:Gem::Version
|
38
|
-
version: '3.0'
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
39
32
|
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: activerecord
|
40
36
|
prerelease: false
|
41
|
-
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
42
38
|
none: false
|
43
|
-
requirements:
|
39
|
+
requirements:
|
44
40
|
- - ~>
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
|
47
|
-
-
|
48
|
-
|
49
|
-
|
50
|
-
none: false
|
51
|
-
requirements:
|
52
|
-
- - ! '>='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 3
|
44
|
+
- 0
|
45
|
+
version: "3.0"
|
55
46
|
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: i18n
|
56
50
|
prerelease: false
|
57
|
-
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
52
|
none: false
|
59
|
-
requirements:
|
60
|
-
- -
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
|
63
|
-
-
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
type: :runtime
|
60
|
+
version_requirements: *id003
|
61
|
+
- !ruby/object:Gem::Dependency
|
64
62
|
name: workflow
|
65
|
-
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
65
|
none: false
|
67
|
-
requirements:
|
68
|
-
- -
|
69
|
-
- !ruby/object:Gem::Version
|
66
|
+
requirements:
|
67
|
+
- - "="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
- 8
|
72
|
+
- 7
|
70
73
|
version: 0.8.7
|
71
74
|
type: :runtime
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: andand
|
72
78
|
prerelease: false
|
73
|
-
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
74
80
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
-
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
version: "0"
|
87
|
+
type: :runtime
|
88
|
+
version_requirements: *id005
|
89
|
+
- !ruby/object:Gem::Dependency
|
80
90
|
name: combustion
|
81
|
-
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
|
-
requirements:
|
84
|
-
- - ~>
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
version: 0.3.1
|
87
|
-
type: :development
|
88
91
|
prerelease: false
|
89
|
-
|
92
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
90
93
|
none: false
|
91
|
-
requirements:
|
94
|
+
requirements:
|
92
95
|
- - ~>
|
93
|
-
- !ruby/object:Gem::Version
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
- 3
|
100
|
+
- 1
|
94
101
|
version: 0.3.1
|
95
|
-
- !ruby/object:Gem::Dependency
|
96
|
-
name: database_cleaner
|
97
|
-
requirement: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
|
-
requirements:
|
100
|
-
- - ~>
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
version: 1.2.0
|
103
102
|
type: :development
|
103
|
+
version_requirements: *id006
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: database_cleaner
|
104
106
|
prerelease: false
|
105
|
-
|
107
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
106
108
|
none: false
|
107
|
-
requirements:
|
109
|
+
requirements:
|
108
110
|
- - ~>
|
109
|
-
- !ruby/object:Gem::Version
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
segments:
|
113
|
+
- 1
|
114
|
+
- 2
|
115
|
+
- 0
|
110
116
|
version: 1.2.0
|
111
|
-
|
112
|
-
|
117
|
+
type: :development
|
118
|
+
version_requirements: *id007
|
119
|
+
description: " Manage invoices. "
|
120
|
+
email:
|
113
121
|
- i.am.douglas.anderson@gmail.com
|
114
122
|
- jeffmess@gmail.com
|
115
123
|
executables: []
|
124
|
+
|
116
125
|
extensions: []
|
126
|
+
|
117
127
|
extra_rdoc_files: []
|
118
|
-
|
128
|
+
|
129
|
+
files:
|
119
130
|
- .gitignore
|
120
131
|
- .rvmrc
|
121
132
|
- .travis.yml
|
@@ -158,31 +169,39 @@ files:
|
|
158
169
|
- spec/lib/uomi/overdue_invoice_spec.rb
|
159
170
|
- spec/spec_helper.rb
|
160
171
|
- uomi.gemspec
|
172
|
+
has_rdoc: true
|
161
173
|
homepage: https://github.com/tehtorq/invoicing
|
162
174
|
licenses: []
|
175
|
+
|
163
176
|
post_install_message:
|
164
177
|
rdoc_options: []
|
165
|
-
|
178
|
+
|
179
|
+
require_paths:
|
166
180
|
- lib
|
167
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
181
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
182
|
none: false
|
169
|
-
requirements:
|
170
|
-
- -
|
171
|
-
- !ruby/object:Gem::Version
|
172
|
-
|
173
|
-
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
segments:
|
187
|
+
- 0
|
188
|
+
version: "0"
|
189
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
190
|
none: false
|
175
|
-
requirements:
|
176
|
-
- -
|
177
|
-
- !ruby/object:Gem::Version
|
178
|
-
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
segments:
|
195
|
+
- 0
|
196
|
+
version: "0"
|
179
197
|
requirements: []
|
198
|
+
|
180
199
|
rubyforge_project: uomi
|
181
|
-
rubygems_version: 1.
|
200
|
+
rubygems_version: 1.3.7.1
|
182
201
|
signing_key:
|
183
202
|
specification_version: 3
|
184
203
|
summary: An uomi gem.
|
185
|
-
test_files:
|
204
|
+
test_files:
|
186
205
|
- spec/README
|
187
206
|
- spec/internal/config/database.yml.sample
|
188
207
|
- spec/internal/config/routes.rb
|