smerp-quotation 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f8b69d99e96beaa0d81e513065d9671cfafa11b57c91ff1d5e1ba782fe380c35
|
4
|
+
data.tar.gz: b85cba78f3e87c7edb171dc3da9120613b1464ee94f9fe4c6e87612cd1137052
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f9e49a67d5fabd72016b5181cba6882965a94cf96a5a32df959ddd2422be90c0a5e1ed5ad352342b204cec9878d3731eefff8330aee3ced28140e566a7e39234
|
7
|
+
data.tar.gz: '081ba3ccd3a13a92f0e4f2d51646454704e2c2b51bc4f9f9001ebc26ac676720351083e4c23d24b67859fc886d13a0321d3733ef1f77a3dbeacdd43cd934a523'
|
data/.rspec
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in smerp-quotation.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem "rake", "~> 13.0"
|
9
|
+
|
10
|
+
gem "rspec", "~> 3.0"
|
11
|
+
|
12
|
+
#gem 'smerp-common', git: 'smerp-common', branch: 'master'
|
13
|
+
#gem 'ca-data_store', git: 'ca-data_store', branch: 'master'
|
14
|
+
#gem 'ca-data_store-ar', git: 'ca-data_store-ar', branch: 'master'
|
15
|
+
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
smerp-quotation (0.1.0)
|
5
|
+
acts_as_list
|
6
|
+
acts_as_tree
|
7
|
+
ca-data_store
|
8
|
+
ca-data_store-ar
|
9
|
+
state_machines-activerecord
|
10
|
+
teLogger
|
11
|
+
toolrack
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
actionpack (7.0.3.1)
|
17
|
+
actionview (= 7.0.3.1)
|
18
|
+
activesupport (= 7.0.3.1)
|
19
|
+
rack (~> 2.0, >= 2.2.0)
|
20
|
+
rack-test (>= 0.6.3)
|
21
|
+
rails-dom-testing (~> 2.0)
|
22
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
23
|
+
actionview (7.0.3.1)
|
24
|
+
activesupport (= 7.0.3.1)
|
25
|
+
builder (~> 3.1)
|
26
|
+
erubi (~> 1.4)
|
27
|
+
rails-dom-testing (~> 2.0)
|
28
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
29
|
+
activemodel (7.0.3.1)
|
30
|
+
activesupport (= 7.0.3.1)
|
31
|
+
activerecord (7.0.3.1)
|
32
|
+
activemodel (= 7.0.3.1)
|
33
|
+
activesupport (= 7.0.3.1)
|
34
|
+
activesupport (7.0.3.1)
|
35
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
36
|
+
i18n (>= 1.6, < 2)
|
37
|
+
minitest (>= 5.1)
|
38
|
+
tzinfo (~> 2.0)
|
39
|
+
acts_as_list (1.0.4)
|
40
|
+
activerecord (>= 4.2)
|
41
|
+
acts_as_tree (2.9.1)
|
42
|
+
activerecord (>= 3.0.0)
|
43
|
+
base58 (0.2.3)
|
44
|
+
builder (3.2.4)
|
45
|
+
ca-data_store (0.1.0)
|
46
|
+
teLogger
|
47
|
+
toolrack
|
48
|
+
ca-data_store-ar (0.1.0)
|
49
|
+
activerecord
|
50
|
+
activesupport
|
51
|
+
ca-data_store
|
52
|
+
standalone_migrations
|
53
|
+
teLogger
|
54
|
+
toolrack
|
55
|
+
concurrent-ruby (1.1.10)
|
56
|
+
crass (1.0.6)
|
57
|
+
devops_assist (0.3.0)
|
58
|
+
git_cli
|
59
|
+
git_cli_prompt
|
60
|
+
gvcs
|
61
|
+
teLogger
|
62
|
+
toolrack
|
63
|
+
tty-prompt
|
64
|
+
diff-lcs (1.5.0)
|
65
|
+
erubi (1.11.0)
|
66
|
+
git_cli (0.10.0)
|
67
|
+
gvcs
|
68
|
+
ptools (~> 1.4.0)
|
69
|
+
teLogger
|
70
|
+
toolrack
|
71
|
+
git_cli_prompt (0.3.1)
|
72
|
+
teLogger
|
73
|
+
toolrack
|
74
|
+
tty-prompt
|
75
|
+
gvcs (0.1.0)
|
76
|
+
i18n (1.12.0)
|
77
|
+
concurrent-ruby (~> 1.0)
|
78
|
+
loofah (2.19.0)
|
79
|
+
crass (~> 1.0.2)
|
80
|
+
nokogiri (>= 1.5.9)
|
81
|
+
method_source (1.0.0)
|
82
|
+
minitest (5.16.3)
|
83
|
+
nokogiri (1.13.8-x86_64-linux)
|
84
|
+
racc (~> 1.4)
|
85
|
+
pastel (0.8.0)
|
86
|
+
tty-color (~> 0.5)
|
87
|
+
ptools (1.4.2)
|
88
|
+
racc (1.6.0)
|
89
|
+
rack (2.2.4)
|
90
|
+
rack-test (2.0.2)
|
91
|
+
rack (>= 1.3)
|
92
|
+
rails-dom-testing (2.0.3)
|
93
|
+
activesupport (>= 4.2.0)
|
94
|
+
nokogiri (>= 1.6)
|
95
|
+
rails-html-sanitizer (1.4.3)
|
96
|
+
loofah (~> 2.3)
|
97
|
+
railties (7.0.3.1)
|
98
|
+
actionpack (= 7.0.3.1)
|
99
|
+
activesupport (= 7.0.3.1)
|
100
|
+
method_source
|
101
|
+
rake (>= 12.2)
|
102
|
+
thor (~> 1.0)
|
103
|
+
zeitwerk (~> 2.5)
|
104
|
+
rake (13.0.6)
|
105
|
+
rspec (3.11.0)
|
106
|
+
rspec-core (~> 3.11.0)
|
107
|
+
rspec-expectations (~> 3.11.0)
|
108
|
+
rspec-mocks (~> 3.11.0)
|
109
|
+
rspec-core (3.11.0)
|
110
|
+
rspec-support (~> 3.11.0)
|
111
|
+
rspec-expectations (3.11.0)
|
112
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
113
|
+
rspec-support (~> 3.11.0)
|
114
|
+
rspec-mocks (3.11.1)
|
115
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
116
|
+
rspec-support (~> 3.11.0)
|
117
|
+
rspec-support (3.11.0)
|
118
|
+
sqlite3 (1.4.4)
|
119
|
+
standalone_migrations (7.1.0)
|
120
|
+
activerecord (>= 4.2.7, < 7.1.0, != 5.2.3.rc1, != 5.2.3)
|
121
|
+
railties (>= 4.2.7, < 7.1.0, != 5.2.3.rc1, != 5.2.3)
|
122
|
+
rake (>= 10.0)
|
123
|
+
state_machines (0.5.0)
|
124
|
+
state_machines-activemodel (0.8.0)
|
125
|
+
activemodel (>= 5.1)
|
126
|
+
state_machines (>= 0.5.0)
|
127
|
+
state_machines-activerecord (0.8.0)
|
128
|
+
activerecord (>= 5.1)
|
129
|
+
state_machines-activemodel (>= 0.8.0)
|
130
|
+
teLogger (0.2.0)
|
131
|
+
thor (1.2.1)
|
132
|
+
toolrack (0.19.1)
|
133
|
+
base58
|
134
|
+
tty-color (0.6.0)
|
135
|
+
tty-cursor (0.7.1)
|
136
|
+
tty-prompt (0.23.1)
|
137
|
+
pastel (~> 0.8)
|
138
|
+
tty-reader (~> 0.8)
|
139
|
+
tty-reader (0.9.0)
|
140
|
+
tty-cursor (~> 0.7)
|
141
|
+
tty-screen (~> 0.8)
|
142
|
+
wisper (~> 2.0)
|
143
|
+
tty-screen (0.8.1)
|
144
|
+
tzinfo (2.0.5)
|
145
|
+
concurrent-ruby (~> 1.0)
|
146
|
+
wisper (2.0.1)
|
147
|
+
zeitwerk (2.6.0)
|
148
|
+
|
149
|
+
PLATFORMS
|
150
|
+
x86_64-linux
|
151
|
+
|
152
|
+
DEPENDENCIES
|
153
|
+
devops_assist
|
154
|
+
rake (~> 13.0)
|
155
|
+
rspec (~> 3.0)
|
156
|
+
smerp-quotation!
|
157
|
+
sqlite3
|
158
|
+
|
159
|
+
BUNDLED WITH
|
160
|
+
2.2.28
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Smerp::Quotation
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/smerp/quotation`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'smerp-quotation'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install smerp-quotation
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/smerp-quotation.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "smerp/quotation"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
Ca::DataStore::Ar.connect_database
|
11
|
+
Ca::DataStore::Ar.show_log
|
12
|
+
Ca::DataStore::Ar.load_model(File.join(File.dirname(__FILE__),"..","lib","smerp","quotation","ar_model"))
|
13
|
+
|
14
|
+
include Smerp::Quotation
|
15
|
+
include Smerp::Quotation::ArModel
|
16
|
+
|
17
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
18
|
+
# require "pry"
|
19
|
+
# Pry.start
|
20
|
+
|
21
|
+
require "irb"
|
22
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/config/database.yml
ADDED
data/db/config.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
class CreateQuotations < ActiveRecord::Migration[7.0]
|
3
|
+
def change
|
4
|
+
create_table :quotations do |t|
|
5
|
+
t.string :qid
|
6
|
+
|
7
|
+
t.string :name
|
8
|
+
t.text :address
|
9
|
+
t.string :attention_to
|
10
|
+
|
11
|
+
t.text :notes
|
12
|
+
t.string :state, default: 'open'
|
13
|
+
|
14
|
+
# config specific to this quotation
|
15
|
+
t.text :sqconfig
|
16
|
+
|
17
|
+
t.date :qdate
|
18
|
+
|
19
|
+
t.datetime :released_timestamp
|
20
|
+
|
21
|
+
t.decimal :total, default: 0.0
|
22
|
+
|
23
|
+
t.decimal :total_discount, default: 0.0
|
24
|
+
t.decimal :total_after_discount, default: 0.0
|
25
|
+
|
26
|
+
t.decimal :total_tax, default: 0.0
|
27
|
+
t.decimal :total_with_tax, default: 0.0
|
28
|
+
|
29
|
+
# standard calculator across all items
|
30
|
+
# such as discount, tax or rounding
|
31
|
+
t.text :extended_calculators
|
32
|
+
|
33
|
+
t.text :private_extended_calculators
|
34
|
+
|
35
|
+
t.text :smerp_domain_info
|
36
|
+
|
37
|
+
t.timestamps
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
class CreateQuotationItems < ActiveRecord::Migration[7.0]
|
3
|
+
def change
|
4
|
+
create_table :quotation_items do |t|
|
5
|
+
|
6
|
+
# group by quotation
|
7
|
+
t.string :quotation_id
|
8
|
+
|
9
|
+
# tree structure
|
10
|
+
t.string :parent_id
|
11
|
+
|
12
|
+
# list structure
|
13
|
+
t.integer :position
|
14
|
+
|
15
|
+
# Item belongs in which group
|
16
|
+
t.string :quotation_item_group_id
|
17
|
+
|
18
|
+
# link to source of the quotation (polymorphic)
|
19
|
+
# i.e. product or resource owner
|
20
|
+
t.string :quotable_id
|
21
|
+
t.string :quotable_type
|
22
|
+
|
23
|
+
t.string :name
|
24
|
+
t.text :notes
|
25
|
+
|
26
|
+
# flag to tell the model if update of
|
27
|
+
# parent field is required or not
|
28
|
+
# This allow manual intevention of user
|
29
|
+
# based details item being entered
|
30
|
+
t.integer :children_link, limit: 1, default: 1
|
31
|
+
|
32
|
+
# show this item in final quotation or not
|
33
|
+
#t.integer :show, limit: 1, default: 0
|
34
|
+
|
35
|
+
# value stored for display
|
36
|
+
t.decimal :quantity, default: 0.0
|
37
|
+
# value stored for display
|
38
|
+
t.string :unit, default: "Unit(s)"
|
39
|
+
# value stored for display
|
40
|
+
# It is also the locked in value from other table such as product
|
41
|
+
t.decimal :unit_price, default: 0.0, precision: 25, scale: 2
|
42
|
+
|
43
|
+
t.string :price_currency
|
44
|
+
|
45
|
+
# value stored for display
|
46
|
+
t.decimal :line_total, default: 0.0, precision: 25, scale: 2
|
47
|
+
|
48
|
+
t.decimal :discount, precision: 25, scale: 2, default: 0.0
|
49
|
+
# yaml hash structure indicate the discount is
|
50
|
+
# 1. Actual value in currency
|
51
|
+
# 2. Percentage from the total
|
52
|
+
# 3. Rounding on discounted amount
|
53
|
+
#t.text :discount_calculation
|
54
|
+
t.decimal :line_total_after_discount, precision: 25, scale: 2, default: 0.0
|
55
|
+
|
56
|
+
t.decimal :tax, default: 0.0
|
57
|
+
# yaml hash structure indicate the tax code
|
58
|
+
# and its detail: exampted, x% etc
|
59
|
+
#t.text :tax_calculation
|
60
|
+
t.decimal :line_total_with_tax, default: 0.0, precision: 25, scale: 2
|
61
|
+
|
62
|
+
t.text :extended_calculators
|
63
|
+
|
64
|
+
t.text :smerp_domain_info
|
65
|
+
|
66
|
+
t.timestamps
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
class CreateQuotationItemGroups < ActiveRecord::Migration[7.0]
|
3
|
+
def change
|
4
|
+
create_table :quotation_item_groups do |t|
|
5
|
+
|
6
|
+
t.string :name
|
7
|
+
|
8
|
+
t.string :quotation_id
|
9
|
+
|
10
|
+
# tree structure
|
11
|
+
t.string :parent_id
|
12
|
+
|
13
|
+
# list structure
|
14
|
+
t.integer :position
|
15
|
+
|
16
|
+
# show this group name in quotation to customer?
|
17
|
+
#t.integer :show_name, limit: 1, default: 0
|
18
|
+
|
19
|
+
# show this group total in quotation to customer?
|
20
|
+
#t.integer :show_total, limit: 1, default: 0
|
21
|
+
|
22
|
+
t.decimal :group_total, default: 0.0, precision: 25, scale: 2
|
23
|
+
|
24
|
+
t.decimal :group_discount, default: 0.0, precision: 25, scale: 2
|
25
|
+
|
26
|
+
t.decimal :group_tax, default: 0.0, precision: 25, scale: 2
|
27
|
+
|
28
|
+
t.text :smerp_domain_info
|
29
|
+
|
30
|
+
t.timestamps
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
class CreateTaxCategory < ActiveRecord::Migration[7.0]
|
3
|
+
def change
|
4
|
+
create_table :tax_category do |t|
|
5
|
+
|
6
|
+
t.string :name
|
7
|
+
|
8
|
+
t.string :display_code
|
9
|
+
|
10
|
+
t.decimal :tax, default: 0.0
|
11
|
+
t.text :formula
|
12
|
+
t.string :state, default: 'active'
|
13
|
+
|
14
|
+
t.text :smerp_domain_info
|
15
|
+
|
16
|
+
t.timestamps
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Smerp
|
4
|
+
module Quotation
|
5
|
+
|
6
|
+
module ArModel
|
7
|
+
class Quotation < Ca::DataStore::Ar::Model
|
8
|
+
include TR::CondUtils
|
9
|
+
|
10
|
+
include TeLogger::TeLogHelper
|
11
|
+
teLogger_tag :quotMdl
|
12
|
+
|
13
|
+
has_many :quotation_items, dependent: :destroy
|
14
|
+
|
15
|
+
belongs_to :customer, polymorphic: true
|
16
|
+
|
17
|
+
has_many :quotation_item_groups, dependent: :destroy
|
18
|
+
|
19
|
+
validates_uniqueness_of :qid, allow_blank: true, case_sensitive: false
|
20
|
+
|
21
|
+
# polymorphic on model of customer/vendor
|
22
|
+
# has_many :quotations, as: :customer
|
23
|
+
|
24
|
+
after_initialize :set_date
|
25
|
+
def set_date
|
26
|
+
self.qdate = Time.now.utc if self.new_record?
|
27
|
+
end
|
28
|
+
|
29
|
+
before_save :trigger_extended_calculations
|
30
|
+
|
31
|
+
state_machine initial: :open do
|
32
|
+
|
33
|
+
after_transition :open => :released do |q,st|
|
34
|
+
q.released_timestamp = Time.now
|
35
|
+
end
|
36
|
+
|
37
|
+
event :release do
|
38
|
+
transition :open => :released
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_ext_cal(cal)
|
44
|
+
if self.extended_calculators.nil?
|
45
|
+
res = []
|
46
|
+
else
|
47
|
+
res = YAML.load(self.extended_calculators)
|
48
|
+
end
|
49
|
+
|
50
|
+
cal.owner = :quotation
|
51
|
+
cal.owner_id = self.id if not self.new_record?
|
52
|
+
|
53
|
+
res << cal
|
54
|
+
|
55
|
+
self.extended_calculators = YAML.dump(res)
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_priv_ext_cal(cal)
|
59
|
+
if self.private_extended_calculators.nil?
|
60
|
+
res = []
|
61
|
+
else
|
62
|
+
res = YAML.load(self.private_extended_calculators)
|
63
|
+
end
|
64
|
+
|
65
|
+
res << cal
|
66
|
+
|
67
|
+
self.private_extended_calculators = YAML.dump(res)
|
68
|
+
end
|
69
|
+
|
70
|
+
def inheritable_extended_calculators
|
71
|
+
if not_empty?(self.extended_calculators)
|
72
|
+
YAML.load(self.extended_calculators)
|
73
|
+
else
|
74
|
+
[]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def trigger_extended_calculations
|
79
|
+
|
80
|
+
privExtCal = self.private_extended_calculators
|
81
|
+
if not_empty?(privExtCal)
|
82
|
+
|
83
|
+
privExtCal = YAML.load(privExtCal)
|
84
|
+
|
85
|
+
cals = []
|
86
|
+
privExtCal.each do |ec|
|
87
|
+
|
88
|
+
if self.send("#{ec.input_field}_changed?")
|
89
|
+
teLogger.debug "Executing extended calculator : #{ec.inspect}"
|
90
|
+
ec.calculate(self)
|
91
|
+
end
|
92
|
+
|
93
|
+
cals << ec.for_storage
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
self.private_extended_calculators = YAML.dump(cals)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
def recalculate
|
103
|
+
# call by calculator after processing
|
104
|
+
end
|
105
|
+
|
106
|
+
end # class Quotation
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|