transaction_faker 1.0.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/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +167 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/transaction_faker.rb +12 -0
- data/lib/transaction_faker/categories.rb +682 -0
- data/lib/transaction_faker/models/account.rb +47 -0
- data/lib/transaction_faker/models/transaction.rb +63 -0
- data/lib/transaction_faker/models/user.rb +61 -0
- data/lib/transaction_faker/transaction_helper.rb +52 -0
- data/lib/transaction_faker/version.rb +3 -0
- data/transaction_faker.gemspec +36 -0
- metadata +144 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module TransactionFaker
|
2
|
+
|
3
|
+
class Account
|
4
|
+
attr_accessor :balance, :id, :institution_type, :item, :user, :type, :meta
|
5
|
+
|
6
|
+
def initialize(available_balance, current_balance)
|
7
|
+
@id = Faker::Lorem.characters(37)
|
8
|
+
@item = Faker::Lorem.characters(37)
|
9
|
+
@user = Faker::Lorem.characters(37)
|
10
|
+
@institution_type = get_random_institution
|
11
|
+
@balance = get_balance(available_balance, current_balance)
|
12
|
+
@meta = get_meta
|
13
|
+
@type = "depository"
|
14
|
+
end
|
15
|
+
|
16
|
+
def ==(other_account)
|
17
|
+
@id = other_account.id
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def get_random_institution
|
23
|
+
['amex', 'bofa', 'capone360', 'schwab', 'chase', 'citi', 'fidelity', 'pnc',
|
24
|
+
'svb', 'us', 'usaa', 'wells'].sample
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_balance(available_balance, current_balance)
|
28
|
+
balance = {
|
29
|
+
"available" => available_balance,
|
30
|
+
"current" => current_balance
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_meta
|
35
|
+
meta = {
|
36
|
+
"name" => get_account_name,
|
37
|
+
"number" => Faker::Number.number(4)
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_account_name
|
42
|
+
string = Faker::Name.name
|
43
|
+
(rand >= 0.5) ? string += "'s Savings" : string += "'s Checking"
|
44
|
+
string
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module TransactionFaker
|
4
|
+
#Excluded meta
|
5
|
+
class Transaction
|
6
|
+
attr_accessor :id, :account, :date, :amount, :name, :meta, :location, :pending, :score, :type, :cat, :category, :category_id, :pending_transaction
|
7
|
+
|
8
|
+
def initialize(account, amount, category_arr, cat_id, month_offset)
|
9
|
+
@id = Faker::Lorem.characters(38)
|
10
|
+
@account = account
|
11
|
+
@date = generate_date(month_offset)
|
12
|
+
@amount = amount
|
13
|
+
@name = Faker::Company.name
|
14
|
+
@location = create_location_hash()
|
15
|
+
@pending = false #should this vary?
|
16
|
+
@pendingTransaction = nil
|
17
|
+
@score = create_score
|
18
|
+
|
19
|
+
# Here for backwards compatibility only.
|
20
|
+
@type = { primary: Categories.get_transaction_type(cat_id) }
|
21
|
+
@category = category_arr
|
22
|
+
@category_id = cat_id
|
23
|
+
@meta = {"location" => @location["coordinates"]}
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other_transaction)
|
27
|
+
@id == other_transaction.id
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def generate_date(month_offset)
|
33
|
+
today = Date.today
|
34
|
+
month = today.prev_month(month_offset)
|
35
|
+
|
36
|
+
start_of_month = Date.new(month.year, month.month)
|
37
|
+
end_of_month = Date.new(start_of_month.year, start_of_month.month + 1) - 1
|
38
|
+
|
39
|
+
Faker::Date.between(start_of_month, end_of_month).iso8601
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_location_hash()
|
43
|
+
hash = {
|
44
|
+
"coordinates" => {
|
45
|
+
"lat" => Faker::Address.latitude.to_i,
|
46
|
+
"lon" => Faker::Address.longitude.to_i,
|
47
|
+
}
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_score
|
52
|
+
hash = {
|
53
|
+
"master" => 1,
|
54
|
+
"detail" => {
|
55
|
+
"address" => 1,
|
56
|
+
"city" => 1,
|
57
|
+
"name" => 1,
|
58
|
+
"state" => 1
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module TransactionFaker
|
4
|
+
class User
|
5
|
+
attr_accessor :account, :transactions, :access_token
|
6
|
+
|
7
|
+
def initialize(available_balance, current_balance, transaction_hash, seed = nil)
|
8
|
+
srand(seed) if seed
|
9
|
+
@account = Account.new(available_balance, current_balance)
|
10
|
+
@transactions = TransactionHelper::create_transactions(transaction_hash, account)
|
11
|
+
@access_token = Faker::Lorem.characters(37)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other_user)
|
15
|
+
@account == other_user.account
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json
|
19
|
+
user_hash = {
|
20
|
+
accounts: [
|
21
|
+
{
|
22
|
+
_id: @account.id,
|
23
|
+
_item: @account.item,
|
24
|
+
_user: @account.user,
|
25
|
+
balance: {
|
26
|
+
available: @account.balance["available"],
|
27
|
+
current: @account.balance["current"]
|
28
|
+
},
|
29
|
+
institution_type: @account.institution_type,
|
30
|
+
meta: @account.meta,
|
31
|
+
type: @account.type
|
32
|
+
}
|
33
|
+
],
|
34
|
+
transactions: add_hash_transactions
|
35
|
+
}
|
36
|
+
JSON.pretty_generate(user_hash)
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_hash_transactions
|
40
|
+
@transactions.map do |transaction|
|
41
|
+
{
|
42
|
+
_account: transaction.account.id,
|
43
|
+
_id: transaction.id,
|
44
|
+
amount: transaction.amount,
|
45
|
+
date: transaction.date,
|
46
|
+
name: transaction.name,
|
47
|
+
meta: transaction.meta,
|
48
|
+
pending: transaction.pending,
|
49
|
+
type: transaction.type,
|
50
|
+
category: transaction.category,
|
51
|
+
category_id: transaction.category_id,
|
52
|
+
score: transaction.score
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'categories'
|
2
|
+
require_relative 'models/transaction'
|
3
|
+
require 'faker'
|
4
|
+
|
5
|
+
module TransactionFaker
|
6
|
+
class TransactionHelper
|
7
|
+
|
8
|
+
# Returns an array with "amount" number of random values that comply with the
|
9
|
+
# mean and the standard_dev.The function gen.rng() will return an error if standard_dev
|
10
|
+
# is 0, so 0.000001 provides the same functionality
|
11
|
+
def self.normal_distribution(mean, standard_dev, amount)
|
12
|
+
standard_dev = 0.000001 if standard_dev == 0
|
13
|
+
gen = Rubystats::NormalDistribution.new(mean, standard_dev)
|
14
|
+
amount.times.map{ gen.rng().round(2) }
|
15
|
+
end
|
16
|
+
|
17
|
+
#Uses the TransactionHelper objects from the array created in 'create_data' to
|
18
|
+
#create an array of transactions over three months.
|
19
|
+
def self.create_transactions(transaction_hash, account_id)
|
20
|
+
3.times.flat_map do |month_offset|
|
21
|
+
transaction_hash.flat_map do |category, data|
|
22
|
+
subcategories = Categories::SUBCATEGORIES[category]
|
23
|
+
|
24
|
+
normal_distribution(data[:mean], data[:std_dev], data[:monthly_freq]).map do |price|
|
25
|
+
category_id = subcategories.sample
|
26
|
+
cat_array = create_category_array(category_id)
|
27
|
+
Transaction.new(account_id, price, cat_array, category_id.to_s, month_offset + 1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#Returns an array of strings with the category hierarchy,
|
34
|
+
# i.e. ["Food and Drink", "Restaurants", "Mexican"]
|
35
|
+
def self.create_category_array(id_num)
|
36
|
+
array = [
|
37
|
+
Categories::FIRST_DIV[convert_id(id_num, 1)],
|
38
|
+
Categories::SECOND_DIV[convert_id(id_num, 2)],
|
39
|
+
Categories::THIRD_DIV[id_num]
|
40
|
+
].compact
|
41
|
+
end
|
42
|
+
|
43
|
+
#Takes in a transaction ID number and floors it to match its superior category's ID
|
44
|
+
#cat_division is either 1 (first category) or 2
|
45
|
+
# i.e. 12034890 -> 12034000 or 12034890 -> 12000000
|
46
|
+
def self.convert_id(id_num, cat_division)
|
47
|
+
divisor = 1000**(3 - cat_division)
|
48
|
+
converted_id = ((id_num.to_f / divisor).to_i * divisor)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'transaction_faker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "transaction_faker"
|
8
|
+
spec.version = TransactionFaker::VERSION
|
9
|
+
spec.authors = ["Abiel Gutierrez"]
|
10
|
+
spec.email = ["abielg@stanford.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Creates fake bank account data and transactions to mimick an API response from Plaid's "Connect" service.}
|
13
|
+
spec.homepage = "https://github.com/abielg/transaction-faker"
|
14
|
+
|
15
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
16
|
+
# delete this section to allow pushing this gem to any host.
|
17
|
+
# if spec.respond_to?(:metadata)
|
18
|
+
# spec.metadata['allowed_push_host'] = "https://github.com/abielg/transaction-faker"
|
19
|
+
# else
|
20
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
21
|
+
# end
|
22
|
+
|
23
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
spec.bindir = "exe"
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "rspec"
|
31
|
+
|
32
|
+
#Gem Dependencies
|
33
|
+
spec.add_dependency "faker"
|
34
|
+
spec.add_dependency "rubystats"
|
35
|
+
spec.add_dependency "descriptive_statistics"
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: transaction_faker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Abiel Gutierrez
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faker
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubystats
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: descriptive_statistics
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- abielg@stanford.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".travis.yml"
|
107
|
+
- Gemfile
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- bin/console
|
111
|
+
- bin/setup
|
112
|
+
- lib/transaction_faker.rb
|
113
|
+
- lib/transaction_faker/categories.rb
|
114
|
+
- lib/transaction_faker/models/account.rb
|
115
|
+
- lib/transaction_faker/models/transaction.rb
|
116
|
+
- lib/transaction_faker/models/user.rb
|
117
|
+
- lib/transaction_faker/transaction_helper.rb
|
118
|
+
- lib/transaction_faker/version.rb
|
119
|
+
- transaction_faker.gemspec
|
120
|
+
homepage: https://github.com/abielg/transaction-faker
|
121
|
+
licenses: []
|
122
|
+
metadata: {}
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 2.4.5
|
140
|
+
signing_key:
|
141
|
+
specification_version: 4
|
142
|
+
summary: Creates fake bank account data and transactions to mimick an API response
|
143
|
+
from Plaid's "Connect" service.
|
144
|
+
test_files: []
|