event_sourced_accounting 0.1.4 → 0.1.6
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/app/models/esa/context.rb +8 -1
- data/app/models/esa/traits/accountable.rb +11 -0
- data/lib/esa.rb +1 -1
- data/lib/esa/configuration.rb +89 -0
- data/lib/esa/context_providers/account_context_provider.rb +1 -1
- data/lib/esa/context_providers/accountable_context_provider.rb +1 -1
- data/lib/esa/context_providers/accountable_type_context_provider.rb +1 -1
- data/lib/esa/context_providers/date_context_provider.rb +1 -1
- data/lib/esa/subcontext_checker.rb +1 -1
- data/lib/esa/version.rb +1 -1
- metadata +3 -3
- data/lib/esa/config.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d898cf40cfd5525402b244a8ebde093e0e9948fa
|
4
|
+
data.tar.gz: 4a925d9356d3aeee2a08790ad1b2ea28838dfc9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e6c5f2d437c040f89af829811cc5b0f92b9da413c03a380479c03b6c9f2089d4ad7d7ea424833ea99a53be8f1eb112a8b6bbcd11bbd7ab3969a8f7951c4c740
|
7
|
+
data.tar.gz: 4d4c47371255499bcda065a9c78213a09a3ccb983388058057d4fa4db9fb60812a3e03a0686feac878b4024c527df1ea8308d95cb82a67b124b26e09a8be3d26
|
data/app/models/esa/context.rb
CHANGED
@@ -30,6 +30,9 @@ module ESA
|
|
30
30
|
scope :roots, lambda { where(parent_id: nil) }
|
31
31
|
scope :subs, lambda { where("esa_contexts.parent_id is not null") }
|
32
32
|
|
33
|
+
scope :fresh, lambda { where("`esa_contexts`.`freshness` > ?", ESA.configuration.context_freshness_threshold.ago) }
|
34
|
+
scope :stale, lambda { where("`esa_contexts`.`freshness` IS NULL OR `esa_contexts`.`freshness` <= ?", ESA.configuration.context_freshness_threshold.ago) }
|
35
|
+
|
33
36
|
def is_root?
|
34
37
|
self.parent_id.nil?
|
35
38
|
end
|
@@ -68,6 +71,10 @@ module ESA
|
|
68
71
|
end
|
69
72
|
end
|
70
73
|
|
74
|
+
def is_fresh?(time=Time.zone.now)
|
75
|
+
self.freshness.present? and (self.freshness + ESA.configuration.context_freshness_threshold) > time
|
76
|
+
end
|
77
|
+
|
71
78
|
def check_freshness(depth=0)
|
72
79
|
if self.is_update_needed?
|
73
80
|
self.update!
|
@@ -99,7 +106,7 @@ module ESA
|
|
99
106
|
def update!
|
100
107
|
self.freshness = Time.zone.now
|
101
108
|
|
102
|
-
|
109
|
+
ESA.configuration.context_checkers.each do |checker|
|
103
110
|
if checker.respond_to? :check
|
104
111
|
checker.check(self)
|
105
112
|
end
|
@@ -8,6 +8,8 @@ module ESA
|
|
8
8
|
has_many :esa_flags, :as => :accountable, :class_name => ESA::Flag.extension_name(self), :extend => ESA::Associations::FlagsExtension
|
9
9
|
has_many :esa_transactions, :as => :accountable, :class_name => ESA::Transaction.extension_name(self), :extend => ESA::Associations::TransactionsExtension
|
10
10
|
|
11
|
+
before_destroy :destroy_accountable
|
12
|
+
|
11
13
|
def esa_ruleset
|
12
14
|
ESA::Ruleset.extension_instance(self)
|
13
15
|
end
|
@@ -15,6 +17,15 @@ module ESA
|
|
15
17
|
def esa_chart
|
16
18
|
self.esa_ruleset.chart
|
17
19
|
end
|
20
|
+
|
21
|
+
def destroy_accountable
|
22
|
+
if self.esa_transactions.blank?
|
23
|
+
self.esa_flags.delete_all
|
24
|
+
self.esa_events.delete_all
|
25
|
+
else
|
26
|
+
false
|
27
|
+
end
|
28
|
+
end
|
18
29
|
end
|
19
30
|
end
|
20
31
|
end
|
data/lib/esa.rb
CHANGED
@@ -0,0 +1,89 @@
|
|
1
|
+
module ESA
|
2
|
+
class << self
|
3
|
+
attr_accessor :configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure
|
7
|
+
self.configuration ||= Configuration.new
|
8
|
+
yield(configuration)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Configuration
|
12
|
+
attr_accessor :base_classes
|
13
|
+
attr_accessor :extension_namespace
|
14
|
+
attr_accessor :processor
|
15
|
+
attr_accessor :context_checkers
|
16
|
+
attr_accessor :context_freshness_threshold
|
17
|
+
attr_accessor :context_providers
|
18
|
+
attr_accessor :context_tree
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@base_classes = [ESA::Ruleset, ESA::Event, ESA::Flag, ESA::Transaction].freeze
|
22
|
+
|
23
|
+
@extension_namespace = "Accounting"
|
24
|
+
|
25
|
+
@processor = ESA::BlockingProcessor
|
26
|
+
|
27
|
+
@context_checkers = Set.new
|
28
|
+
@context_checkers << ESA::BalanceChecker
|
29
|
+
@context_checkers << ESA::SubcontextChecker
|
30
|
+
|
31
|
+
@context_freshness_threshold = 15.minutes
|
32
|
+
|
33
|
+
@context_providers = {
|
34
|
+
'account' => ESA::ContextProviders::AccountContextProvider,
|
35
|
+
'accountable' => ESA::ContextProviders::AccountableContextProvider,
|
36
|
+
'accountable_type' => ESA::ContextProviders::AccountableTypeContextProvider,
|
37
|
+
'monthly' => [ESA::ContextProviders::DateContextProvider, {period: :month}],
|
38
|
+
'daily' => [ESA::ContextProviders::DateContextProvider, {period: :day}],
|
39
|
+
}
|
40
|
+
|
41
|
+
@context_tree = {
|
42
|
+
'account' => {
|
43
|
+
'monthly' => {
|
44
|
+
'daily' => {},
|
45
|
+
},
|
46
|
+
},
|
47
|
+
'monthly' => {
|
48
|
+
'account' => {
|
49
|
+
'daily' => {},
|
50
|
+
},
|
51
|
+
},
|
52
|
+
'daily' => {
|
53
|
+
'account' => {},
|
54
|
+
},
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def register(accountable, short_name=nil)
|
59
|
+
accountable_name = accountable.to_s
|
60
|
+
extension_name = short_name || accountable_name.demodulize
|
61
|
+
|
62
|
+
@base_classes.each do |klass|
|
63
|
+
klass.register_extension(accountable_name, self.extension_class(klass.name.demodulize, extension_name))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def extension_class(extension_type, extension_name)
|
68
|
+
[
|
69
|
+
@extension_namespace.presence,
|
70
|
+
"#{extension_type}s",
|
71
|
+
"#{extension_name}#{extension_type}"
|
72
|
+
].compact.join('::')
|
73
|
+
end
|
74
|
+
|
75
|
+
def walk_context_tree(path=[], tree=@context_tree)
|
76
|
+
if path.respond_to? :count and path.count == 0
|
77
|
+
tree || {}
|
78
|
+
elsif path.respond_to? :first and tree.is_a? Hash and path.first.in? tree
|
79
|
+
self.walk_context_tree(path.drop(1), tree[path.first])
|
80
|
+
else
|
81
|
+
{}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def context_providers_for_path(path=[])
|
86
|
+
@context_providers.slice(*self.walk_context_tree(path).keys)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -10,7 +10,7 @@ module ESA
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.contained_ids(context, options = {})
|
13
|
-
context.transactions.pluck([:accountable_id, :accountable_type])
|
13
|
+
context.transactions.uniq.pluck([:accountable_id, :accountable_type])
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.instantiate(parent, namespace, id, options = {})
|
@@ -10,7 +10,7 @@ module ESA
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.contained_ids(context, options = {})
|
13
|
-
dates = context.transactions.pluck("date(esa_transactions.time)").
|
13
|
+
dates = context.transactions.uniq.pluck("date(esa_transactions.time)").sort
|
14
14
|
|
15
15
|
if options[:period].present? and options[:period] == :month
|
16
16
|
dates.group_by{|d| [d.year, d.month]}.keys.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ESA
|
2
2
|
class SubcontextChecker
|
3
3
|
def self.check(context)
|
4
|
-
ESA
|
4
|
+
ESA.configuration.context_providers_for_path(context.effective_path).each do |namespace,provider|
|
5
5
|
if provider.is_a? Class and provider.respond_to? :check_subcontexts
|
6
6
|
provider.check_subcontexts(context, namespace)
|
7
7
|
elsif provider.respond_to? :count and provider.count == 2 and
|
data/lib/esa/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_sourced_accounting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lenno Nagel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -234,9 +234,9 @@ files:
|
|
234
234
|
- lib/esa/context_providers/date_context_provider.rb
|
235
235
|
- lib/esa/context_providers/accountable_context_provider.rb
|
236
236
|
- lib/esa/context_providers/accountable_type_context_provider.rb
|
237
|
-
- lib/esa/config.rb
|
238
237
|
- lib/esa/context_provider.rb
|
239
238
|
- lib/esa/balance_checker.rb
|
239
|
+
- lib/esa/configuration.rb
|
240
240
|
- lib/esa/blocking_processor.rb
|
241
241
|
- lib/esa/filters/chart_filter.rb
|
242
242
|
- lib/esa/filters/accountable_type_filter.rb
|
data/lib/esa/config.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module ESA
|
2
|
-
module Config
|
3
|
-
mattr_accessor :processor
|
4
|
-
self.processor = ESA::BlockingProcessor
|
5
|
-
|
6
|
-
mattr_accessor :context_checkers
|
7
|
-
self.context_checkers = Set.new
|
8
|
-
self.context_checkers << ESA::BalanceChecker
|
9
|
-
self.context_checkers << ESA::SubcontextChecker
|
10
|
-
|
11
|
-
mattr_accessor :context_providers
|
12
|
-
self.context_providers = {
|
13
|
-
'account' => ESA::ContextProviders::AccountContextProvider,
|
14
|
-
'accountable' => ESA::ContextProviders::AccountableContextProvider,
|
15
|
-
'accountable_type' => ESA::ContextProviders::AccountableTypeContextProvider,
|
16
|
-
'monthly' => [ESA::ContextProviders::DateContextProvider, {period: :month}],
|
17
|
-
'daily' => [ESA::ContextProviders::DateContextProvider, {period: :day}],
|
18
|
-
}
|
19
|
-
|
20
|
-
mattr_accessor :context_tree
|
21
|
-
self.context_tree = {
|
22
|
-
'account' => {
|
23
|
-
'monthly' => {
|
24
|
-
'daily' => {},
|
25
|
-
},
|
26
|
-
},
|
27
|
-
'monthly' => {
|
28
|
-
'account' => {
|
29
|
-
'daily' => {},
|
30
|
-
},
|
31
|
-
},
|
32
|
-
'daily' => {
|
33
|
-
'account' => {},
|
34
|
-
},
|
35
|
-
}
|
36
|
-
|
37
|
-
def self.walk_context_tree(path=[], tree=self.context_tree)
|
38
|
-
if path.respond_to? :count and path.count == 0
|
39
|
-
tree || {}
|
40
|
-
elsif path.respond_to? :first and tree.is_a? Hash and path.first.in? tree
|
41
|
-
walk_context_tree(path.drop(1), tree[path.first])
|
42
|
-
else
|
43
|
-
{}
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.context_providers_for_path(path=[])
|
48
|
-
context_providers.slice(*walk_context_tree(path).keys)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|