purchase 0.0.2 → 0.0.3
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.
- data/features/purchase_committees.feature +125 -10
- data/features/purchase_emissions.feature +24 -7
- data/features/step_definitions/committee_steps.rb +93 -0
- data/lib/purchase/carbon_model.rb +108 -31
- data/lib/purchase/characterization.rb +6 -7
- data/lib/purchase/data.rb +7 -4
- data/lib/test_support/db/schema.rb +3 -3
- data/lib/test_support/purchase_record.rb +6 -0
- metadata +41 -24
@@ -1,13 +1,128 @@
|
|
1
1
|
Feature: Purchase Committee Calculations
|
2
2
|
The purchase model should generate correct committee calculations
|
3
3
|
|
4
|
-
Scenario Outline:
|
5
|
-
Given a purchase
|
6
|
-
And
|
7
|
-
And
|
8
|
-
When
|
9
|
-
Then the
|
10
|
-
|
11
|
-
|
12
|
-
|
|
13
|
-
|
|
4
|
+
Scenario Outline: Adjusted cost committee from cost and date
|
5
|
+
Given a purchase emitter
|
6
|
+
And a characteristic "cost" of "<cost>"
|
7
|
+
And characteristic "date" of "<date>"
|
8
|
+
When the "adjusted_cost" committee is calculated
|
9
|
+
Then the committee should have used quorum "from cost and date"
|
10
|
+
And the conclusion of the committee should be "<adjusted_cost>"
|
11
|
+
Examples:
|
12
|
+
| cost | date | adjusted_cost |
|
13
|
+
| 831.23 | 2010-08-01 | 831.23 |
|
14
|
+
| 11.00 | 2005-07-14 | 11.0 |
|
15
|
+
|
16
|
+
Scenario Outline: Adjusted cost committee from purchase amount and date
|
17
|
+
Given a purchase emitter
|
18
|
+
And a characteristic "purchase_amount" of "<amount>"
|
19
|
+
And characteristic "date" of "<date>"
|
20
|
+
When the "adjusted_cost" committee is calculated
|
21
|
+
Then the committee should have used quorum "from purchase amount and date"
|
22
|
+
And the conclusion of the committee should be "<adjusted_cost>"
|
23
|
+
Examples:
|
24
|
+
| amount | date | adjusted_cost |
|
25
|
+
| 831.23 | 2010-08-01 | 748.107 |
|
26
|
+
| 11.00 | 2005-07-14 | 9.9 |
|
27
|
+
|
28
|
+
Scenario Outline: Merchant category committee from merchant
|
29
|
+
Given a purchase emitter
|
30
|
+
And a characteristic "merchant.id" of "<id>"
|
31
|
+
When the "merchant_category" committee is calculated
|
32
|
+
Then the conclusion of the committee should have "mcc" of "<mcc>"
|
33
|
+
Examples:
|
34
|
+
| id | mcc |
|
35
|
+
| 1 | 5111 |
|
36
|
+
| 2 | 5732 |
|
37
|
+
|
38
|
+
Scenario Outline: Industry shares committee
|
39
|
+
Given a purchase emitter
|
40
|
+
And a characteristic "merchant_category.mcc" of "<mcc>"
|
41
|
+
When the "industry_shares" committee is calculated
|
42
|
+
Then the conclusion of the committee should have a record identified with "naics_code" of "<naics>" and having "ratio" of "<ratio>"
|
43
|
+
Examples:
|
44
|
+
| mcc | naics | ratio |
|
45
|
+
| 5111 | 45321 | 1.0 |
|
46
|
+
| 5732 | 443112 | 1.0 |
|
47
|
+
| 5172 | 32411 | 0.8 |
|
48
|
+
| 5172 | 324121 | 0.05 |
|
49
|
+
| 5172 | 324122 | 0.05 |
|
50
|
+
| 5172 | 324191 | 0.05 |
|
51
|
+
| 5172 | 324199 | 0.05 |
|
52
|
+
|
53
|
+
Scenario Outline: Product line shares committee
|
54
|
+
Given a purchase emitter
|
55
|
+
And a characteristic "merchant_category.mcc" of "<mcc>"
|
56
|
+
When the "industry_shares" committee is calculated
|
57
|
+
And the "product_line_shares" committee is calculated
|
58
|
+
Then the conclusion of the committee should include a key of <ps_code> and value <ratio>
|
59
|
+
Examples:
|
60
|
+
| mcc | ps_code | ratio |
|
61
|
+
| 5111 | 20370 | 0.6 |
|
62
|
+
| 5732 | 20375 | 0.5 |
|
63
|
+
| 5172 | 30860 | 0.32 |
|
64
|
+
| 5172 | 30861 | 0.0225 |
|
65
|
+
| 5172 | 30862 | 0.0175 |
|
66
|
+
| 5172 | 30863 | 0.018 |
|
67
|
+
| 5172 | 30864 | 0.019 |
|
68
|
+
|
69
|
+
Scenario Outline: Sector shares committee from industry shares
|
70
|
+
Given a purchase emitter
|
71
|
+
And a characteristic "merchant_category.mcc" of "<mcc>"
|
72
|
+
When the "industry_shares" committee is calculated
|
73
|
+
And the "sector_shares" committee is calculated
|
74
|
+
Then the conclusion of the committee should include a key of "<io_code>" and subvalue "share" of "<share>" and subvalue "emission_factor" of "<emission_factor>"
|
75
|
+
Examples:
|
76
|
+
| mcc | io_code | emission_factor | share |
|
77
|
+
| 5111 | | | |
|
78
|
+
| 5732 | | | |
|
79
|
+
| 5172 | 324110 | 2.0 | 0.8 |
|
80
|
+
| 5172 | 324121 | 1.3 | 0.05 |
|
81
|
+
| 5172 | 324122 | 0.9 | 0.05 |
|
82
|
+
| 5172 | 324191 | 0.2 | 0.05 |
|
83
|
+
| 5172 | 324199 | 1.2 | 0.05 |
|
84
|
+
|
85
|
+
Scenario Outline: Sector shares committee from industry shares and product line shares
|
86
|
+
Given a purchase emitter
|
87
|
+
And a characteristic "merchant_category.mcc" of "<mcc>"
|
88
|
+
When the "industry_shares" committee is calculated
|
89
|
+
And the "product_line_shares" committee is calculated
|
90
|
+
And the "sector_shares" committee is calculated
|
91
|
+
Then the conclusion of the committee should include a key of "<io_code>" and subvalue "share" of "<share>" and subvalue "emission_factor" of "<emission_factor>"
|
92
|
+
Examples:
|
93
|
+
| mcc | io_code | emission_factor | share |
|
94
|
+
| 5111 | 334111 | 1.3 | 0.24 |
|
95
|
+
| 5111 | 33411A | 0.5 | 0.18 |
|
96
|
+
| 5111 | 511200 | 1.0 | 0.18 |
|
97
|
+
| 5111 | 339940 | 1.1 | 0.2 |
|
98
|
+
| 5111 | 322230 | 1.4 | 0.2 |
|
99
|
+
| 5732 | 33411A | 0.5 | 0.5 |
|
100
|
+
| 5732 | 334300 | 1.2 | 0.25 |
|
101
|
+
| 5732 | 334210 | 1.6 | 0.2 |
|
102
|
+
| 5172 | 324110 | 2.0 | 0.256 |
|
103
|
+
| 5172 | 324121 | 1.3 | 0.05 |
|
104
|
+
| 5172 | 324122 | 0.9 | 0.05 |
|
105
|
+
| 5172 | 324191 | 0.2 | 0.32 |
|
106
|
+
| 5172 | 324199 | 1.2 | 0.05 |
|
107
|
+
| 8225 | 722000 | 0.8 | 0.15 |
|
108
|
+
|
109
|
+
Scenario Outline: Emission factor from sector shares
|
110
|
+
Given a purchase emitter
|
111
|
+
And a characteristic "merchant_category.mcc" of "<mcc>"
|
112
|
+
When the "industry_shares" committee is calculated
|
113
|
+
And the "product_line_shares" committee is calculated
|
114
|
+
And the "sector_shares" committee is calculated
|
115
|
+
And the "emission_factor" committee is calculated
|
116
|
+
Then the conclusion of the committee should be "<emission_factor>"
|
117
|
+
Examples:
|
118
|
+
| mcc | emission_factor |
|
119
|
+
| 5111 | 1.082 |
|
120
|
+
| 5732 | 0.87 |
|
121
|
+
| 5172 | 0.799205 |
|
122
|
+
| 8225 | 0.12 |
|
123
|
+
|
124
|
+
Scenario Outline: Emission factor from default
|
125
|
+
Given a purchase emitter
|
126
|
+
And a characteristic "merchant_category.mcc" of "<mcc>"
|
127
|
+
When the "emission_factor" committee is calculated
|
128
|
+
Then the conclusion of the committee should be "100"
|
@@ -1,13 +1,30 @@
|
|
1
1
|
Feature: Purchase Emissions Calculations
|
2
2
|
The purchase model should generate correct emission calculations
|
3
|
-
|
4
|
-
Scenario Outline:
|
5
|
-
Given a purchase has "
|
6
|
-
And it has "
|
3
|
+
|
4
|
+
Scenario Outline: Calculations for a merchant
|
5
|
+
Given a purchase has "merchant.id" of "<id>"
|
6
|
+
And it has "cost" of "<cost>"
|
7
7
|
And it has "date" of "<date>"
|
8
8
|
When emissions are calculated
|
9
9
|
Then the emission value should be within 1 kgs of <emission>
|
10
10
|
Examples:
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
| id | cost | date | emission |
|
12
|
+
| 1 | 100.00 | 2010-07-28 | 108.2 |
|
13
|
+
| 2 | 100.00 | 2010-07-28 | 87.0 |
|
14
|
+
| 3 | 100.00 | 2010-07-28 | 80.0 |
|
15
|
+
| 4 | 100.00 | 2010-07-28 | 121.0 |
|
16
|
+
| 5 | 100.00 | 2010-07-28 | 79.9205 |
|
17
|
+
|
18
|
+
Scenario Outline: Calculations for a merchant category
|
19
|
+
Given a purchase has "merchant_category.mcc" of "<mcc>"
|
20
|
+
And it has "cost" of "<cost>"
|
21
|
+
And it has "date" of "<date>"
|
22
|
+
When emissions are calculated
|
23
|
+
Then the emission value should be within 1 kgs of <emission>
|
24
|
+
Examples:
|
25
|
+
| mcc | cost | date | emission |
|
26
|
+
| 5111 | 100.00 | 2010-07-28 | 108.2 |
|
27
|
+
| 5732 | 100.00 | 2010-07-28 | 87.0 |
|
28
|
+
| 5812 | 100.00 | 2010-07-28 | 80.0 |
|
29
|
+
| 3504 | 100.00 | 2010-07-28 | 121.0 |
|
30
|
+
| 5172 | 100.00 | 2010-07-28 | 79.9205 |
|
@@ -0,0 +1,93 @@
|
|
1
|
+
def coerce_value(value)
|
2
|
+
if value =~ /\d+\.\d+/
|
3
|
+
value.to_f
|
4
|
+
elsif value =~ /^\d+$/
|
5
|
+
value.to_i
|
6
|
+
else
|
7
|
+
value
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def compare_values(a, b)
|
12
|
+
if b =~ /\d+\.\d+/
|
13
|
+
b = b.to_f
|
14
|
+
a.should be_close(b, 0.00001)
|
15
|
+
elsif b =~ /^\d+$/
|
16
|
+
b = b.to_i
|
17
|
+
a.should == b
|
18
|
+
else
|
19
|
+
a.should == b
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Given /^a purchase emitter$/ do
|
24
|
+
@activity = PurchaseRecord
|
25
|
+
end
|
26
|
+
|
27
|
+
Given /^(a )?characteristic "(.*)" of "(.*)"$/ do |_, name, value|
|
28
|
+
@characteristics ||= {}
|
29
|
+
|
30
|
+
if name =~ /\./
|
31
|
+
model_name, attribute = name.split /\./
|
32
|
+
model = model_name.singularize.camelize.constantize
|
33
|
+
value = model.send "find_by_#{attribute}", value
|
34
|
+
@characteristics[model_name.to_sym] = value
|
35
|
+
else
|
36
|
+
value = coerce_value(value)
|
37
|
+
@characteristics[name.to_sym] = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
When /^the "(.*)" committee is calculated$/ do |committee_name|
|
42
|
+
@decision ||= @activity.decisions[:emission]
|
43
|
+
@committee = @decision.committees.find { |c| c.name.to_s == committee_name }
|
44
|
+
@report = @committee.report(@characteristics, [])
|
45
|
+
@characteristics[committee_name.to_sym] = @report.conclusion
|
46
|
+
end
|
47
|
+
|
48
|
+
Then /^the committee should have used quorum "(.*)"$/ do |quorum|
|
49
|
+
@report.quorum.name.should == quorum
|
50
|
+
end
|
51
|
+
|
52
|
+
Then /^the conclusion of the committee should be "(.+)"$/ do |conclusion|
|
53
|
+
compare_values(@report.conclusion, conclusion)
|
54
|
+
end
|
55
|
+
|
56
|
+
Then /^the conclusion of the committee should include a key of (.*) and value (.*)$/ do |key, value|
|
57
|
+
if key.present?
|
58
|
+
@report.conclusion.keys.map(&:to_s).should include(key)
|
59
|
+
else
|
60
|
+
@report.conclusion.keys.map(&:to_s).should be_empty
|
61
|
+
end
|
62
|
+
|
63
|
+
if value.present?
|
64
|
+
@report.conclusion.each do |k, v|
|
65
|
+
@report.conclusion[k.to_s] == v
|
66
|
+
end
|
67
|
+
compare_values(@report.conclusion[key.to_s], value)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Then /^the conclusion of the committee should have "(.*)" of "(.*)"$/ do |attribute, value|
|
72
|
+
report_value = coerce_value @report.conclusion.send(attribute)
|
73
|
+
report_value.should == coerce_value(value)
|
74
|
+
end
|
75
|
+
|
76
|
+
Then /^the conclusion of the committee should have a record identified with "(.*)" of "(.*)" and having "(.*)" of "(.*)"$/ do |id_field, id, field, value|
|
77
|
+
id_field = id_field.to_sym
|
78
|
+
records = @report.conclusion
|
79
|
+
record = records.send("find_by_#{id_field}", id)
|
80
|
+
coerce_value(record.send(field)).should == coerce_value(value)
|
81
|
+
end
|
82
|
+
|
83
|
+
Then /^the conclusion of the committee should include a key of "(.*)" and subvalue "(.*)" of "(.*)" and subvalue "(.*)" of "(.*)"$/ do |key, subkey1, subvalue1, subkey2, subvalue2|
|
84
|
+
if key.present?
|
85
|
+
@report.conclusion.keys.map(&:to_s).should include(key)
|
86
|
+
actual_subvalue1 = coerce_value(@report.conclusion[key.to_s][subkey1.to_sym].to_s)
|
87
|
+
compare_values(actual_subvalue1, subvalue1)
|
88
|
+
actual_subvalue2 = coerce_value(@report.conclusion[key.to_s][subkey2.to_sym].to_s)
|
89
|
+
compare_values(actual_subvalue2, subvalue2)
|
90
|
+
else
|
91
|
+
@report.conclusion.keys.map(&:to_s).should be_empty
|
92
|
+
end
|
93
|
+
end
|
@@ -4,67 +4,144 @@ require 'timeframe'
|
|
4
4
|
module BrighterPlanet
|
5
5
|
module Purchase
|
6
6
|
module CarbonModel
|
7
|
+
class MissingSectorForProductLineSector < Exception; end
|
8
|
+
class MissingEmissionFactor < Exception; end
|
9
|
+
|
7
10
|
def self.included(base)
|
8
11
|
base.extend ::Leap::Subject
|
9
12
|
base.extend FastTimestamp
|
10
13
|
base.decide :emission, :with => :characteristics do
|
11
|
-
committee :emission do
|
12
|
-
|
14
|
+
committee :emission do
|
15
|
+
quorum 'from emissions factor and adjusted cost', :needs => [:emission_factor, :adjusted_cost] do |characteristics|
|
13
16
|
# lbs CO2e / 2002 US $ 2002 US $
|
14
|
-
characteristics[:emission_factor] *
|
17
|
+
characteristics[:emission_factor] * characteristics[:adjusted_cost]
|
15
18
|
end
|
16
19
|
|
17
|
-
|
20
|
+
quorum 'default' do
|
18
21
|
raise "The purchase's default emission quorum should never be called"
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
22
|
-
committee :emission_factor do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
committee :emission_factor do
|
26
|
+
quorum 'from sector_shares', :needs => [:sector_shares] do |characteristics|
|
27
|
+
characteristics[:sector_shares].inject(0) do |sum, (io_code, data)|
|
28
|
+
if data[:emission_factor].nil?
|
29
|
+
raise MissingEmissionFactor,
|
30
|
+
"Missing emission factor for sector #{io_code}"
|
31
|
+
end
|
32
|
+
sum + data[:emission_factor] * data[:share]
|
29
33
|
end
|
30
34
|
end
|
35
|
+
|
36
|
+
quorum 'default' do
|
37
|
+
# FIXME TODO figure out a real fallback emission factor
|
38
|
+
100
|
39
|
+
end
|
31
40
|
end
|
41
|
+
|
42
|
+
committee :sector_shares do
|
43
|
+
quorum 'from industry shares and product line shares', :needs => [:industry_shares, :product_line_shares] do |characteristics|
|
44
|
+
industry_sector_shares = sector_shares_from_industry_shares(characteristics[:industry_shares])
|
45
|
+
|
46
|
+
product_line_shares = characteristics[:product_line_shares]
|
47
|
+
product_lines_sectors = ProductLinesSectors.find :all,
|
48
|
+
:conditions => { :ps_code => product_line_shares.keys }
|
49
|
+
product_sector_shares = product_lines_sectors.inject({}) do |hash, product_line_sector|
|
50
|
+
io_code = product_line_sector.io_code
|
51
|
+
ps_code = product_line_sector.ps_code
|
52
|
+
product_line_share = product_line_shares[ps_code]
|
53
|
+
|
54
|
+
share = product_line_sector.ratio * product_line_share
|
55
|
+
sector = product_line_sector.sector
|
56
|
+
if sector.nil?
|
57
|
+
raise MissingSectorForProductLineSector,
|
58
|
+
"Missing a related sector for ProductLineSector #{product_line_sector.inspect}"
|
59
|
+
end
|
60
|
+
hash[io_code] = {
|
61
|
+
:share => share,
|
62
|
+
:emission_factor => sector.emission_factor
|
63
|
+
}
|
64
|
+
hash
|
65
|
+
end
|
66
|
+
|
67
|
+
industry_sector_shares.merge product_sector_shares
|
68
|
+
end
|
32
69
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
70
|
+
# TODO Do we need this?
|
71
|
+
quorum 'from industry shares', :needs => [:industry_shares] do |characteristics|
|
72
|
+
sector_shares_from_industry_shares(characteristics[:industry_shares])
|
73
|
+
end
|
74
|
+
|
75
|
+
quorum 'default' do
|
76
|
+
raise "We need a merchant, merchant category, industry, or product_line"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
committee :product_line_shares do
|
81
|
+
quorum 'from industry shares', :needs => [:industry_shares] do |characteristics|
|
82
|
+
industry_shares = characteristics[:industry_shares]
|
83
|
+
industries_product_lines = industry_shares.
|
84
|
+
map(&:industries_product_lines).flatten
|
85
|
+
|
86
|
+
industries_product_lines.inject({}) do |hash, industry_product_line|
|
87
|
+
ps_code = industry_product_line.ps_code
|
88
|
+
naics_code = industry_product_line.naics_code
|
89
|
+
industry_share = industry_shares.find_by_naics_code naics_code
|
90
|
+
hash[ps_code] =
|
91
|
+
industry_product_line.ratio * industry_share.ratio
|
92
|
+
hash
|
39
93
|
end
|
40
94
|
end
|
41
95
|
end
|
42
|
-
|
43
|
-
committee :
|
44
|
-
|
45
|
-
characteristics[:merchant_category].
|
96
|
+
|
97
|
+
committee :industry_shares do
|
98
|
+
quorum 'from merchant category', :needs => [:merchant_category] do |characteristics|
|
99
|
+
characteristics[:merchant_category].merchant_categories_industries
|
46
100
|
end
|
47
101
|
end
|
48
|
-
|
49
|
-
committee :merchant_category do
|
50
|
-
|
102
|
+
|
103
|
+
committee :merchant_category do
|
104
|
+
quorum 'from merchant', :needs => [:merchant] do |characteristics|
|
51
105
|
characteristics[:merchant].merchant_category
|
52
106
|
end
|
53
107
|
end
|
54
|
-
|
55
|
-
committee :adjusted_cost do
|
56
|
-
|
57
|
-
|
58
|
-
|
108
|
+
|
109
|
+
committee :adjusted_cost do
|
110
|
+
quorum 'from cost and date', :needs => [:cost, :date] do |characteristics|
|
111
|
+
# FIXME TODO convert cost to 2002 dollars based on date
|
112
|
+
characteristics[:cost]
|
59
113
|
end
|
60
114
|
|
61
|
-
|
62
|
-
#
|
115
|
+
quorum 'from purchase amount and date', :needs => [:purchase_amount, :date] do |characteristics|
|
116
|
+
# FIXME TODO take out tax, then convert to 2002 US $ based on date and cost
|
117
|
+
characteristics[:purchase_amount] * 0.9
|
118
|
+
end
|
119
|
+
|
120
|
+
quorum 'default' do
|
121
|
+
raise "We need either a cost or purchase amount"
|
63
122
|
end
|
64
123
|
end
|
65
124
|
end
|
66
125
|
# FIXME TODO make other committees to report emissions by gas, by io sector, etc.
|
67
126
|
end
|
127
|
+
|
128
|
+
def self.sector_shares_from_industry_shares(industry_shares)
|
129
|
+
industry_sectors = industry_shares.map(&:industries_sectors).flatten
|
130
|
+
industry_sectors.inject({}) do |hash, industry_sector|
|
131
|
+
io_code = industry_sector.io_code
|
132
|
+
unless ['420000','4A0000'].include?(io_code.to_s)
|
133
|
+
naics_code = industry_sector.naics_code
|
134
|
+
industry_share = industry_shares.find_by_naics_code naics_code
|
135
|
+
calculated_share = industry_share.ratio * industry_sector.ratio
|
136
|
+
sector = industry_sector.sector
|
137
|
+
hash[io_code] = {
|
138
|
+
:share => calculated_share,
|
139
|
+
:emission_factor => sector.emission_factor
|
140
|
+
}
|
141
|
+
end
|
142
|
+
hash
|
143
|
+
end
|
144
|
+
end
|
68
145
|
end
|
69
146
|
end
|
70
147
|
end
|
@@ -6,16 +6,15 @@ module BrighterPlanet
|
|
6
6
|
def self.included(base)
|
7
7
|
base.send :include, Characterizable
|
8
8
|
base.characterize do
|
9
|
-
has :merchant
|
10
|
-
|
11
|
-
|
12
|
-
has :
|
13
|
-
has :
|
14
|
-
has :io_sector
|
9
|
+
has :merchant
|
10
|
+
has :merchant_category
|
11
|
+
has :industry_shares
|
12
|
+
has :product_line_shares
|
13
|
+
has :sector_shares
|
15
14
|
has :purchase_amount # full purchase amount
|
16
15
|
has :tax # tax portion of purchase
|
17
16
|
has :cost # cost before tax
|
18
|
-
has :line_item
|
17
|
+
has :line_item # text describing what was purchased
|
19
18
|
has :customer_code
|
20
19
|
has :zip_code
|
21
20
|
has :date
|
data/lib/purchase/data.rb
CHANGED
@@ -6,14 +6,17 @@ module BrighterPlanet
|
|
6
6
|
def self.included(base)
|
7
7
|
base.data_miner do
|
8
8
|
schema do
|
9
|
-
|
9
|
+
string 'merchant_id'
|
10
10
|
string 'mcc'
|
11
|
-
string 'naics_code'
|
12
|
-
string '
|
13
|
-
string 'io_code'
|
11
|
+
string 'naics_code'
|
12
|
+
string 'ps_code'
|
13
|
+
string 'io_code'
|
14
14
|
float 'purchase_amount'
|
15
|
+
string 'purchase_amount_units'
|
15
16
|
float 'tax'
|
17
|
+
string 'tax_units'
|
16
18
|
float 'cost'
|
19
|
+
string 'cost_units'
|
17
20
|
string 'line_item'
|
18
21
|
string 'customer_code'
|
19
22
|
string 'zip_code_name'
|
@@ -4,9 +4,9 @@ Sniff::Database.define_schema do
|
|
4
4
|
create_table "purchase_records", :force => true do |t|
|
5
5
|
t.integer 'merchant_id'
|
6
6
|
t.string 'mcc'
|
7
|
-
t.string 'naics_code'
|
8
|
-
t.string '
|
9
|
-
t.string 'io_code'
|
7
|
+
t.string 'naics_code'
|
8
|
+
t.string 'ps_code'
|
9
|
+
t.string 'io_code'
|
10
10
|
t.float 'purchase_amount'
|
11
11
|
t.float 'tax'
|
12
12
|
t.float 'cost'
|
@@ -6,4 +6,10 @@ require 'sniff'
|
|
6
6
|
class PurchaseRecord < ActiveRecord::Base
|
7
7
|
include Sniff::Emitter
|
8
8
|
include BrighterPlanet::Purchase
|
9
|
+
|
10
|
+
belongs_to :merchant, :foreign_key => 'merchant_id'
|
11
|
+
belongs_to :merchant_category, :foreign_key => 'mcc'
|
12
|
+
# belongs_to :industry, :foreign_key => 'naics_code'
|
13
|
+
# belongs_to :product_line, :foreign_key => 'ps_code'
|
14
|
+
# belongs_to :sector, :foreign_key => 'io_code'
|
9
15
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: purchase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andy Rossmeissl
|
@@ -19,7 +19,7 @@ autorequire:
|
|
19
19
|
bindir: bin
|
20
20
|
cert_chain: []
|
21
21
|
|
22
|
-
date: 2010-
|
22
|
+
date: 2010-08-02 00:00:00 -04:00
|
23
23
|
default_executable:
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
@@ -144,12 +144,12 @@ dependencies:
|
|
144
144
|
requirements:
|
145
145
|
- - "="
|
146
146
|
- !ruby/object:Gem::Version
|
147
|
-
hash:
|
147
|
+
hash: 57
|
148
148
|
segments:
|
149
149
|
- 0
|
150
150
|
- 0
|
151
|
-
-
|
152
|
-
version: 0.0.
|
151
|
+
- 19
|
152
|
+
version: 0.0.19
|
153
153
|
requirement: *id008
|
154
154
|
- !ruby/object:Gem::Dependency
|
155
155
|
type: :runtime
|
@@ -170,8 +170,23 @@ dependencies:
|
|
170
170
|
- !ruby/object:Gem::Dependency
|
171
171
|
type: :runtime
|
172
172
|
prerelease: false
|
173
|
-
name:
|
173
|
+
name: cohort_scope
|
174
174
|
version_requirements: &id010 !ruby/object:Gem::Requirement
|
175
|
+
none: false
|
176
|
+
requirements:
|
177
|
+
- - ~>
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
hash: 11
|
180
|
+
segments:
|
181
|
+
- 0
|
182
|
+
- 0
|
183
|
+
version: "0.0"
|
184
|
+
requirement: *id010
|
185
|
+
- !ruby/object:Gem::Dependency
|
186
|
+
type: :runtime
|
187
|
+
prerelease: false
|
188
|
+
name: data_miner
|
189
|
+
version_requirements: &id011 !ruby/object:Gem::Requirement
|
175
190
|
none: false
|
176
191
|
requirements:
|
177
192
|
- - "="
|
@@ -182,28 +197,28 @@ dependencies:
|
|
182
197
|
- 5
|
183
198
|
- 2
|
184
199
|
version: 0.5.2
|
185
|
-
requirement: *
|
200
|
+
requirement: *id011
|
186
201
|
- !ruby/object:Gem::Dependency
|
187
202
|
type: :runtime
|
188
203
|
prerelease: false
|
189
204
|
name: earth
|
190
|
-
version_requirements: &
|
205
|
+
version_requirements: &id012 !ruby/object:Gem::Requirement
|
191
206
|
none: false
|
192
207
|
requirements:
|
193
208
|
- - ">="
|
194
209
|
- !ruby/object:Gem::Version
|
195
|
-
hash:
|
210
|
+
hash: 61
|
196
211
|
segments:
|
197
212
|
- 0
|
198
213
|
- 0
|
199
|
-
-
|
200
|
-
version: 0.0.
|
201
|
-
requirement: *
|
214
|
+
- 17
|
215
|
+
version: 0.0.17
|
216
|
+
requirement: *id012
|
202
217
|
- !ruby/object:Gem::Dependency
|
203
218
|
type: :runtime
|
204
219
|
prerelease: false
|
205
220
|
name: falls_back_on
|
206
|
-
version_requirements: &
|
221
|
+
version_requirements: &id013 !ruby/object:Gem::Requirement
|
207
222
|
none: false
|
208
223
|
requirements:
|
209
224
|
- - "="
|
@@ -214,12 +229,12 @@ dependencies:
|
|
214
229
|
- 0
|
215
230
|
- 2
|
216
231
|
version: 0.0.2
|
217
|
-
requirement: *
|
232
|
+
requirement: *id013
|
218
233
|
- !ruby/object:Gem::Dependency
|
219
234
|
type: :runtime
|
220
235
|
prerelease: false
|
221
236
|
name: fast_timestamp
|
222
|
-
version_requirements: &
|
237
|
+
version_requirements: &id014 !ruby/object:Gem::Requirement
|
223
238
|
none: false
|
224
239
|
requirements:
|
225
240
|
- - "="
|
@@ -230,12 +245,12 @@ dependencies:
|
|
230
245
|
- 0
|
231
246
|
- 4
|
232
247
|
version: 0.0.4
|
233
|
-
requirement: *
|
248
|
+
requirement: *id014
|
234
249
|
- !ruby/object:Gem::Dependency
|
235
250
|
type: :runtime
|
236
251
|
prerelease: false
|
237
252
|
name: leap
|
238
|
-
version_requirements: &
|
253
|
+
version_requirements: &id015 !ruby/object:Gem::Requirement
|
239
254
|
none: false
|
240
255
|
requirements:
|
241
256
|
- - "="
|
@@ -246,12 +261,12 @@ dependencies:
|
|
246
261
|
- 4
|
247
262
|
- 1
|
248
263
|
version: 0.4.1
|
249
|
-
requirement: *
|
264
|
+
requirement: *id015
|
250
265
|
- !ruby/object:Gem::Dependency
|
251
266
|
type: :runtime
|
252
267
|
prerelease: false
|
253
268
|
name: summary_judgement
|
254
|
-
version_requirements: &
|
269
|
+
version_requirements: &id016 !ruby/object:Gem::Requirement
|
255
270
|
none: false
|
256
271
|
requirements:
|
257
272
|
- - "="
|
@@ -262,12 +277,12 @@ dependencies:
|
|
262
277
|
- 3
|
263
278
|
- 8
|
264
279
|
version: 1.3.8
|
265
|
-
requirement: *
|
280
|
+
requirement: *id016
|
266
281
|
- !ruby/object:Gem::Dependency
|
267
282
|
type: :runtime
|
268
283
|
prerelease: false
|
269
284
|
name: timeframe
|
270
|
-
version_requirements: &
|
285
|
+
version_requirements: &id017 !ruby/object:Gem::Requirement
|
271
286
|
none: false
|
272
287
|
requirements:
|
273
288
|
- - "="
|
@@ -278,7 +293,7 @@ dependencies:
|
|
278
293
|
- 0
|
279
294
|
- 8
|
280
295
|
version: 0.0.8
|
281
|
-
requirement: *
|
296
|
+
requirement: *id017
|
282
297
|
description: A software model in Ruby for the greenhouse gas emissions of a purchase
|
283
298
|
email: seamus@brighterplanet.com
|
284
299
|
executables: []
|
@@ -300,6 +315,7 @@ files:
|
|
300
315
|
- lib/test_support/db/schema.rb
|
301
316
|
- lib/test_support/purchase_record.rb
|
302
317
|
- README.html
|
318
|
+
- features/step_definitions/committee_steps.rb
|
303
319
|
- features/support/env.rb
|
304
320
|
- features/purchase_committees.feature
|
305
321
|
- features/purchase_emissions.feature
|
@@ -338,6 +354,7 @@ signing_key:
|
|
338
354
|
specification_version: 3
|
339
355
|
summary: A carbon model
|
340
356
|
test_files:
|
357
|
+
- features/step_definitions/committee_steps.rb
|
341
358
|
- features/support/env.rb
|
342
359
|
- features/purchase_committees.feature
|
343
360
|
- features/purchase_emissions.feature
|