has_accounts 0.8.3 → 0.9.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.
- data/app/models/booking.rb +7 -1
- data/lib/has_accounts/version.rb +3 -0
- metadata +17 -22
- data/MIT-LICENSE +0 -20
- data/Rakefile +0 -26
- data/app/models/account.rb~ +0 -107
- data/app/models/booking.rb~ +0 -186
- data/lib/generators/has_accounts/templates/migration.rb~ +0 -59
- data/lib/generators/migration_generator.rb~ +0 -27
data/app/models/booking.rb
CHANGED
@@ -33,7 +33,13 @@ class Booking < ActiveRecord::Base
|
|
33
33
|
default_scope order('value_date, id')
|
34
34
|
|
35
35
|
scope :by_value_date, lambda {|value_date| where("date(value_date) = ?", value_date) }
|
36
|
-
scope :by_value_period, lambda {|from, to|
|
36
|
+
scope :by_value_period, lambda {|from, to|
|
37
|
+
if from.present?
|
38
|
+
where("date(value_date) BETWEEN :from AND :to", :from => from, :to => to)
|
39
|
+
else
|
40
|
+
where("date(value_date) <= :to", :to => to)
|
41
|
+
end
|
42
|
+
}
|
37
43
|
|
38
44
|
scope :by_account, lambda {|account_id|
|
39
45
|
{ :conditions => ["debit_account_id = :account_id OR credit_account_id = :account_id", {:account_id => account_id}] }
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has_accounts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 59
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Simon H\xC3\xBCrlimann (CyT)"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-27 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -26,31 +26,26 @@ executables: []
|
|
26
26
|
|
27
27
|
extensions: []
|
28
28
|
|
29
|
-
extra_rdoc_files:
|
30
|
-
|
29
|
+
extra_rdoc_files:
|
30
|
+
- README.md
|
31
31
|
files:
|
32
|
+
- app/models/account.rb
|
32
33
|
- app/models/account_scope_extension.rb
|
33
|
-
- app/models/
|
34
|
+
- app/models/account_type.rb
|
34
35
|
- app/models/bank.rb
|
35
|
-
- app/models/account.rb
|
36
36
|
- app/models/bank_account.rb
|
37
|
-
- app/models/account_type.rb
|
38
37
|
- app/models/booking.rb
|
39
|
-
-
|
40
|
-
- lib/has_accounts/
|
38
|
+
- lib/generators/has_accounts/migration_generator.rb
|
39
|
+
- lib/generators/has_accounts/templates/migration.rb
|
40
|
+
- lib/has_accounts.rb
|
41
41
|
- lib/has_accounts/class_methods.rb
|
42
42
|
- lib/has_accounts/core_ext/rounding.rb
|
43
43
|
- lib/has_accounts/model.rb
|
44
|
-
- lib/has_accounts.rb
|
45
|
-
- lib/
|
46
|
-
- lib/generators/has_accounts/templates/migration.rb~
|
47
|
-
- lib/generators/has_accounts/templates/migration.rb
|
48
|
-
- lib/generators/migration_generator.rb~
|
49
|
-
- MIT-LICENSE
|
50
|
-
- Rakefile
|
44
|
+
- lib/has_accounts/railtie.rb
|
45
|
+
- lib/has_accounts/version.rb
|
51
46
|
- README.md
|
52
47
|
has_rdoc: true
|
53
|
-
homepage:
|
48
|
+
homepage: https://github.com/huerlisi/has_accounts
|
54
49
|
licenses: []
|
55
50
|
|
56
51
|
post_install_message:
|
@@ -79,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
74
|
requirements: []
|
80
75
|
|
81
76
|
rubyforge_project:
|
82
|
-
rubygems_version: 1.
|
77
|
+
rubygems_version: 1.3.7
|
83
78
|
signing_key:
|
84
79
|
specification_version: 3
|
85
80
|
summary: HasAccounts provides models for financial accounting.
|
data/MIT-LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2008 [name of plugin creator]
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
require 'rubygems'
|
3
|
-
begin
|
4
|
-
require 'bundler/setup'
|
5
|
-
rescue LoadError
|
6
|
-
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
-
end
|
8
|
-
|
9
|
-
require 'rake'
|
10
|
-
require 'rdoc/task'
|
11
|
-
|
12
|
-
require 'rspec/core'
|
13
|
-
require 'rspec/core/rake_task'
|
14
|
-
|
15
|
-
RSpec::Core::RakeTask.new(:spec)
|
16
|
-
|
17
|
-
task :default => :spec
|
18
|
-
|
19
|
-
desc 'Generate documentation for the has_accounts plugin.'
|
20
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
21
|
-
rdoc.rdoc_dir = 'rdoc'
|
22
|
-
rdoc.title = 'Accounting'
|
23
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
24
|
-
rdoc.rdoc_files.include('README')
|
25
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
26
|
-
end
|
data/app/models/account.rb~
DELETED
@@ -1,107 +0,0 @@
|
|
1
|
-
class Account < ActiveRecord::Base
|
2
|
-
# Scopes
|
3
|
-
default_scope :order => 'code'
|
4
|
-
|
5
|
-
# Dummy scope to make scoped_by happy
|
6
|
-
scope :by_value_period, scoped
|
7
|
-
|
8
|
-
# Validation
|
9
|
-
validates_presence_of :code, :title
|
10
|
-
|
11
|
-
# String
|
12
|
-
def to_s(format = :default)
|
13
|
-
"%s (%s)" % [title, code]
|
14
|
-
end
|
15
|
-
|
16
|
-
# Account Type
|
17
|
-
# ============
|
18
|
-
belongs_to :account_type
|
19
|
-
validates_presence_of :account_type
|
20
|
-
|
21
|
-
def is_asset_account?
|
22
|
-
Account.by_type(['current_assets', 'capital_assets', 'costs']).exists?(self)
|
23
|
-
end
|
24
|
-
|
25
|
-
def is_liability_account?
|
26
|
-
!is_asset_account?
|
27
|
-
end
|
28
|
-
|
29
|
-
scope :by_type, lambda {|value| includes(:account_type).where('account_types.name' => value)} do
|
30
|
-
include AccountScopeExtension
|
31
|
-
end
|
32
|
-
|
33
|
-
# Holder
|
34
|
-
# ======
|
35
|
-
belongs_to :holder, :polymorphic => true
|
36
|
-
|
37
|
-
# Bookings
|
38
|
-
# ========
|
39
|
-
has_many :credit_bookings, :class_name => "Booking", :foreign_key => "credit_account_id"
|
40
|
-
has_many :debit_bookings, :class_name => "Booking", :foreign_key => "debit_account_id"
|
41
|
-
|
42
|
-
def bookings
|
43
|
-
Booking.by_account(id)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Helpers
|
47
|
-
# =======
|
48
|
-
def self.overview(value_range = Date.today, format = :default)
|
49
|
-
Account.all.map{|a| a.to_s(value_range, format)}
|
50
|
-
end
|
51
|
-
|
52
|
-
# Calculations
|
53
|
-
def turnover(selector = Date.today, inclusive = true)
|
54
|
-
if selector.is_a? Range or selector.is_a? Array
|
55
|
-
if selector.first.is_a? Booking
|
56
|
-
equality = "=" if inclusive
|
57
|
-
if selector.first.value_date == selector.last.value_date
|
58
|
-
condition = ["date(value_date) = :value_date AND id >#{equality} :first_id AND id <#{equality} :last_id", {
|
59
|
-
:value_date => selector.first.value_date,
|
60
|
-
:first_id => selector.first.id,
|
61
|
-
:last_id => selector.last.id
|
62
|
-
}]
|
63
|
-
else
|
64
|
-
condition = ["(value_date > :first_value_date AND value_date < :latest_value_date) OR (date(value_date) = :first_value_date AND id >#{equality} :first_id) OR (date(value_date) = :latest_value_date AND id <#{equality} :last_id)", {
|
65
|
-
:first_value_date => selector.first.value_date,
|
66
|
-
:latest_value_date => selector.last.value_date,
|
67
|
-
:first_id => selector.first.id,
|
68
|
-
:last_id => selector.last.id
|
69
|
-
}]
|
70
|
-
end
|
71
|
-
elsif
|
72
|
-
if selector.first == selector.last
|
73
|
-
condition = ["date(value_date) = :value_date", {
|
74
|
-
:value_date => selector.first
|
75
|
-
}]
|
76
|
-
else
|
77
|
-
condition = ["date(value_date) BETWEEN :first_value_date AND :latest_value_date", {
|
78
|
-
:first_value_date => selector.first,
|
79
|
-
:latest_value_date => selector.last
|
80
|
-
}]
|
81
|
-
end
|
82
|
-
end
|
83
|
-
else
|
84
|
-
if selector.is_a? Booking
|
85
|
-
equality = "=" if inclusive
|
86
|
-
# date(value_date) is needed on sqlite!
|
87
|
-
condition = ["(value_date < :value_date) OR (date(value_date) = :value_date AND id <#{equality} :id)", {:value_date => selector.value_date, :id => selector.id}]
|
88
|
-
else
|
89
|
-
equality = "=" if inclusive
|
90
|
-
condition = ["date(value_date) <#{equality} ?", selector]
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
credit_amount = credit_bookings.where(condition).sum(:amount)
|
95
|
-
debit_amount = debit_bookings.where(condition).sum(:amount)
|
96
|
-
|
97
|
-
[credit_amount || 0.0, debit_amount || 0.0]
|
98
|
-
end
|
99
|
-
|
100
|
-
def saldo(selector = Date.today, inclusive = true)
|
101
|
-
credit_amount, debit_amount = turnover(selector, inclusive)
|
102
|
-
|
103
|
-
amount = credit_amount - debit_amount
|
104
|
-
|
105
|
-
return is_asset_account? ? amount : -amount
|
106
|
-
end
|
107
|
-
end
|
data/app/models/booking.rb~
DELETED
@@ -1,186 +0,0 @@
|
|
1
|
-
class Booking < ActiveRecord::Base
|
2
|
-
# Validation
|
3
|
-
validates_presence_of :debit_account, :credit_account, :title, :amount, :value_date
|
4
|
-
validates_time :value_date
|
5
|
-
|
6
|
-
# Account
|
7
|
-
belongs_to :debit_account, :foreign_key => 'debit_account_id', :class_name => "Account"
|
8
|
-
belongs_to :credit_account, :foreign_key => 'credit_account_id', :class_name => "Account"
|
9
|
-
|
10
|
-
def direct_account
|
11
|
-
return nil unless reference
|
12
|
-
|
13
|
-
return reference.direct_account if reference.respond_to? :direct_account
|
14
|
-
end
|
15
|
-
|
16
|
-
def contra_account(account = nil)
|
17
|
-
# Derive from direct_account if available
|
18
|
-
account ||= direct_account
|
19
|
-
|
20
|
-
return unless account
|
21
|
-
|
22
|
-
if debit_account == account
|
23
|
-
return credit_account
|
24
|
-
elsif credit_account == account
|
25
|
-
return debit_account
|
26
|
-
else
|
27
|
-
return nil
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Scoping
|
32
|
-
default_scope order('value_date, id')
|
33
|
-
|
34
|
-
scope :by_value_date, lambda {|value_date| where("date(value_date) = ?", value_date) }
|
35
|
-
scope :by_value_period, lambda {|from, to| where("date(value_date) BETWEEN :from AND :to", :from => from, :to => to) }
|
36
|
-
|
37
|
-
scope :by_account, lambda {|account_id|
|
38
|
-
{ :conditions => ["debit_account_id = :account_id OR credit_account_id = :account_id", {:account_id => account_id}] }
|
39
|
-
} do
|
40
|
-
# Returns array of all booking titles.
|
41
|
-
def titles
|
42
|
-
find(:all, :group => :title).map{|booking| booking.title}
|
43
|
-
end
|
44
|
-
|
45
|
-
# Statistics per booking title.
|
46
|
-
#
|
47
|
-
# The statistics are an array of hashes with keys title, count, sum, average.
|
48
|
-
def statistics
|
49
|
-
find(:all, :select => "title, count(*) AS count, sum(amount) AS sum, avg(amount) AS avg", :group => :title).map{|stat| stat.attributes}
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
scope :by_text, lambda {|value|
|
54
|
-
text = '%' + value + '%'
|
55
|
-
|
56
|
-
amount = value.delete("'").to_f
|
57
|
-
if amount == 0.0
|
58
|
-
amount = nil unless value.match(/^[0.]*$/)
|
59
|
-
end
|
60
|
-
|
61
|
-
date = nil
|
62
|
-
begin
|
63
|
-
date = Date.parse(value)
|
64
|
-
rescue ArgumentError
|
65
|
-
end
|
66
|
-
|
67
|
-
where("title LIKE :text OR comments LIKE :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
|
68
|
-
}
|
69
|
-
|
70
|
-
# Returns array of all years we have bookings for
|
71
|
-
def self.fiscal_years
|
72
|
-
with_exclusive_scope do
|
73
|
-
select("DISTINCT year(value_date) AS year").all.map{|booking| booking.year}
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Standard methods
|
78
|
-
def to_s(format = :default)
|
79
|
-
case format
|
80
|
-
when :short
|
81
|
-
"%s: %s / %s CHF %s" % [
|
82
|
-
value_date ? value_date : '?',
|
83
|
-
credit_account ? credit_account.code : '?',
|
84
|
-
debit_account ? debit_account.code : '?',
|
85
|
-
amount ? "%0.2f" % amount : '?',
|
86
|
-
]
|
87
|
-
else
|
88
|
-
"%s: %s an %s CHF %s, %s (%s)" % [
|
89
|
-
value_date ? value_date : '?',
|
90
|
-
credit_account ? "#{credit_account.title} (#{credit_account.code})" : '?',
|
91
|
-
debit_account ? "#{debit_account.title} (#{debit_account.code})" : '?',
|
92
|
-
amount ? "%0.2f" % amount : '?',
|
93
|
-
title.present? ? title : '?',
|
94
|
-
comments.present? ? comments : '?'
|
95
|
-
]
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Helpers
|
100
|
-
def accounted_amount(account)
|
101
|
-
if credit_account == account
|
102
|
-
balance = -(amount)
|
103
|
-
elsif debit_account == account
|
104
|
-
balance = amount
|
105
|
-
else
|
106
|
-
return BigDecimal.new('0')
|
107
|
-
end
|
108
|
-
|
109
|
-
if account.is_asset_account?
|
110
|
-
return -(balance)
|
111
|
-
else
|
112
|
-
return balance
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def amount_as_string
|
117
|
-
'%0.2f' % amount
|
118
|
-
end
|
119
|
-
|
120
|
-
def amount_as_string=(value)
|
121
|
-
self.amount = value
|
122
|
-
end
|
123
|
-
|
124
|
-
def rounded_amount
|
125
|
-
if amount.nil?
|
126
|
-
return 0
|
127
|
-
else
|
128
|
-
return (amount * 20).round / 20.0
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# Templates
|
133
|
-
def booking_template_id
|
134
|
-
nil
|
135
|
-
end
|
136
|
-
|
137
|
-
def booking_template_id=(value)
|
138
|
-
end
|
139
|
-
|
140
|
-
# Helpers
|
141
|
-
def split(amount, params = {})
|
142
|
-
# Clone
|
143
|
-
new_booking = self.clone
|
144
|
-
|
145
|
-
# Set amount
|
146
|
-
new_booking[:amount] = amount
|
147
|
-
self.amount -= amount
|
148
|
-
|
149
|
-
# Update attributes
|
150
|
-
params.each{|key, value|
|
151
|
-
new_booking[key] = value
|
152
|
-
}
|
153
|
-
|
154
|
-
[self, new_booking]
|
155
|
-
end
|
156
|
-
|
157
|
-
# Reference
|
158
|
-
belongs_to :reference, :polymorphic => true
|
159
|
-
after_save :notify_references
|
160
|
-
|
161
|
-
# Safety net for form assignments
|
162
|
-
def reference_type=(value)
|
163
|
-
write_attribute(:reference_type, value) unless value.blank?
|
164
|
-
end
|
165
|
-
|
166
|
-
scope :by_reference, lambda {|value|
|
167
|
-
where(:reference_id => value.id, :reference_type => value.class.base_class)
|
168
|
-
} do
|
169
|
-
# TODO duplicated in Invoice
|
170
|
-
def direct_balance(direct_account)
|
171
|
-
balance = 0.0
|
172
|
-
|
173
|
-
for booking in all
|
174
|
-
balance += booking.accounted_amount(direct_account)
|
175
|
-
end
|
176
|
-
|
177
|
-
balance
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
private
|
182
|
-
def notify_references
|
183
|
-
return unless reference and reference.respond_to?(:booking_saved)
|
184
|
-
reference.booking_saved(self)
|
185
|
-
end
|
186
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
class SetupHasAccountsEngine < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table "account_types", :force => true do |t|
|
4
|
-
t.string "name", :limit => 100
|
5
|
-
t.string "title", :limit => 100
|
6
|
-
t.datetime "created_at"
|
7
|
-
t.datetime "updated_at"
|
8
|
-
end
|
9
|
-
|
10
|
-
create_table "accounts", :force => true do |t|
|
11
|
-
t.string "title", :limit => 100
|
12
|
-
t.integer "parent_id"
|
13
|
-
t.integer "account_type_id"
|
14
|
-
t.integer "number"
|
15
|
-
t.string "code"
|
16
|
-
t.integer "type"
|
17
|
-
t.integer "holder_id"
|
18
|
-
t.string "holder_type"
|
19
|
-
t.integer "bank_id"
|
20
|
-
t.integer "esr_id"
|
21
|
-
t.integer "pc_id"
|
22
|
-
t.datetime "created_at"
|
23
|
-
t.datetime "updated_at"
|
24
|
-
end
|
25
|
-
|
26
|
-
add_index "accounts", ["bank_id"], :name => "index_accounts_on_bank_id"
|
27
|
-
add_index "accounts", ["code"], :name => "index_accounts_on_code"
|
28
|
-
add_index "accounts", ["holder_id", "holder_type"], :name => "index_accounts_on_holder_id_and_holder_type"
|
29
|
-
add_index "accounts", ["type"], :name => "index_accounts_on_type"
|
30
|
-
|
31
|
-
create_table "banks", :force => true do |t|
|
32
|
-
t.integer "vcard_id"
|
33
|
-
t.datetime "created_at"
|
34
|
-
t.datetime "updated_at"
|
35
|
-
end
|
36
|
-
|
37
|
-
create_table "bookings", :force => true do |t|
|
38
|
-
t.string "title", :limit => 100
|
39
|
-
t.decimal "amount"
|
40
|
-
t.integer "credit_account_id"
|
41
|
-
t.integer "debit_account_id"
|
42
|
-
t.date "value_date"
|
43
|
-
t.text "comments", :limit => 1000, :default => ""
|
44
|
-
t.string "scan"
|
45
|
-
t.string "debit_currency", :default => "CHF"
|
46
|
-
t.string "credit_currency", :default => "CHF"
|
47
|
-
t.float "exchange_rate", :default => 1.0
|
48
|
-
t.datetime "created_at"
|
49
|
-
t.datetime "updated_at"
|
50
|
-
t.integer "reference_id"
|
51
|
-
t.string "reference_type"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.down
|
56
|
-
drop_table :account_types, :accounts, :banks, :bookings
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'rails/generators/base'
|
2
|
-
require 'rails/generators/migration'
|
3
|
-
|
4
|
-
module HasVcards
|
5
|
-
class MigrationGenerator < Rails::Generators::Base
|
6
|
-
include Rails::Generators::Migration
|
7
|
-
|
8
|
-
def self.source_root
|
9
|
-
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
10
|
-
end
|
11
|
-
|
12
|
-
# Implement the required interface for Rails::Generators::Migration.
|
13
|
-
# taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
|
14
|
-
def self.next_migration_number(dirname)
|
15
|
-
if ActiveRecord::Base.timestamped_migrations
|
16
|
-
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
17
|
-
else
|
18
|
-
"%.3d" % (current_migration_number(dirname) + 1)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def create_migration_file
|
23
|
-
migration_template 'migration.rb', 'db/migrate/create_has_vcards.rb'
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|