smerp-quotation 0.1.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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +160 -0
- data/README.md +35 -0
- data/Rakefile +13 -0
- data/bin/console +22 -0
- data/bin/setup +8 -0
- data/config/database.yml +5 -0
- data/db/config.yml +5 -0
- data/db/migrate/20220901033002_create_quotations.rb +40 -0
- data/db/migrate/20220901033007_create_quotation_items.rb +69 -0
- data/db/migrate/20220918121051_create_quotation_item_groups.rb +34 -0
- data/db/migrate/20220922121503_create_tax_category.rb +20 -0
- data/lib/smerp/quotation/ar_model/quotation.rb +111 -0
- data/lib/smerp/quotation/ar_model/quotation_item.rb +417 -0
- data/lib/smerp/quotation/ar_model/quotation_item_group.rb +34 -0
- data/lib/smerp/quotation/ar_model/tax_category.rb +34 -0
- data/lib/smerp/quotation/calculators/discount_calculator.rb +69 -0
- data/lib/smerp/quotation/calculators/round_up_calculator.rb +33 -0
- data/lib/smerp/quotation/calculators/tax_calculator.rb +76 -0
- data/lib/smerp/quotation/extended_calculator.rb +76 -0
- data/lib/smerp/quotation/item_group_manager.rb +72 -0
- data/lib/smerp/quotation/quotation_item_manager.rb +112 -0
- data/lib/smerp/quotation/quotation_manager.rb +86 -0
- data/lib/smerp/quotation/tax_category_manager.rb +22 -0
- data/lib/smerp/quotation/version.rb +7 -0
- data/lib/smerp/quotation.rb +40 -0
- data/schema.rb +85 -0
- data/smerp-quotation.gemspec +51 -0
- metadata +197 -0
@@ -0,0 +1,417 @@
|
|
1
|
+
|
2
|
+
require 'acts_as_tree'
|
3
|
+
|
4
|
+
module Smerp
|
5
|
+
|
6
|
+
module Quotation
|
7
|
+
|
8
|
+
module ArModel
|
9
|
+
class QuotationItem < Ca::DataStore::Ar::Model
|
10
|
+
|
11
|
+
include TR::CondUtils
|
12
|
+
|
13
|
+
include TeLogger::TeLogHelper
|
14
|
+
teLogger_tag :quotItmMdl
|
15
|
+
|
16
|
+
include ActsAsTree
|
17
|
+
acts_as_tree
|
18
|
+
|
19
|
+
belongs_to :quotation
|
20
|
+
|
21
|
+
belongs_to :quotable, polymorphic: true
|
22
|
+
# polymorphic on model of products / resources
|
23
|
+
# has_many :quotation_items, as: :quotable
|
24
|
+
|
25
|
+
belongs_to :quotation_item_group, optional: true
|
26
|
+
|
27
|
+
before_save :update_total
|
28
|
+
after_save :update_group_total, :update_quotation_total
|
29
|
+
|
30
|
+
before_destroy :update_total
|
31
|
+
after_destroy :update_group_total, :update_quotation_total
|
32
|
+
|
33
|
+
def update_total
|
34
|
+
|
35
|
+
if children.length == 0
|
36
|
+
self.line_total = self.quantity * self.unit_price if self.quantity_changed? or self.unit_price_changed?
|
37
|
+
self.line_total_after_discount = self.line_total
|
38
|
+
self.line_total_with_tax = self.line_total
|
39
|
+
end
|
40
|
+
|
41
|
+
if self.quantity_changed?
|
42
|
+
# Change unit_price for record that has children
|
43
|
+
# since unit_price is 'derived' from children's line_total
|
44
|
+
if self.quantity > 0
|
45
|
+
self.unit_price = self.line_total / self.quantity
|
46
|
+
else
|
47
|
+
self.unit_price = 0.0
|
48
|
+
self.line_total = 0.0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
res = { local: [], quotation: [] }
|
53
|
+
extCals = { local: [], quotation: [] }
|
54
|
+
if not_empty?(self.extended_calculators)
|
55
|
+
extCals = YAML.load(self.extended_calculators)
|
56
|
+
end
|
57
|
+
|
58
|
+
extCals[:local].each do |ec|
|
59
|
+
teLogger.debug "Executing item calculator : #{ec.inspect}"
|
60
|
+
ec.calculate(self)
|
61
|
+
ec.owner_id = self.id if is_empty?(ec.owner_id) and not self.new_record?
|
62
|
+
res[:local] << ec.for_storage
|
63
|
+
end
|
64
|
+
|
65
|
+
if self.new_record?
|
66
|
+
|
67
|
+
# apply global calculator from quotation
|
68
|
+
gExtCals = []
|
69
|
+
if not_empty?(self.quotation.extended_calculators)
|
70
|
+
gExtCals = YAML.load(self.quotation.extended_calculators)
|
71
|
+
end
|
72
|
+
|
73
|
+
#cals = []
|
74
|
+
gExtCals.each do |ec|
|
75
|
+
|
76
|
+
teLogger.debug "Executing item-quotation calculator : #{ec.inspect}"
|
77
|
+
ec.calculate(self)
|
78
|
+
ec.owner_id = self.quotation.id if is_empty?(ec.owner_id)
|
79
|
+
res[:quotation] << ec.for_storage
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
else
|
84
|
+
|
85
|
+
extCals[:quotation].each do |ec|
|
86
|
+
teLogger.debug "Executing item-quotation calculator : #{ec.inspect}"
|
87
|
+
ec.calculate(self)
|
88
|
+
ec.owner_id = self.quotation.id if is_empty?(ec.owner_id)
|
89
|
+
res[:quotation] << ec.for_storage
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# after calculate, remove item with zero params
|
96
|
+
res[:local].delete_if { |c|
|
97
|
+
case c.params
|
98
|
+
when Smerp::Common::FinUtils::Percent
|
99
|
+
c.params.value == 0
|
100
|
+
else
|
101
|
+
c.params.to_i == 0
|
102
|
+
end
|
103
|
+
}
|
104
|
+
|
105
|
+
res[:quotation].delete_if { |c|
|
106
|
+
case c.params
|
107
|
+
when Smerp::Common::FinUtils::Percent
|
108
|
+
c.params.value == 0
|
109
|
+
else
|
110
|
+
c.params.to_i == 0
|
111
|
+
end
|
112
|
+
}
|
113
|
+
|
114
|
+
self.extended_calculators = YAML.dump(res)
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
def update_group_total
|
119
|
+
|
120
|
+
grp = self.quotation_item_group
|
121
|
+
if not grp.nil?
|
122
|
+
# update total
|
123
|
+
grp.group_total = grp.children.sum(:group_total) + grp.quotation_items.sum(:line_total)
|
124
|
+
grp.group_discount = grp.children.sum(:group_discount) + grp.quotation_items.sum(:discount)
|
125
|
+
grp.group_tax = grp.children.sum(:group_tax) + grp.quotation_items.sum(:tax)
|
126
|
+
grp.save
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
def update_quotation_total
|
132
|
+
|
133
|
+
if not self.parent.nil?
|
134
|
+
|
135
|
+
self.parent.reload
|
136
|
+
|
137
|
+
if self.parent.is_children_linked?
|
138
|
+
|
139
|
+
teLogger.debug "Parent #{self.parent.inspect} IS children linked"
|
140
|
+
#
|
141
|
+
# Children of another QuotationItem
|
142
|
+
#
|
143
|
+
if self.parent.quantity > 0
|
144
|
+
# for children item that has a parent
|
145
|
+
# update parent line_total
|
146
|
+
self.parent.line_total = self.parent.children.sum(:line_total)
|
147
|
+
|
148
|
+
# update unit_price since line_total is sum of children's line_total
|
149
|
+
self.parent.unit_price = self.parent.line_total / self.parent.quantity
|
150
|
+
|
151
|
+
self.parent.discount = self.parent.children.sum(:discount)
|
152
|
+
self.parent.line_total_after_discount = self.parent.children.sum(:line_total_after_discount)
|
153
|
+
self.parent.tax = self.parent.children.sum(:tax)
|
154
|
+
self.parent.line_total_with_tax = self.parent.children.sum(:line_total_with_tax)
|
155
|
+
|
156
|
+
teLogger.debug "After update from children : #{self.parent.inspect}"
|
157
|
+
|
158
|
+
else
|
159
|
+
|
160
|
+
self.parent.line_total = 0.0
|
161
|
+
self.parent.unit_price = 0.0
|
162
|
+
self.parent.discount = 0.0
|
163
|
+
self.parent.line_total_after_discount = 0.0
|
164
|
+
self.parent.tax = 0.0
|
165
|
+
self.parent.line_total_with_tax = 0.0
|
166
|
+
end
|
167
|
+
|
168
|
+
self.parent.save
|
169
|
+
|
170
|
+
else
|
171
|
+
teLogger.debug "Parent #{self.parent.inspect} is NOT children linked. Skipping children update to parent."
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
self.quotation.total = self.quotation.quotation_items.where(["parent_id is null"]).sum(:line_total)
|
177
|
+
self.quotation.total_discount = self.quotation.quotation_items.where(["parent_id is null"]).sum(:discount)
|
178
|
+
self.quotation.total_after_discount = self.quotation.quotation_items.where(["parent_id is null"]).sum(:line_total_after_discount)
|
179
|
+
self.quotation.total_tax = self.quotation.quotation_items.where(["parent_id is null"]).sum(:tax)
|
180
|
+
self.quotation.total_with_tax = self.quotation.quotation_items.where(["parent_id is null"]).sum(:line_total_with_tax)
|
181
|
+
|
182
|
+
self.quotation.save
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
def recalculate
|
187
|
+
|
188
|
+
if self.quantity_changed? or self.unit_price_changed?
|
189
|
+
self.line_total = self.quantity * self.unit_price
|
190
|
+
end
|
191
|
+
|
192
|
+
if self.discount_changed?
|
193
|
+
self.line_total_after_discount = self.line_total - self.discount
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
#def children
|
200
|
+
# if @_children.nil?
|
201
|
+
# @_children = QuotationItem.where(["parent_id = ?",self.id])
|
202
|
+
# end
|
203
|
+
# @_children
|
204
|
+
#end
|
205
|
+
|
206
|
+
#def parent
|
207
|
+
# if self.parent_id.nil?
|
208
|
+
# nil
|
209
|
+
# else
|
210
|
+
# if @_parent.nil?
|
211
|
+
# @_parent = QuotationItem.find(self.parent_id)
|
212
|
+
# end
|
213
|
+
# @_parent
|
214
|
+
# end
|
215
|
+
#end
|
216
|
+
|
217
|
+
def break_children_link
|
218
|
+
|
219
|
+
self.children_link = 0
|
220
|
+
# all fields updated by children shall be reset
|
221
|
+
self.line_total = 0.0
|
222
|
+
self.unit_price = 0.0
|
223
|
+
self.discount = 0.0
|
224
|
+
self.line_total_after_discount = 0.0
|
225
|
+
self.tax = 0.0
|
226
|
+
self.line_total_with_tax = 0.0
|
227
|
+
|
228
|
+
self.save
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
def ensure_children_link
|
233
|
+
|
234
|
+
self.children_link = 1
|
235
|
+
|
236
|
+
if self.children.length > 0 and self.quantity > 0
|
237
|
+
|
238
|
+
# update from line_total
|
239
|
+
self.line_total = self.children.sum(:line_total)
|
240
|
+
|
241
|
+
# update unit_price since line_total is sum of children's line_total
|
242
|
+
self.unit_price = self.line_total / self.quantity
|
243
|
+
|
244
|
+
self.discount = self.children.sum(:discount)
|
245
|
+
self.line_total_after_discount = self.children.sum(:line_total_after_discount)
|
246
|
+
self.tax = self.children.sum(:tax)
|
247
|
+
self.line_total_with_tax = self.children.sum(:line_total_with_tax)
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
self.save
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
def is_children_linked?
|
256
|
+
self.children_link == 1
|
257
|
+
end
|
258
|
+
|
259
|
+
def add_ext_cal(cal)
|
260
|
+
if self.extended_calculators.nil?
|
261
|
+
res = { local: [], quotation: [] }
|
262
|
+
else
|
263
|
+
res = YAML.load(self.extended_calculators)
|
264
|
+
end
|
265
|
+
|
266
|
+
case cal
|
267
|
+
when Hash
|
268
|
+
ac = ExtendedCalculator.instance_from_hash(cal)
|
269
|
+
when ExtendedCalculator
|
270
|
+
ac = cal
|
271
|
+
else
|
272
|
+
raise ExtendedCalculator::ExtendedCalculatorException, "Unsupported calculator type '#{cal.class}'"
|
273
|
+
end
|
274
|
+
|
275
|
+
ac.owner = :quotation_item
|
276
|
+
ac.owner_id = self.id if not self.new_record?
|
277
|
+
|
278
|
+
res[:local] << ac
|
279
|
+
|
280
|
+
self.extended_calculators = YAML.dump(res)
|
281
|
+
end
|
282
|
+
|
283
|
+
def update_ext_cal(ecid, opts = { })
|
284
|
+
if not self.extended_calculators.nil?
|
285
|
+
cal = YAML.load(self.extended_calculators)
|
286
|
+
cal[:local].each do |c|
|
287
|
+
if c.ecid == ecid
|
288
|
+
opts.each do |k,v|
|
289
|
+
c.send("#{k}=", v)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
cal[:quotation].each do |c|
|
295
|
+
if c.ecid == ecid
|
296
|
+
opts.each do |k,v|
|
297
|
+
c.send("#{k}=",v)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
self.extended_calculators = YAML.dump(cal)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def add_quotation_ext_cal(cal)
|
307
|
+
|
308
|
+
if self.extended_calculators.nil?
|
309
|
+
res = { local: [], quotation: [] }
|
310
|
+
else
|
311
|
+
res = YAML.load(self.extended_calculators)
|
312
|
+
end
|
313
|
+
|
314
|
+
case cal
|
315
|
+
when Hash
|
316
|
+
ac = ExtendedCalculator.instance_from_hash(cal)
|
317
|
+
when ExtendedCalculator
|
318
|
+
ac = cal
|
319
|
+
else
|
320
|
+
raise ExtendedCalculator::ExtendedCalculatorException, "Unsupported calculator type '#{cal.class}'"
|
321
|
+
end
|
322
|
+
|
323
|
+
res[:quotation] << ac
|
324
|
+
|
325
|
+
self.extended_calculators = YAML.dump(res)
|
326
|
+
|
327
|
+
end
|
328
|
+
|
329
|
+
def ext_cals
|
330
|
+
if self.extended_calculators.nil?
|
331
|
+
[]
|
332
|
+
else
|
333
|
+
YAML.load(self.extended_calculators)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def get_item_discount(input_field = nil)
|
338
|
+
if not_empty?(self.extended_calculators)
|
339
|
+
cal = YAML.load(self.extended_calculators)
|
340
|
+
found = nil
|
341
|
+
cal[:local].each do |c|
|
342
|
+
if c.is_a?(Smerp::Quotation::DiscountCalculator)
|
343
|
+
if not_empty?(input_field)
|
344
|
+
if c.input_field.to_sym == input_field.to_sym
|
345
|
+
found = c
|
346
|
+
break
|
347
|
+
end
|
348
|
+
else
|
349
|
+
found = c
|
350
|
+
break
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
found
|
356
|
+
else
|
357
|
+
nil
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def get_qoutation_discount(input_field = nil)
|
362
|
+
if not_empty?(self.extended_calculators)
|
363
|
+
cal = YAML.load(self.extended_calculators)
|
364
|
+
found = nil
|
365
|
+
cal[:quotation].each do |c|
|
366
|
+
if c.is_a?(Smerp::Quotation::DiscountCalculator)
|
367
|
+
if not_empty?(input_field)
|
368
|
+
if c.input_field.to_sym == input_field.to_sym
|
369
|
+
found = c
|
370
|
+
break
|
371
|
+
end
|
372
|
+
else
|
373
|
+
found = c
|
374
|
+
break
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
found
|
380
|
+
else
|
381
|
+
nil
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def get_item_tax
|
386
|
+
if not_empty?(self.extended_calculators)
|
387
|
+
cal = YAML.load(self.extended_calculators)
|
388
|
+
found = nil
|
389
|
+
cal[:local].each do |c|
|
390
|
+
if c.is_a?(Smerp::Quotation::TaxCalculator)
|
391
|
+
found = c
|
392
|
+
break
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
if found.nil?
|
397
|
+
cal[:quotation].each do |c|
|
398
|
+
if c.is_a?(Smerp::Quotation::TaxCalculator)
|
399
|
+
found = c
|
400
|
+
break
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
found
|
406
|
+
else
|
407
|
+
nil
|
408
|
+
end
|
409
|
+
|
410
|
+
end
|
411
|
+
|
412
|
+
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
require 'acts_as_tree'
|
3
|
+
|
4
|
+
module Smerp
|
5
|
+
module Quotation
|
6
|
+
|
7
|
+
module ArModel
|
8
|
+
class QuotationItemGroup < Ca::DataStore::Ar::Model
|
9
|
+
include ActsAsTree
|
10
|
+
|
11
|
+
acts_as_tree
|
12
|
+
|
13
|
+
has_many :quotation_items
|
14
|
+
|
15
|
+
belongs_to :quotation
|
16
|
+
|
17
|
+
after_save :update_parent
|
18
|
+
|
19
|
+
def update_parent
|
20
|
+
par = self.parent
|
21
|
+
if not par.nil?
|
22
|
+
par.group_total = par.children.sum(:group_total) + par.quotation_items.sum(:line_total)
|
23
|
+
par.group_discount = par.children.sum(:group_discount) + par.quotation_items.sum(:discount)
|
24
|
+
|
25
|
+
par.group_tax = par.children.sum(:group_tax) + par.quotation_items.sum(:tax)
|
26
|
+
|
27
|
+
par.save
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Smerp
|
4
|
+
module Quotation
|
5
|
+
module ArModel
|
6
|
+
|
7
|
+
class TaxCategory < Ca::DataStore::Ar::Model
|
8
|
+
|
9
|
+
validates_uniqueness_of :name
|
10
|
+
validates_uniqueness_of :display_code
|
11
|
+
|
12
|
+
belongs_to :extended_calculator
|
13
|
+
|
14
|
+
state_machine initial: :active do
|
15
|
+
|
16
|
+
event :inactivate do
|
17
|
+
transition :active => :inactive
|
18
|
+
end
|
19
|
+
|
20
|
+
event :activate do
|
21
|
+
transition :inactive => :active
|
22
|
+
end
|
23
|
+
|
24
|
+
event :deprecate do
|
25
|
+
transition :inactive => :deprecated
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Smerp
|
4
|
+
module Quotation
|
5
|
+
class DiscountCalculator
|
6
|
+
include ExtendedCalculator
|
7
|
+
include TR::CondUtils
|
8
|
+
|
9
|
+
include TeLogger::TeLogHelper
|
10
|
+
teLogger_tag :discountCal
|
11
|
+
|
12
|
+
DiscountedAmount = :discounted_amount
|
13
|
+
ValueAfterDiscount = :value_after_discount
|
14
|
+
|
15
|
+
def calculate(mdl)
|
16
|
+
|
17
|
+
srcVal = mdl.send(@input_field)
|
18
|
+
if not_empty?(srcVal)
|
19
|
+
|
20
|
+
srcVal = srcVal.to_f
|
21
|
+
|
22
|
+
res = { input: @input_field, input_value: srcVal }
|
23
|
+
case @params
|
24
|
+
when Smerp::Common::FinUtils::Percent
|
25
|
+
res[DiscountedAmount] = srcVal * @params.rep_value
|
26
|
+
when Smerp::Common::FinUtils::RawValue
|
27
|
+
res[DiscountedAmount] = @params.rep_value
|
28
|
+
else
|
29
|
+
res[DiscountedAmount] = @params.to_f
|
30
|
+
end
|
31
|
+
|
32
|
+
res[ValueAfterDiscount] = srcVal - res[DiscountedAmount]
|
33
|
+
|
34
|
+
if not_empty?(@output_field)
|
35
|
+
|
36
|
+
case @output_field
|
37
|
+
when Array
|
38
|
+
@output_field.each do |of|
|
39
|
+
of.each do |f, v|
|
40
|
+
mdl.send("#{f}=", res[v])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
when Hash
|
44
|
+
@output_field.each do |f,v|
|
45
|
+
mdl.send("#{f}=", res[v])
|
46
|
+
end
|
47
|
+
when Symbol
|
48
|
+
mdl.send("#{@output_field}=", res[DiscountedAmount])
|
49
|
+
end
|
50
|
+
|
51
|
+
res[:output] = @output_field
|
52
|
+
mdl.recalculate
|
53
|
+
end
|
54
|
+
|
55
|
+
@result = res
|
56
|
+
|
57
|
+
trigger_listener(:after_calculation, mdl)
|
58
|
+
|
59
|
+
teLogger.debug "Discount calculation log : #{res}"
|
60
|
+
|
61
|
+
@result
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Smerp
|
4
|
+
module Quotation
|
5
|
+
class RoundUpCalculator
|
6
|
+
include ExtendedCalculator
|
7
|
+
include TR::CondUtils
|
8
|
+
|
9
|
+
include TeLogger::TeLogHelper
|
10
|
+
teLogger_tag :roundUpCal
|
11
|
+
|
12
|
+
def calculate(mdl)
|
13
|
+
srcVal = mdl.send(@input_field)
|
14
|
+
if not_empty?(srcVal)
|
15
|
+
|
16
|
+
@result = srcVal.to_f.round_to_nearest(@params)
|
17
|
+
teLogger.debug "Rounding field '#{@input_field}' (#{srcVal}) to nearest #{@params} is #{@result.inspect}"
|
18
|
+
|
19
|
+
if not_empty?(@output_field)
|
20
|
+
mdl.send("#{@output_field}=", @result.rounded_value)
|
21
|
+
mdl.recalculate
|
22
|
+
end
|
23
|
+
|
24
|
+
trigger_listener(:after_calculation, mdl)
|
25
|
+
|
26
|
+
@result
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Smerp
|
4
|
+
module Quotation
|
5
|
+
class TaxCalculator
|
6
|
+
include ExtendedCalculator
|
7
|
+
include TR::CondUtils
|
8
|
+
|
9
|
+
include TeLogger::TeLogHelper
|
10
|
+
teLogger_tag :taxCal
|
11
|
+
|
12
|
+
attr_accessor :tax_category_id, :name, :code, :notes
|
13
|
+
|
14
|
+
TaxAmount = :tax_amount
|
15
|
+
ValueWithTax = :value_with_tax
|
16
|
+
|
17
|
+
def calculate(mdl)
|
18
|
+
|
19
|
+
srcVal = mdl.send(@input_field)
|
20
|
+
if not_empty?(srcVal)
|
21
|
+
|
22
|
+
srcVal = srcVal.to_f
|
23
|
+
|
24
|
+
res = { input: @input_field, input_value: srcVal }
|
25
|
+
case @params
|
26
|
+
when Smerp::Common::FinUtils::Percent
|
27
|
+
res[TaxAmount] = srcVal * @params.rep_value
|
28
|
+
when Smerp::Common::FinUtils::RawValue
|
29
|
+
res[TaxAmount] = @params.rep_value
|
30
|
+
else
|
31
|
+
res[TaxAmount] = @params.to_f
|
32
|
+
end
|
33
|
+
|
34
|
+
res[ValueWithTax] = srcVal + res[TaxAmount]
|
35
|
+
|
36
|
+
if not_empty?(@output_field)
|
37
|
+
|
38
|
+
case @output_field
|
39
|
+
when Array
|
40
|
+
@output_field.each do |of|
|
41
|
+
of.each do |f, v|
|
42
|
+
mdl.send("#{f}=", res[v])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
when Hash
|
47
|
+
@output_field.each do |f,v|
|
48
|
+
mdl.send("#{f}=", res[v])
|
49
|
+
end
|
50
|
+
|
51
|
+
when Symbol
|
52
|
+
mdl.send("#{@output_field}=", res[ValueWithTax])
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
res[:output] = @output_field
|
57
|
+
end
|
58
|
+
|
59
|
+
teLogger.debug "Tax calculation log : #{res}"
|
60
|
+
|
61
|
+
res[:tax_category_id] = @tax_category_id
|
62
|
+
res[:name] = @name
|
63
|
+
res[:code] = @code
|
64
|
+
res[:notes] = @notes
|
65
|
+
|
66
|
+
@result = res
|
67
|
+
|
68
|
+
trigger_listener(:after_calculation, mdl)
|
69
|
+
|
70
|
+
@result
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|