avmtrf1-tools 0.11.2 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d9d2aeb4f8c6609917bfee3a3b9e8991ae24a7e10adaacdb87f04e4409a68e3
4
- data.tar.gz: 703ccfa1ee139154efa028805063f7b9477a89842d5f1ecc963e450b6e2a0d52
3
+ metadata.gz: ef001c26f83ae5f6ca0752cad6eac0eeff0cc402cfe6f5f2acf27ced7e36e2ee
4
+ data.tar.gz: c5f0fb9404e584124a954498d8eb4db22dad6b0b4b383e664e6a3e0d538fef55
5
5
  SHA512:
6
- metadata.gz: db0460a5171348b0d4aa85553e6c25e99bf7c2430e942874a179b034b2324192a0411533cbdf08a53b7f5136667eb630f5a41dc491c5e9fb2ca83f385839f493
7
- data.tar.gz: 6d728ac9aaff3309cd57abed5d8e99241c3054a3c08df6a45ae8bd92aeff7733fabfd65e8372f1b9162f4ff057f805002311d7a0abacd7fbbf8857efa19ea27f
6
+ metadata.gz: 8eeb23824123920f62d4b6030ad7b1833fda4e0585e444e2730968565ff784cc091581922ae689cc155f8f47f07b636e633335db3117d09e1d42d22a076bf48e
7
+ data.tar.gz: f7b141e875ff41297f2b5e2921bd34b92da87e2834e049fd2d9e246df72d9ac09d700626ca3ec46bfaf696f357fe70345c7636924e59510fb538ec0eba08da67
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avmtrf1
4
+ module Forponto
5
+ class User
6
+ class Balance
7
+ include ::EacRubyUtils::SimpleCache
8
+
9
+ attr_reader :user
10
+
11
+ def initialize(user)
12
+ @user = user
13
+ build_balances
14
+ end
15
+
16
+ def months_balances_uncached
17
+ sorted_months.map { |m| MyBalance.new(m) }
18
+ end
19
+
20
+ def sorted_months_uncached
21
+ r = []
22
+ current = head_month
23
+ while current.present?
24
+ r << current
25
+ current = current.parent_month
26
+ end
27
+ r.reverse
28
+ end
29
+
30
+ def head_month
31
+ today = ::Date.today
32
+ date = ::Date.civil(today.year, today.month, 1)
33
+ user.month(date.year, date.month)
34
+ end
35
+
36
+ def debito_left
37
+ months_balances.inject(0) { |a, e| a + e.debito.left }
38
+ end
39
+
40
+ def credito_left
41
+ months_balances.inject(0) { |a, e| a + e.credito.left }
42
+ end
43
+
44
+ def saldo_left
45
+ credito_left - debito_left
46
+ end
47
+
48
+ private
49
+
50
+ def build_balances
51
+ previous = []
52
+ months_balances.each do |current|
53
+ current.consume(previous)
54
+ previous << current
55
+ if previous.count > 3
56
+ removed = previous.shift
57
+ removed.mark_lost
58
+ end
59
+ end
60
+ end
61
+
62
+ class MyBalance
63
+ attr_accessor :debito, :credito, :month, :lost
64
+
65
+ def initialize(month)
66
+ @month = month
67
+ @debito = AttrConsumer.new(self, false, month.debito)
68
+ @credito = AttrConsumer.new(self, true, month.credito)
69
+ @lost = false
70
+ end
71
+
72
+ def after_trigger
73
+ credito.after_trigger - debito.after_trigger
74
+ end
75
+
76
+ def after_trigger_acum
77
+ credito.after_trigger_acum - debito.after_trigger_acum
78
+ end
79
+
80
+ def mark_lost
81
+ @lost = true
82
+ end
83
+
84
+ def to_s
85
+ month.to_s
86
+ end
87
+
88
+ def consume(previous)
89
+ debito.consume_from_months(previous)
90
+ credito.consume_from_months(previous)
91
+ end
92
+
93
+ class AttrConsumer
94
+ attr_reader :owner_month, :initial_value, :left, :unconsumed, :withdrawals, :requests,
95
+ :after_trigger, :after_trigger_acum
96
+
97
+ def initialize(owner_month, credito, initial_value)
98
+ @owner_month = owner_month
99
+ @credito = credito
100
+ @left = initial_value
101
+ @initial_value = initial_value
102
+ @withdrawals = []
103
+ @requests = []
104
+ @after_trigger = nil
105
+ end
106
+
107
+ def to_s
108
+ "[#{owner_month}|#{attr}]"
109
+ end
110
+
111
+ def consume_from_months(months)
112
+ (months + [owner_month]).each do |month|
113
+ break unless left.positive?
114
+
115
+ consume_from_month(month)
116
+ end
117
+ @after_trigger = left
118
+ @after_trigger_acum = months.inject(0) { |a, e| a + e.send(attr).left } + left
119
+ end
120
+
121
+ def withdrawal(month, value)
122
+ month.assert_argument(MyBalance, :month)
123
+ raise "Value is not positive: #{value} (Month: #{month})" unless value.positive?
124
+
125
+ self.left -= value
126
+ raise "Left less than zero: #{left} (Value: #{value})" if left.negative?
127
+
128
+ @withdrawals << OpenStruct.new(month: month, value: value)
129
+ end
130
+
131
+ private
132
+
133
+ attr_writer :left, :unconsumed
134
+
135
+ def consume_from_month(month)
136
+ month_attr = month.send(reverse_attr)
137
+ return unless month_attr.left.positive?
138
+
139
+ value = [left, month_attr.left].min
140
+ self.left -= value
141
+ month_attr.withdrawal(owner_month, value)
142
+ @requests << OpenStruct.new(month: month, value: value)
143
+ end
144
+
145
+ def attr
146
+ @credito ? :credito : :debito
147
+ end
148
+
149
+ def reverse_attr
150
+ @credito ? :debito : :credito
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -3,6 +3,7 @@
3
3
  require 'active_support/json'
4
4
  require 'eac_ruby_utils/core_ext'
5
5
  require 'eac_ruby_utils/yaml'
6
+ require 'recursive-open-struct'
6
7
  require 'avmtrf1/forponto/parsers/espelho'
7
8
  require 'avmtrf1/forponto/session'
8
9
  require 'avmtrf1/fs_cache'
@@ -30,7 +31,7 @@ module Avmtrf1
30
31
  data_cache.write(r.to_yaml)
31
32
  r
32
33
  else
33
- ::EacRubyUtils::Yaml.load_common(data_cache.read)
34
+ cached_data
34
35
  end
35
36
  end
36
37
 
@@ -86,11 +87,19 @@ module Avmtrf1
86
87
  end
87
88
 
88
89
  def recache?
89
- !data_cache.cached?
90
+ !data_cache.cached? || yesterday_uncached?
91
+ end
92
+
93
+ def yesterday_uncached?
94
+ last_cached_day < end_date && last_cached_day < (::Date.today - 1.days)
95
+ end
96
+
97
+ def last_cached_day_uncached
98
+ cached_data.fetch('days').map { |day| day.fetch('date') }.max
90
99
  end
91
100
 
92
101
  def data_cache_uncached
93
- ::Avmtrf1.fs_cache.child('forponto', user.matricula, month.to_s.rjust(2, '0'))
102
+ ::Avmtrf1.fs_cache.child('forponto', user.matricula, year.to_s, month.to_s.rjust(2, '0'))
94
103
  end
95
104
 
96
105
  def date(day)
@@ -105,6 +114,12 @@ module Avmtrf1
105
114
  date(-1)
106
115
  end
107
116
 
117
+ def cached_data
118
+ raise 'There is no data cached' unless data_cache.cached?
119
+
120
+ ::EacRubyUtils::Yaml.load_common(data_cache.read)
121
+ end
122
+
108
123
  def fresh_data
109
124
  session = new_session
110
125
  begin
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'avm/templates/directory'
4
- require 'avm/templates/file'
3
+ require 'eac_ruby_utils/templates/searcher'
5
4
 
6
5
  module Avmtrf1
7
6
  class << self
@@ -9,12 +8,16 @@ module Avmtrf1
9
8
  ::File.expand_path('../../template', __dir__)
10
9
  end
11
10
 
12
- def template(subpath)
13
- path = ::File.join(templates_root, subpath)
14
- return ::Avm::Templates::Directory.new(path) if ::File.directory?(path)
15
- return ::Avm::Templates::File.new(path) if ::File.file?(path)
11
+ def template_searcher
12
+ @template_searcher ||= begin
13
+ r = ::EacRubyUtils::Templates::Searcher.new
14
+ r.included_paths << templates_root
15
+ r
16
+ end
17
+ end
16
18
 
17
- raise "Template \"#{path}\" not found"
19
+ def template(subpath)
20
+ template_searcher.template(subpath)
18
21
  end
19
22
  end
20
23
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avmtrf1
4
+ module Tools
5
+ class Runner < ::EacRubyUtils::Console::DocoptRunner
6
+ class Forponto < ::EacRubyUtils::Console::DocoptRunner
7
+ class Resumos < ::EacRubyUtils::Console::DocoptRunner
8
+ include ::EacRubyUtils::SimpleCache
9
+ include ::EacRubyUtils::Console::Speaker
10
+
11
+ DOC = <<~DOCOPT
12
+ Mostra os resumos.
13
+
14
+ Usage:
15
+ __PROGRAM__ [options]
16
+ __PROGRAM__ -h | --help
17
+
18
+ Options:
19
+ -h --help Show this screen.
20
+ DOCOPT
21
+
22
+ def run
23
+ sorted_months.each do |month|
24
+ show_month(month)
25
+ end
26
+ end
27
+
28
+ def head_month
29
+ today = ::Date.today
30
+ date = ::Date.civil(today.year, today.month, 1)
31
+ context(:user).month(date.year, date.month)
32
+ end
33
+
34
+ def show_month(month)
35
+ infov 'Month', month
36
+ show_self_summaries(month)
37
+ end
38
+
39
+ def show_self_summaries(month)
40
+ infov ' * Self summaries', month.os_data.summaries.count
41
+ show_month_summaries(month)
42
+ show_month_self_summaries(month)
43
+ show_month_acum_summaries(month)
44
+ end
45
+
46
+ def show_month_summaries(month)
47
+ month.os_data.summaries.each do |s|
48
+ infov ' * ' + summary_to_label(s), summary_to_value(s)
49
+ end
50
+ end
51
+
52
+ def show_month_self_summaries(month)
53
+ infov ' * Débito', minutes_to_s(month.debito)
54
+ infov ' * Crédito', minutes_to_s(month.credito)
55
+ infov ' * Saldo', minutes_to_s(month.saldo)
56
+ end
57
+
58
+ def show_month_acum_summaries(month)
59
+ infov ' * Débito acum.', minutes_to_s(month.debito_acum)
60
+ infov ' * Crédito acum.', minutes_to_s(month.credito_acum)
61
+ infov ' * Saldo acum.', minutes_to_s(month.saldo_acum)
62
+ end
63
+
64
+ def summary_to_label(summary)
65
+ "#{summary.code} - #{summary.description}"
66
+ end
67
+
68
+ def summary_to_value(summary)
69
+ minutes_to_s(summary.minutes)
70
+ end
71
+
72
+ def minutes_to_s(minutes)
73
+ signal = ''
74
+ if minutes.negative?
75
+ signal = '-'
76
+ minutes = -minutes
77
+ end
78
+ time = [minutes / 60, minutes % 60].map { |x| x.to_s.rjust(2, '0') }.join(':')
79
+ "#{signal}#{time} / #{signal}#{minutes} minutes"
80
+ end
81
+
82
+ def sorted_months_uncached
83
+ r = []
84
+ current = head_month
85
+ while current.present?
86
+ r << current
87
+ current = current.parent_month
88
+ end
89
+ r.reverse
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avmtrf1
4
+ module Tools
5
+ class Runner < ::EacRubyUtils::Console::DocoptRunner
6
+ class Forponto < ::EacRubyUtils::Console::DocoptRunner
7
+ class Saldo < ::EacRubyUtils::Console::DocoptRunner
8
+ include ::EacRubyUtils::SimpleCache
9
+ include ::EacRubyUtils::Console::Speaker
10
+
11
+ DOC = <<~DOCOPT
12
+ Calcula saldo de horas atual.
13
+
14
+ Usage:
15
+ __PROGRAM__ [options]
16
+ __PROGRAM__ -h | --help
17
+
18
+ Options:
19
+ -h --help Show this screen.
20
+ -d --details Show details.
21
+ DOCOPT
22
+
23
+ def run
24
+ balance.months_balances.each do |mb|
25
+ show_balance_month(mb)
26
+ end
27
+ end_banner
28
+ end
29
+
30
+ def end_banner
31
+ infov 'Crédito final', minutes_to_s(balance.credito_left)
32
+ infov 'Débito final', minutes_to_s(balance.debito_left)
33
+ infov 'Saldo final', minutes_to_s(balance.saldo_left)
34
+ end
35
+
36
+ def show_balance_month(balance_month)
37
+ infov 'Month', balance_month.month
38
+ show_month_attr_balance(balance_month.credito, 'Crédito')
39
+ show_month_attr_balance(balance_month.debito, 'Débito')
40
+ infov ' * After trigger', minutes_to_s(balance_month.after_trigger)
41
+ infov ' * After trigger acum.', minutes_to_s(balance_month.after_trigger_acum)
42
+ end
43
+
44
+ def show_month_attr_balance(mba, label)
45
+ infov " * #{label}", minutes_to_s(mba.initial_value)
46
+ return unless options.fetch('--details')
47
+
48
+ show_month_withdrawals(mba)
49
+ show_month_requests(mba)
50
+ show_month_end_resume(mba)
51
+ end
52
+
53
+ def show_month_withdrawals(mba)
54
+ infov ' * Withdrawals', mba.withdrawals.count
55
+ mba.withdrawals.each do |w|
56
+ infov " * #{w.month.month}", minutes_to_s(w.value)
57
+ end
58
+ end
59
+
60
+ def show_month_requests(mba)
61
+ infov ' * Requests', mba.requests.count
62
+ mba.requests.each do |r|
63
+ infov " * #{r.month.month}", minutes_to_s(r.value)
64
+ end
65
+ end
66
+
67
+ def show_month_end_resume(mba)
68
+ infov ' * Left', minutes_to_s(mba.left) + ' ' + left_status(mba)
69
+ infov ' * After trigger', minutes_to_s(mba.after_trigger)
70
+ infov ' * After trigger acum.', minutes_to_s(mba.after_trigger_acum)
71
+ end
72
+
73
+ def left_status(mba)
74
+ if mba.left.positive? && mba.owner_month.lost
75
+ '[LOST]'.red
76
+ else
77
+ '[OK]'
78
+ end
79
+ end
80
+
81
+ def minutes_to_s(minutes)
82
+ signal = ''
83
+ if minutes.negative?
84
+ signal = '-'
85
+ minutes = -minutes
86
+ end
87
+ time = [minutes / 60, minutes % 60].map { |x| x.to_s.rjust(2, '0') }.join(':')
88
+ "#{signal}#{time} / #{signal}#{minutes} minutes"
89
+ end
90
+
91
+ def balance_uncached
92
+ ::Avmtrf1::Forponto::User::Balance.new(context(:user))
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Avmtrf1
4
4
  module Tools
5
- VERSION = '0.11.2'
5
+ VERSION = '0.12.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avmtrf1-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.2
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eduardo H. Bogoni
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-25 00:00:00.000000000 Z
11
+ date: 2019-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aranha-parsers
@@ -154,6 +154,20 @@ dependencies:
154
154
  - - ">="
155
155
  - !ruby/object:Gem::Version
156
156
  version: '0'
157
+ - !ruby/object:Gem::Dependency
158
+ name: recursive-open-struct
159
+ requirement: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - "~>"
162
+ - !ruby/object:Gem::Version
163
+ version: '1.1'
164
+ type: :runtime
165
+ prerelease: false
166
+ version_requirements: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - "~>"
169
+ - !ruby/object:Gem::Version
170
+ version: '1.1'
157
171
  - !ruby/object:Gem::Dependency
158
172
  name: rspec
159
173
  requirement: !ruby/object:Gem::Requirement
@@ -254,6 +268,7 @@ files:
254
268
  - lib/avmtrf1/forponto/parsers/espelho/utils.rb
255
269
  - lib/avmtrf1/forponto/session.rb
256
270
  - lib/avmtrf1/forponto/user.rb
271
+ - lib/avmtrf1/forponto/user/balance.rb
257
272
  - lib/avmtrf1/forponto/user/month.rb
258
273
  - lib/avmtrf1/fs_cache.rb
259
274
  - lib/avmtrf1/git.rb
@@ -313,6 +328,8 @@ files:
313
328
  - lib/avmtrf1/tools/runner/esosti.rb
314
329
  - lib/avmtrf1/tools/runner/forponto.rb
315
330
  - lib/avmtrf1/tools/runner/forponto/espelho.rb
331
+ - lib/avmtrf1/tools/runner/forponto/resumos.rb
332
+ - lib/avmtrf1/tools/runner/forponto/saldo.rb
316
333
  - lib/avmtrf1/tools/runner/git.rb
317
334
  - lib/avmtrf1/tools/runner/git/issues_check.rb
318
335
  - lib/avmtrf1/tools/runner/git/push_large.rb