africompta 1.9.8

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.
@@ -0,0 +1,16 @@
1
+ class Schema_Infos < Entities
2
+ def setup_data
3
+ @default_type = :SQLiteAC
4
+ @data_field_id = :id
5
+
6
+ value_str :version
7
+ end
8
+
9
+ def migration_1(s)
10
+ s.version = '0.4'
11
+ end
12
+
13
+ def migration_2(s)
14
+ s.version = '0.5'
15
+ end
16
+ end
@@ -0,0 +1,292 @@
1
+ DEBUG_SLOW=4
2
+ class Movements < Entities
3
+ attr_reader :check_state, :check_progress
4
+
5
+ def setup_data
6
+ @default_type = :SQLiteAC
7
+ @data_field_id = :id
8
+ value_int :index
9
+
10
+ value_entity_account :account_src_id
11
+ value_entity_account :account_dst_id
12
+ value_float :value
13
+ value_str :desc
14
+ value_date :date
15
+ value_int :revision
16
+ value_str :global_id
17
+ value_int :rev_index
18
+ end
19
+
20
+ def migration_1(m)
21
+ dputs(1) { "Migrating #{m.id}" }
22
+ m.rev_index = m.id
23
+ end
24
+
25
+ def self.from_json(str)
26
+ self.from_s(ActiveSupport::JSON.decode(str)['str'])
27
+ end
28
+
29
+ def self.get_accounts(src, dst)
30
+ [Accounts.match_by_global_id(src), Accounts.match_by_global_id(dst)]
31
+ end
32
+
33
+ def self.mbgi(global_id)
34
+ self.match_by_global_id(global_id)
35
+ end
36
+
37
+ def self.from_s(str)
38
+ str.force_encoding(Encoding::UTF_8)
39
+ dputs(3) { "Getting movement from #{str.inspect}" }
40
+ desc, str = str.split("\r")
41
+ global_id, value, date, src, dst = str.split("\t")
42
+ #date = Time.parse(date).to_ss
43
+ date = Date.strptime(date, '%Y-%m-%d')
44
+ value = value.to_f
45
+ a_src, a_dst = self.get_accounts(src, dst)
46
+ if not a_src or not a_dst
47
+ dputs(0) { "Couldn't parse #{str.inspect}: " +
48
+ (a_src ? '' : "account #{src} not found. ") +
49
+ (a_dst ? '' : "account #{dst} not found") }
50
+ return nil
51
+ end
52
+ # Does the movement already exist?
53
+ dputs(DEBUG_SLOW) { 'from_s 1'
54
+ }
55
+ our_m = nil
56
+ if not (our_m = self.mbgi(global_id))
57
+ dputs(3) { 'New movement' }
58
+ our_m = self.create(desc, date, value,
59
+ a_src, a_dst)
60
+ dputs(DEBUG_SLOW) { 'from_s 2' }
61
+ our_m.global_id = global_id
62
+ else
63
+ dputs(1) { "Overwriting movement\n#{our_m.to_json.inspect} with" }
64
+ # And update it
65
+ our_m.set(desc, date, value, a_src.id, a_dst.id)
66
+ dputs(1) { "#{our_m.to_json.inspect}" }
67
+ dputs(2) { "Now we're #{our_m.rev_index}:#{our_m.id} -> #{global_id}" }
68
+ end
69
+ dputs(DEBUG_SLOW) { 'from_s 3' }
70
+ return our_m
71
+ end
72
+
73
+ def create(desc, date, value, source, dest)
74
+ return nil if source == dest
75
+ dputs(DEBUG_SLOW) { 'create - 1' }
76
+ if date.class == String
77
+ date = Date.strptime(date, '%Y-%m-%d')
78
+ end
79
+ t = super(:desc => desc, :date => date,
80
+ :value => 0, :account_src_id => source.id, :account_dst_id => dest.id)
81
+ dputs(DEBUG_SLOW) { 'create - 2' }
82
+ t.value = value
83
+ dputs(DEBUG_SLOW) { 'create - 3' }
84
+ t.global_id = Users.match_by_name('local').full + '-' + t.id.to_s
85
+ dputs(DEBUG_SLOW) { 'create - 4' }
86
+ dputs(1) { "Created #{t.to_json.inspect}" }
87
+ t
88
+ end
89
+
90
+ def search_index_range(from, to)
91
+ @data.select { |k, v|
92
+ v._rev_index && v._rev_index >= from && v._rev_index <= to
93
+ }.map { |k, v|
94
+ get_data_instance(k)
95
+ }
96
+ end
97
+
98
+ def get_account(db, id)
99
+ db.execute("select * from compta_accounts where id=#{id}").first[4]
100
+ end
101
+
102
+ def check_against_db(file)
103
+ # First build
104
+ # in_db - content of 'file' in .to_s format
105
+ # in_local - content available locally in .to_s format
106
+ in_db, diff, in_local = [], [], []
107
+
108
+ dputs(3) { 'Searching all movements' }
109
+ @check_state = 'Collect local'
110
+ @check_progress = 0.0
111
+ in_local = Movements.search_all_.reject { |m| m.value.to_f.round(3) == 0.0 }
112
+ progress_step = 1.0 / (in_local.size + 1)
113
+ dputs(3) { "Movements total: #{in_local.size}" }
114
+
115
+ @check_state = 'Collect local'
116
+ in_local = in_local.collect { |a|
117
+ @check_progress += progress_step
118
+ a.to_s
119
+ }
120
+
121
+ dputs(3) { 'Going to check all movements' }
122
+ @check_state = 'Collect file-DB'
123
+ @check_progress = 0.0
124
+ SQLite3::Database.new(file) do |db|
125
+ db.execute('select id, desc, global_id, value, date, account_src_id, account_dst_id '+
126
+ 'from compta_movements').each do |row|
127
+ @check_progress += progress_step
128
+ #dputs(3) { "Looking at #{row}" }
129
+
130
+ id_, desc_, gid_, value_, date_, src_, dst_ = row
131
+ if value_.to_f.round(3) != 0.0
132
+ in_db.push "#{desc_}\r#{gid_}\t" +
133
+ "#{sprintf('%.3f', value_.to_f.round(3))}\t#{date_.to_s}\t"+
134
+ "#{get_account(db, src_)}\t#{get_account(db, dst_)}"
135
+ end
136
+ end
137
+ end
138
+
139
+ # Now compare what is available only in db and what is available only locally
140
+ dputs(3) { 'Verifying movements on one side only' }
141
+ @check_state = 'On one side'
142
+ @check_progress = 0.0
143
+ in_db.delete_if { |a|
144
+ @check_progress += progress_step
145
+ in_local.delete(a)
146
+ }
147
+
148
+ # And search for accounts with same global-id but different content
149
+ dputs(3) { 'Verifying mixed-up movements' }
150
+ (in_db + in_local).sort_by { |a| a.match(/\r(.*?)\t/)[1] }
151
+ @check_state = 'Mixed-up'
152
+ @check_progress = 0.0
153
+ progress_step = 1.0 / (in_db.size + 1)
154
+ in_db.delete_if { |a|
155
+ @check_progress += progress_step
156
+ gid = a.match(/\r(.*?)\t/)[1]
157
+ if c = in_local.find { |b| b =~ /\r#{gid}\t/ }
158
+ diff.push [a, c]
159
+ in_local.delete c
160
+ end
161
+ }
162
+
163
+ @check_state = 'Done'
164
+ [in_db, diff, in_local]
165
+ end
166
+
167
+ end
168
+
169
+
170
+ class Movement < Entity
171
+
172
+ def init_instance
173
+ end
174
+
175
+ def data_set(f, v)
176
+ if f != :_rev_index
177
+ dputs(3){"Updating index for field #{f.inspect}"}
178
+ new_index
179
+ end
180
+ super(f, v)
181
+ end
182
+
183
+ def new_index
184
+ u_l = Users.match_by_name('local')
185
+ self.rev_index = u_l.movement_index.to_i
186
+ u_l.movement_index = self.rev_index + 1
187
+ dputs(3) { "index is #{self.rev_index} and date is --#{self.date}--" }
188
+ dputs(3) { "User('local').rev_index is: " + Users.match_by_name('local').movement_index.to_s }
189
+ end
190
+
191
+ def get_index
192
+ return self.rev_index
193
+ end
194
+
195
+ def is_in_account(a)
196
+ return (a == account_src or a == account_dst)
197
+ end
198
+
199
+ def value=(v)
200
+ if account_src and account_dst
201
+ dputs(3) { 'value=' + v.to_s + ':' + account_src.total.to_s }
202
+ diff = value.to_f - v.to_f
203
+ account_src.total = account_src.total.to_f + (diff * account_src.multiplier)
204
+ account_dst.total = account_dst.total.to_f - (diff * account_dst.multiplier)
205
+ end
206
+ data_set(:_value, v)
207
+ end
208
+
209
+ def get_value(account)
210
+ account_side = (account_src == account ? -1 : 1)
211
+ dputs(5) { "account_src #{account_src.inspect} == account #{account.inspect}" }
212
+ dputs(5) { "Account_side = #{account_side}" }
213
+ value.to_f * account.multiplier.to_f * account_side
214
+ end
215
+
216
+ def get_other_account(account)
217
+ account_src == account ? account_dst : account_src
218
+ end
219
+
220
+ def move_from_to(from, to)
221
+ v = self.value
222
+ self.value = 0
223
+ if account_src_id == from
224
+ self.account_src_id = to
225
+ end
226
+ if account_dst_id == from
227
+ self.account_dst_id = to
228
+ end
229
+ self.value = v
230
+ end
231
+
232
+ def set(desc, date, value, source, dest)
233
+ dputs(3) { 'self.value ' + self.value.to_s + ' - ' + value.to_s }
234
+ self.value = 0
235
+ self.account_src_id, self.account_dst_id = source, dest
236
+ if false
237
+ # Do some date-magic, so that we can give either the day, day and month or
238
+ # a complete date. The rest is filled up with todays date.
239
+ date = date.split('/')
240
+ da = Date.today
241
+ d = [da.day, da.month, da.year]
242
+ date += d.last(3 - date.size)
243
+ if date[2].to_s.size > 2
244
+ self.date = Date.strptime(date.join('/'), '%d/%m/%Y')
245
+ else
246
+ self.date = Date.strptime(date.join('/'), '%d/%m/%y')
247
+ end
248
+ else
249
+ self.date = Date.from_s(date.to_s)
250
+ end
251
+ self.desc, self.value = desc, value
252
+ dputs(DEBUG_SLOW) { 'Getting new index' }
253
+ self.new_index
254
+ dputs(DEBUG_SLOW) { 'Date ' + self.date.to_s }
255
+ end
256
+
257
+ def to_s
258
+ dputs(5) { "I am: #{to_hash.inspect} - my id is: #{global_id}" }
259
+ "#{desc}\r#{global_id}\t" +
260
+ "#{sprintf('%.3f', value.to_f.round(3))}\t#{date.to_s}\t" +
261
+ account_src.global_id.to_s + "\t" +
262
+ account_dst.global_id.to_s
263
+ end
264
+
265
+ def to_json
266
+ ActiveSupport::JSON.encode(:str => to_s)
267
+ end
268
+
269
+ # Copying over data from old AfriCompta
270
+ def account_src
271
+ account_src_id
272
+ end
273
+
274
+ def account_dst
275
+ account_dst_id
276
+ end
277
+
278
+ def delete
279
+ dputs(DEBUG_SLOW) { "Deleting movement #{desc}" }
280
+ src, dst = account_src, account_dst
281
+ dputs(3) { "totals before: #{src.get_path}=#{src.total}, " +
282
+ "#{dst.get_path}=#{dst.total}" }
283
+ self.value = 0
284
+ dputs(3) { "totals after: #{src.get_path}=#{src.total}, " +
285
+ "#{dst.get_path}=#{dst.total}" }
286
+ super
287
+ end
288
+
289
+ def value_form
290
+ Account.total_form(value)
291
+ end
292
+ end
@@ -0,0 +1,27 @@
1
+ class Remotes < Entities
2
+
3
+ def create( d )
4
+ r = super( d )
5
+ d.has_key?( :account_index ) || r.account_index = 0
6
+ d.has_key?( :movement_index ) || r.movement_index = 0
7
+ r
8
+ end
9
+
10
+ def setup_data
11
+ value_str :url
12
+ value_str :name
13
+ value_str :pass
14
+ value_int :account_index
15
+ value_int :movement_index
16
+ end
17
+ end
18
+
19
+ class Remote < Entity
20
+ def update_movement_index
21
+ self.movement_index = Users.match_by_name('local').movement_index - 1
22
+ end
23
+
24
+ def update_account_index
25
+ self.account_index = Users.match_by_name('local').account_index - 1
26
+ end
27
+ end
@@ -0,0 +1,55 @@
1
+ class Users < Entities
2
+
3
+ def setup_data
4
+ @default_type = :SQLiteAC
5
+ @data_field_id = :id
6
+
7
+ value_str :name
8
+ value_str :full
9
+ value_str :pass
10
+ #value_array :accounts
11
+ # The last account_index that got transmitted
12
+ value_int :account_index
13
+ # The last movement_index that got transmitted
14
+ value_int :movement_index
15
+ end
16
+
17
+ def load
18
+ super
19
+ if Users.search_by_name('local').count == 0
20
+ user = Users.create('local', Digest::MD5.hexdigest((rand 2**128).to_s).to_s,
21
+ rand(2 ** 128).to_s)
22
+ dputs(1) { "Created local user #{user}" }
23
+ end
24
+ end
25
+
26
+ def migration_1(u)
27
+ u.account_index ||= 0
28
+ u.movement_index ||= 0
29
+ end
30
+
31
+ def create(name, full = nil, pass = nil)
32
+ if not full or not pass
33
+ dputs(2) { "Creating with hash: #{name.inspect}" }
34
+ name, full, pass = name[:name], name[:full], name[:pass]
35
+ end
36
+ new_user = super(:name => name, :full => full, :pass => pass)
37
+ new_user.account_index, new_user.movement_index = 0, 0
38
+ new_user
39
+ end
40
+ end
41
+
42
+ class User < Entity
43
+ def update_movement_index
44
+ self.movement_index = Users.match_by_name('local').movement_index - 1
45
+ end
46
+
47
+ def update_account_index
48
+ self.account_index = Users.match_by_name('local').account_index - 1
49
+ end
50
+
51
+ def update_all
52
+ update_movement_index
53
+ update_account_index
54
+ end
55
+ end
@@ -0,0 +1,8 @@
1
+
2
+ class EditMovements < View
3
+ def layout
4
+ gui_vbox do
5
+ show_str :movement
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+
2
+ class EditTabs < View
3
+ def layout
4
+ gui_vbox do
5
+ show_str :edit
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ class ReportAnnual < View
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class ReportTabs < View
2
+
3
+ end
data/lib/africompta.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler/setup'
2
+ require 'africompta/africompta'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: africompta
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.9.8
5
+ platform: ruby
6
+ authors:
7
+ - Linus Gasser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: qooxview
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: With this module you can have a simple accounting-system
28
+ email: ineiti@linusetviviane.ch
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ".gitignore"
34
+ - Gemfile
35
+ - Gemfile.lock
36
+ - TODO
37
+ - Test/ac_account.rb
38
+ - Test/ac_africompta.rb
39
+ - Test/ac_big.rb
40
+ - Test/ac_movement.rb
41
+ - Test/ac_sqlite.rb
42
+ - Test/config_test.yaml
43
+ - Test/db.testGestion
44
+ - Test/test.rb
45
+ - VERSION
46
+ - africompta.gemspec
47
+ - lib/africompta.rb
48
+ - lib/africompta/acaccess.rb
49
+ - lib/africompta/acqooxview.rb
50
+ - lib/africompta/africompta.rb
51
+ - lib/africompta/entities/account.rb
52
+ - lib/africompta/entities/acschemas.rb
53
+ - lib/africompta/entities/movement.rb
54
+ - lib/africompta/entities/remote.rb
55
+ - lib/africompta/entities/users.rb
56
+ - lib/africompta/views/edit/movement.rb
57
+ - lib/africompta/views/edit/tabs.rb
58
+ - lib/africompta/views/report/annual.rb
59
+ - lib/africompta/views/report/tabs.rb
60
+ homepage: https://github.com/ineiti/AfriCompta
61
+ licenses:
62
+ - GPLv3
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.2.2
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Africompta-module for QooxView
84
+ test_files: []