ledger_sync 1.0.10 → 1.1.1
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +36 -20
- data/README.md +105 -66
- data/ledger_sync.gemspec +1 -0
- data/lib/ledger_sync.rb +23 -4
- data/lib/ledger_sync/adaptors/operation.rb +28 -28
- data/lib/ledger_sync/adaptors/quickbooks_online/account/mapping.rb +325 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/create.rb +54 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/find.rb +38 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/update.rb +61 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/account/searcher.rb +67 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +18 -16
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/create.rb +65 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/find.rb +37 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/update.rb +69 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/searcher.rb +28 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/create.rb +6 -6
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/find.rb +1 -3
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/update.rb +6 -9
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/searcher.rb +2 -38
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/create.rb +61 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/find.rb +36 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/update.rb +65 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/searcher.rb +28 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/mapping.rb +15 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/create.rb +68 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/find.rb +39 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/update.rb +72 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/searcher.rb +28 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/mapping.rb +14 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/create.rb +56 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/find.rb +34 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/update.rb +60 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/searcher.rb +28 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation.rb +30 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/create.rb +8 -22
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/find.rb +0 -2
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/update.rb +6 -22
- data/lib/ledger_sync/adaptors/quickbooks_online/searcher.rb +45 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/create.rb +52 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/find.rb +36 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/update.rb +57 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/create.rb +46 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/find.rb +36 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/update.rb +51 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/searcher.rb +64 -0
- data/lib/ledger_sync/adaptors/searcher.rb +3 -1
- data/lib/ledger_sync/adaptors/test/account/operations/create.rb +53 -0
- data/lib/ledger_sync/adaptors/test/account/operations/find.rb +38 -0
- data/lib/ledger_sync/adaptors/test/account/operations/invalid.rb +25 -0
- data/lib/ledger_sync/adaptors/test/account/operations/update.rb +50 -0
- data/lib/ledger_sync/adaptors/test/account/operations/valid.rb +31 -0
- data/lib/ledger_sync/adaptors/test/account/searcher.rb +40 -0
- data/lib/ledger_sync/adaptors/test/adaptor.rb +4 -4
- data/lib/ledger_sync/adaptors/test/customer/operations/create.rb +4 -6
- data/lib/ledger_sync/adaptors/test/customer/operations/find.rb +0 -2
- data/lib/ledger_sync/adaptors/test/customer/operations/update.rb +4 -6
- data/lib/ledger_sync/adaptors/test/customer/searcher.rb +2 -2
- data/lib/ledger_sync/adaptors/test/expense/operations/create.rb +54 -0
- data/lib/ledger_sync/adaptors/test/expense/operations/find.rb +39 -0
- data/lib/ledger_sync/adaptors/test/expense/operations/update.rb +57 -0
- data/lib/ledger_sync/adaptors/test/payment/operations/create.rb +4 -20
- data/lib/ledger_sync/adaptors/test/payment/operations/find.rb +0 -2
- data/lib/ledger_sync/adaptors/test/payment/operations/update.rb +4 -20
- data/lib/ledger_sync/adaptors/test/transfer/operations/create.rb +45 -0
- data/lib/ledger_sync/adaptors/test/transfer/operations/find.rb +36 -0
- data/lib/ledger_sync/adaptors/test/transfer/operations/update.rb +48 -0
- data/lib/ledger_sync/adaptors/test/vendor/operations/create.rb +47 -0
- data/lib/ledger_sync/adaptors/test/vendor/operations/find.rb +34 -0
- data/lib/ledger_sync/adaptors/test/vendor/operations/invalid.rb +21 -0
- data/lib/ledger_sync/adaptors/test/vendor/operations/update.rb +44 -0
- data/lib/ledger_sync/adaptors/test/vendor/operations/valid.rb +27 -0
- data/lib/ledger_sync/adaptors/test/vendor/searcher.rb +41 -0
- data/lib/ledger_sync/error/resource_errors.rb +24 -0
- data/lib/ledger_sync/resource.rb +24 -64
- data/lib/ledger_sync/resource_attribute.rb +50 -0
- data/lib/ledger_sync/resource_attribute/dirty_mixin.rb +49 -0
- data/lib/ledger_sync/resource_attribute/mixin.rb +90 -0
- data/lib/ledger_sync/resource_attribute/reference.rb +9 -0
- data/lib/ledger_sync/resource_attribute/reference/many.rb +34 -0
- data/lib/ledger_sync/resource_attribute/reference/one.rb +33 -0
- data/lib/ledger_sync/resource_attribute_set.rb +58 -0
- data/lib/ledger_sync/resources/account.rb +14 -0
- data/lib/ledger_sync/resources/bill.rb +17 -0
- data/lib/ledger_sync/resources/bill_line_item.rb +11 -0
- data/lib/ledger_sync/resources/customer.rb +5 -4
- data/lib/ledger_sync/resources/deposit.rb +16 -0
- data/lib/ledger_sync/resources/deposit_line_item.rb +11 -0
- data/lib/ledger_sync/resources/expense.rb +19 -0
- data/lib/ledger_sync/resources/expense_line_item.rb +11 -0
- data/lib/ledger_sync/resources/journal_entry.rb +13 -0
- data/lib/ledger_sync/resources/journal_entry_line_item.rb +12 -0
- data/lib/ledger_sync/resources/payment.rb +5 -3
- data/lib/ledger_sync/resources/transfer.rb +15 -0
- data/lib/ledger_sync/resources/vendor.rb +12 -0
- data/lib/ledger_sync/result.rb +0 -24
- data/lib/ledger_sync/type/boolean.rb +17 -0
- data/lib/ledger_sync/type/date.rb +17 -0
- data/lib/ledger_sync/type/float.rb +17 -0
- data/lib/ledger_sync/type/integer.rb +17 -0
- data/lib/ledger_sync/type/reference_many.rb +27 -0
- data/lib/ledger_sync/type/reference_one.rb +26 -0
- data/lib/ledger_sync/type/string.rb +17 -0
- data/lib/ledger_sync/type/value.rb +12 -0
- data/lib/ledger_sync/type/value_mixin.rb +19 -0
- data/lib/ledger_sync/util/hash_helpers.rb +16 -1
- data/lib/ledger_sync/util/resources_builder.rb +36 -9
- data/lib/ledger_sync/version.rb +1 -1
- metadata +92 -7
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/upsert.rb +0 -42
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/upsert.rb +0 -53
- data/lib/ledger_sync/adaptors/test/customer/operations/upsert.rb +0 -42
- data/lib/ledger_sync/adaptors/test/payment/operations/upsert.rb +0 -53
- data/lib/ledger_sync/sync.rb +0 -108
- data/lib/ledger_sync/util/coordinator.rb +0 -72
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ledger_sync/type/value'
|
4
|
+
|
5
|
+
Gem.find_files('ledger_sync/type/**/*.rb').each do |path|
|
6
|
+
require path
|
7
|
+
end
|
8
|
+
|
9
|
+
Gem.find_files('ledger_sync/resource_attribute/**/*.rb').each do |path|
|
10
|
+
require path
|
11
|
+
end
|
12
|
+
|
13
|
+
module LedgerSync
|
14
|
+
class ResourceAttribute
|
15
|
+
include Fingerprintable::Mixin
|
16
|
+
include SimplySerializable::Mixin
|
17
|
+
|
18
|
+
attr_accessor :value
|
19
|
+
attr_reader :name,
|
20
|
+
:reference,
|
21
|
+
:type
|
22
|
+
|
23
|
+
def initialize(name:, type:, value: nil)
|
24
|
+
@name = name.to_sym
|
25
|
+
|
26
|
+
type = type.new if type.respond_to?(:new) && !type.is_a?(Type::Value)
|
27
|
+
|
28
|
+
raise "Invalid Type: #{type}" unless type.is_a?(ActiveModel::Type::Value)
|
29
|
+
|
30
|
+
@type = type
|
31
|
+
|
32
|
+
@value = value
|
33
|
+
end
|
34
|
+
|
35
|
+
def cast(value)
|
36
|
+
type.cast(value)
|
37
|
+
end
|
38
|
+
|
39
|
+
# This is for ActiveModel::Dirty, since we define @attributes
|
40
|
+
# def forgetting_assignment; end
|
41
|
+
|
42
|
+
def reference?
|
43
|
+
is_a?(Reference)
|
44
|
+
end
|
45
|
+
|
46
|
+
def valid_with?(value:)
|
47
|
+
type.valid_without_casting?(value: value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Helper methods for adding dirty tracked attributes
|
4
|
+
module LedgerSync
|
5
|
+
class ResourceAttribute
|
6
|
+
module DirtyMixin
|
7
|
+
def self.included(base)
|
8
|
+
base.include(ActiveModel::Dirty)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def dirty_attribute(*names)
|
14
|
+
names.each do |name|
|
15
|
+
class_eval do
|
16
|
+
attr_reader name
|
17
|
+
define_attribute_methods name # From ActiveModel
|
18
|
+
dirty_attributes[name] = {
|
19
|
+
name: name
|
20
|
+
}
|
21
|
+
|
22
|
+
define_method("#{name}=") do |val|
|
23
|
+
send("#{name}_will_change!") unless val == instance_variable_get("@#{name}")
|
24
|
+
instance_variable_set("@#{name}", val)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def dirty_attributes
|
31
|
+
@dirty_attributes ||= {}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Normally you would just call `changes_applied`, but because we
|
36
|
+
# define an `@attributes` instance variable, the `ActiveModel::Dirty`
|
37
|
+
# mixin assumes it is a list of attributes in their format (spoiler: it
|
38
|
+
# isn't). So this is copying the code from `changes_applied` and setting
|
39
|
+
# `@mutations_from_database` to the value it would receive if
|
40
|
+
# `@attributes` did not exist.
|
41
|
+
def save
|
42
|
+
# changes_applied # Code reproduced below.
|
43
|
+
@mutations_before_last_save = mutations_from_database
|
44
|
+
# forget_attribute_assignments # skipped as our attributes do not implement this method
|
45
|
+
@mutations_from_database = ActiveModel::ForcedMutationTracker.new(self) # Manually set to expected value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../resource_attribute_set'
|
4
|
+
require_relative 'dirty_mixin'
|
5
|
+
|
6
|
+
# Mixin for attribute functionality
|
7
|
+
module LedgerSync
|
8
|
+
class ResourceAttribute
|
9
|
+
module Mixin
|
10
|
+
def self.included(base)
|
11
|
+
base.include(DirtyMixin)
|
12
|
+
base.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def _define_attribute_methods(name)
|
17
|
+
class_eval do
|
18
|
+
define_attribute_methods name
|
19
|
+
|
20
|
+
define_method name do
|
21
|
+
resource_attributes[name].value
|
22
|
+
end
|
23
|
+
|
24
|
+
define_method "#{name}=" do |val|
|
25
|
+
public_send("#{name}_will_change!") unless val == resource_attributes[name] # For Dirty
|
26
|
+
|
27
|
+
attribute = resource_attributes[name]
|
28
|
+
|
29
|
+
unless attribute.valid_with?(value: val)
|
30
|
+
raise ResourceError::AttributeTypeError.new(
|
31
|
+
attribute: attribute,
|
32
|
+
resource: self,
|
33
|
+
value: val
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
attribute.value = val
|
38
|
+
end
|
39
|
+
|
40
|
+
serialize attributes: [name]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def attribute(name, type:)
|
45
|
+
resource_attribute = ResourceAttribute.new(name: name, type: type)
|
46
|
+
|
47
|
+
_define_attribute_methods(name)
|
48
|
+
|
49
|
+
resource_attributes.add(resource_attribute)
|
50
|
+
|
51
|
+
resource_attribute
|
52
|
+
end
|
53
|
+
|
54
|
+
def resource_attributes
|
55
|
+
@resource_attributes ||= ResourceAttributeSet.new(resource: self)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(**data)
|
60
|
+
# Initialize empty values
|
61
|
+
resource_attributes.keys.each { |e| instance_variable_set("@#{e}", nil) }
|
62
|
+
|
63
|
+
assign_attributes(data)
|
64
|
+
|
65
|
+
super()
|
66
|
+
end
|
67
|
+
|
68
|
+
def assign_attribute(name, value)
|
69
|
+
raise "#{name} is not an attribute of #{self.class.name}" unless resource_attributes.key?(name)
|
70
|
+
|
71
|
+
public_send("#{name}=", value)
|
72
|
+
end
|
73
|
+
|
74
|
+
def assign_attributes(attribute_hash)
|
75
|
+
attribute_hash.each do |name, value|
|
76
|
+
assign_attribute(name, value)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Store attribute instance values separately
|
81
|
+
def resource_attributes
|
82
|
+
@resource_attributes ||= Marshal.load(Marshal.dump(self.class.resource_attributes))
|
83
|
+
end
|
84
|
+
|
85
|
+
def serialize_attributes
|
86
|
+
Hash[resource_attributes.map { |k, v| [k, v.value] }]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../reference'
|
4
|
+
|
5
|
+
# Reference attribute type for has_one
|
6
|
+
module LedgerSync
|
7
|
+
class ResourceAttribute
|
8
|
+
class Reference
|
9
|
+
class Many < Reference
|
10
|
+
module Mixin
|
11
|
+
def self.included(base)
|
12
|
+
base.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def references_many(name, to:)
|
17
|
+
resource_attribute = ResourceAttribute::Reference::Many.new(name: name, to: to)
|
18
|
+
resource_attributes.add resource_attribute
|
19
|
+
_define_attribute_methods(name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(name:, to:)
|
25
|
+
super(
|
26
|
+
name: name,
|
27
|
+
type: Type::ReferenceMany.new(resource_class: to),
|
28
|
+
value: []
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../reference'
|
4
|
+
|
5
|
+
# Reference attribute type for has_one
|
6
|
+
module LedgerSync
|
7
|
+
class ResourceAttribute
|
8
|
+
class Reference
|
9
|
+
class One < Reference
|
10
|
+
module Mixin
|
11
|
+
def self.included(base)
|
12
|
+
base.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def references_one(name, to:)
|
17
|
+
resource_attribute = ResourceAttribute::Reference::One.new(name: name, to: to)
|
18
|
+
resource_attributes.add resource_attribute
|
19
|
+
_define_attribute_methods(name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(name:, to:)
|
25
|
+
super(
|
26
|
+
name: name,
|
27
|
+
type: Type::ReferenceOne.new(resource_class: to)
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LedgerSync
|
4
|
+
class ResourceAttributeSet
|
5
|
+
attr_reader :attributes,
|
6
|
+
:references,
|
7
|
+
:references_one,
|
8
|
+
:references_many,
|
9
|
+
:resource
|
10
|
+
|
11
|
+
delegate :[],
|
12
|
+
:each,
|
13
|
+
:include?,
|
14
|
+
:key?,
|
15
|
+
:keys,
|
16
|
+
:map,
|
17
|
+
to: :attributes
|
18
|
+
|
19
|
+
alias names keys
|
20
|
+
|
21
|
+
def initialize(resource:)
|
22
|
+
@attributes = {}
|
23
|
+
@references = []
|
24
|
+
@references_one = []
|
25
|
+
@references_many = []
|
26
|
+
|
27
|
+
@resource = resource
|
28
|
+
end
|
29
|
+
|
30
|
+
def add(attribute)
|
31
|
+
name = attribute.name
|
32
|
+
raise "Attribute #{name} already exists on #{resource.name}." if attributes.key?(name)
|
33
|
+
|
34
|
+
case attribute
|
35
|
+
when ResourceAttribute
|
36
|
+
nil
|
37
|
+
when ResourceAttribute::Reference::One
|
38
|
+
@references << attribute
|
39
|
+
@references_one << attribute
|
40
|
+
when ResourceAttribute::Reference::Many
|
41
|
+
@references << attribute
|
42
|
+
@references_many << attribute
|
43
|
+
else
|
44
|
+
raise 'Unknown attribute class'
|
45
|
+
end
|
46
|
+
|
47
|
+
@attributes[attribute.name] = attribute
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_a
|
51
|
+
attributes.values
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_h
|
55
|
+
Hash[attributes.map { |k, v| [k, v.value] }]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LedgerSync
|
4
|
+
class Account < LedgerSync::Resource
|
5
|
+
attribute :name, type: Type::String
|
6
|
+
attribute :classification, type: Type::String
|
7
|
+
attribute :account_type, type: Type::String
|
8
|
+
attribute :account_sub_type, type: Type::String
|
9
|
+
attribute :number, type: Type::Integer
|
10
|
+
attribute :currency, type: Type::String
|
11
|
+
attribute :description, type: Type::String
|
12
|
+
attribute :active, type: Type::Boolean
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module LedgerSync
|
2
|
+
class Bill < LedgerSync::Resource
|
3
|
+
attribute :currency, type: Type::String
|
4
|
+
attribute :memo, type: Type::String
|
5
|
+
attribute :transaction_date, type: Type::Date
|
6
|
+
attribute :due_date, type: Type::Date
|
7
|
+
|
8
|
+
references_one :vendor, to: Vendor
|
9
|
+
references_one :account, to: Account
|
10
|
+
|
11
|
+
references_many :line_items, to: BillLineItem
|
12
|
+
|
13
|
+
def name
|
14
|
+
"Bill: #{transaction_date.to_s}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module LedgerSync
|
2
4
|
class Customer < LedgerSync::Resource
|
3
|
-
attribute :email
|
4
|
-
attribute :name
|
5
|
-
attribute :phone_number
|
6
|
-
# attribute :active
|
5
|
+
attribute :email, type: Type::String
|
6
|
+
attribute :name, type: Type::String
|
7
|
+
attribute :phone_number, type: Type::String
|
7
8
|
end
|
8
9
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module LedgerSync
|
2
|
+
class Deposit < LedgerSync::Resource
|
3
|
+
attribute :currency, type: Type::String
|
4
|
+
attribute :memo, type: Type::String
|
5
|
+
attribute :transaction_date, type: Type::Date
|
6
|
+
attribute :exchange_rate, type: Type::Float
|
7
|
+
|
8
|
+
references_one :account, to: Account
|
9
|
+
|
10
|
+
references_many :line_items, to: DepositLineItem
|
11
|
+
|
12
|
+
def name
|
13
|
+
"Deposit: #{currency}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module LedgerSync
|
2
|
+
class Expense < LedgerSync::Resource
|
3
|
+
attribute :currency, type: Type::String
|
4
|
+
attribute :amount, type: Type::Integer
|
5
|
+
attribute :memo, type: Type::String
|
6
|
+
attribute :payment_type, type: Type::String
|
7
|
+
attribute :transaction_date, type: Type::Date
|
8
|
+
attribute :exchange_rate, type: Type::Float
|
9
|
+
|
10
|
+
references_one :vendor, to: Vendor
|
11
|
+
references_one :account, to: Account
|
12
|
+
|
13
|
+
references_many :line_items, to: ExpenseLineItem
|
14
|
+
|
15
|
+
def name
|
16
|
+
"Purchase: #{amount} #{currency}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|