stockr 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +8 -0
- data/README.rdoc +73 -26
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/bin/stockr +3 -1
- data/lib/stockr.rb +41 -21
- data/lib/stockr/export.rb +35 -10
- data/lib/stockr/import.rb +43 -0
- data/lib/stockr/part.rb +57 -30
- data/lib/stockr/web.rb +2 -2
- data/spec/data/export.txt +12 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/stockr/export_spec.rb +30 -0
- data/spec/stockr/part_spec.rb +14 -1
- data/spec/stockr_spec.rb +39 -35
- data/stockr.gemspec +88 -0
- metadata +45 -29
- data/LICENSE.txt +0 -20
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
GEM
|
2
2
|
specs:
|
3
3
|
diff-lcs (1.1.2)
|
4
|
+
eletro (0.1.1)
|
5
|
+
stick (>= 1.3.3)
|
6
|
+
facets (2.9.0)
|
4
7
|
git (1.2.5)
|
5
8
|
jeweler (1.5.1)
|
6
9
|
bundler (~> 1.0.0)
|
7
10
|
git (>= 1.2.5)
|
8
11
|
rake
|
12
|
+
multipart-post (1.0.1)
|
9
13
|
rack (1.2.1)
|
10
14
|
rake (0.8.7)
|
11
15
|
rcov (0.9.9)
|
@@ -21,6 +25,8 @@ GEM
|
|
21
25
|
sinatra (1.1.0)
|
22
26
|
rack (~> 1.1)
|
23
27
|
tilt (~> 1.1)
|
28
|
+
stick (1.3.3)
|
29
|
+
facets (>= 2.1.0)
|
24
30
|
tilt (1.1)
|
25
31
|
|
26
32
|
PLATFORMS
|
@@ -28,7 +34,9 @@ PLATFORMS
|
|
28
34
|
|
29
35
|
DEPENDENCIES
|
30
36
|
bundler (~> 1.0.0)
|
37
|
+
eletro
|
31
38
|
jeweler (~> 1.5.1)
|
39
|
+
multipart-post
|
32
40
|
rcov
|
33
41
|
redis
|
34
42
|
rspec (~> 2.1.0)
|
data/README.rdoc
CHANGED
@@ -1,19 +1,50 @@
|
|
1
1
|
= stockr
|
2
2
|
|
3
3
|
|
4
|
-
Keep your stock up to date.
|
5
|
-
|
6
|
-
Exports to a bunch of formats too.
|
4
|
+
Keep your stock up to date with easy bash editing and web view.
|
5
|
+
Some fancy stuff, oh, and it exports to a bunch of formats too.
|
7
6
|
|
8
7
|
|
9
8
|
== Use
|
10
9
|
|
10
|
+
stockr quantity name package and/or price
|
11
|
+
|
12
|
+
|
13
|
+
stockr 5 LM358
|
14
|
+
> 5x LM358
|
11
15
|
|
12
|
-
stockr +5 LM358
|
13
16
|
stockr -2 LM358
|
14
|
-
stockr LM358
|
15
17
|
> 3x LM358
|
16
18
|
|
19
|
+
stockr LM
|
20
|
+
> 3x LM358
|
21
|
+
|
22
|
+
stockr 2 LM338 DIP
|
23
|
+
stockr 2 LM338 0.50
|
24
|
+
stockr 2 LM338 SMD 0.50
|
25
|
+
...
|
26
|
+
|
27
|
+
|
28
|
+
=== Web View
|
29
|
+
|
30
|
+
stockr web
|
31
|
+
|
32
|
+
If a navigator windows doesn`t appear, try: http://localhost:4567
|
33
|
+
|
34
|
+
|
35
|
+
=== Part Find
|
36
|
+
|
37
|
+
Resistors:
|
38
|
+
|
39
|
+
Supposing you got 1k and 220R resistors, when you ask for "500R" we should see:
|
40
|
+
|
41
|
+
2x 1k Parallel
|
42
|
+
2x 220R Serie
|
43
|
+
|
44
|
+
Alternatives ICs (TODO)
|
45
|
+
|
46
|
+
This will need human linkage? Isn't there a world database for this?
|
47
|
+
|
17
48
|
=== Shop List
|
18
49
|
|
19
50
|
If stock goes under 1, shows how many of that item we need, so just ask for shop:
|
@@ -23,24 +54,25 @@ If stock goes under 1, shows how many of that item we need, so just ask for shop
|
|
23
54
|
>2x ATMEGA8
|
24
55
|
|
25
56
|
|
26
|
-
===
|
27
|
-
|
28
|
-
stockr web
|
57
|
+
=== Export formats
|
29
58
|
|
30
|
-
|
59
|
+
Export to a bunch of formats (online someday?)
|
31
60
|
|
32
|
-
|
61
|
+
stockr [format]
|
33
62
|
|
63
|
+
Available: txt, csv, pdf, html, xml.
|
34
64
|
|
35
65
|
|
36
|
-
===
|
66
|
+
=== Import formats
|
37
67
|
|
38
|
-
|
68
|
+
You can use the txt format as a backup store. And run:
|
39
69
|
|
40
|
-
|
70
|
+
stockr [file]
|
41
71
|
|
72
|
+
To import it.
|
42
73
|
|
43
74
|
|
75
|
+
= PT
|
44
76
|
|
45
77
|
== Usar
|
46
78
|
|
@@ -50,34 +82,49 @@ sudo gem install stockr
|
|
50
82
|
|
51
83
|
Como funfa:
|
52
84
|
|
53
|
-
|
54
|
-
|
85
|
+
stockr +5 LM358
|
86
|
+
stockr +2 LM1117
|
55
87
|
|
56
88
|
Dae tu vai, usa um LM em um circ:
|
57
89
|
|
58
|
-
|
90
|
+
stockr -1 LM1117
|
59
91
|
|
60
92
|
Opa, q q eu tenho de lm?
|
61
93
|
|
62
|
-
|
94
|
+
stockr LM
|
95
|
+
|
96
|
+
> 5x LM358
|
97
|
+
> 1x LM1117
|
63
98
|
|
64
|
-
|
65
|
-
|
99
|
+
Aceita preços também:
|
100
|
+
|
101
|
+
|
102
|
+
stockr 10 LM7805 0.95
|
103
|
+
> 10x LM7805 0.95 (9.50)
|
66
104
|
|
67
105
|
|
68
106
|
=== Shop List
|
69
|
-
Outra opcao eh colocar coisas negativas, ou qdo chegar em valor negativo, vc chama:
|
70
107
|
|
71
|
-
stockr
|
108
|
+
Quando se adiciona peças negativas (stockr -5 LM7805, por exemplo),
|
109
|
+
ou qdo uma chega em valor negativo, executando:
|
110
|
+
|
111
|
+
stockr shop
|
112
|
+
|
113
|
+
É exibida uma listagem de coisas faltando...
|
114
|
+
|
115
|
+
|
116
|
+
=== Interface Web
|
117
|
+
|
118
|
+
stockr web
|
119
|
+
|
120
|
+
Se uma janela do navegador não abrir, visite http://localhost:4567
|
72
121
|
|
73
|
-
Vem a lista de coisas faltando...
|
74
122
|
|
75
|
-
|
123
|
+
=== Exportar Dados
|
76
124
|
|
77
|
-
|
125
|
+
stockr [FORMATO]
|
78
126
|
|
79
|
-
|
80
|
-
Sugestoes/duvidas to ae.
|
127
|
+
Exporta seu estoque. FORMATO podendo ser txt, csv, pdf, html.....
|
81
128
|
|
82
129
|
|
83
130
|
|
data/Rakefile
CHANGED
@@ -20,7 +20,8 @@ Jeweler::Tasks.new do |gem|
|
|
20
20
|
gem.email = "x@nofxx.com"
|
21
21
|
gem.authors = ["Marcos Piccinini"]
|
22
22
|
|
23
|
-
|
23
|
+
# DEPRECATED?
|
24
|
+
# gem.add_runtime_dependency 'redis'
|
24
25
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
25
26
|
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
26
27
|
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/stockr
CHANGED
data/lib/stockr.rb
CHANGED
@@ -1,22 +1,55 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
require "redis"
|
3
|
+
require "eletro"
|
3
4
|
|
4
5
|
require "stockr/store"
|
5
6
|
require "stockr/part"
|
7
|
+
require "stockr/import"
|
6
8
|
require "stockr/export"
|
7
9
|
|
8
10
|
module Stockr
|
9
11
|
|
10
12
|
FORMATS = %w{ txt csv html pdf xml }
|
13
|
+
DOTFILE = ENV['HOME'] + "/.stockr"
|
14
|
+
# TECHUB = "http://techub.heroku.com"
|
15
|
+
TECHUB = "http://localhost:3000"
|
11
16
|
|
12
|
-
def self.print_parts(res)
|
13
|
-
return "Not found... go shop!" unless res && !res.empty?
|
14
|
-
res.map(&:facts).join("\n")
|
15
17
|
|
18
|
+
def self.get_user
|
19
|
+
unless File.exists?(DOTFILE)
|
20
|
+
puts "What\`s your techub username?"
|
21
|
+
name = gets.chomp
|
22
|
+
puts "Password?"
|
23
|
+
pass = gets.chomp
|
24
|
+
File.open(DOTFILE, "w") { |f| f << "name: #{name}\npass: #{pass}"}
|
25
|
+
end
|
26
|
+
@conf = YAML.load(File.read(DOTFILE))
|
27
|
+
[@conf["name"], @conf["pass"]]
|
16
28
|
end
|
17
29
|
|
30
|
+
def self.run(txt)
|
31
|
+
if txt.size == 1
|
32
|
+
if txt.join =~ /#{FORMATS.join('|')}/
|
33
|
+
f = Export.send(txt[0].to_sym)
|
34
|
+
"File saved! #{f}"
|
35
|
+
else
|
36
|
+
puts "Searching...#{txt.join}"
|
37
|
+
res = Part.search(txt.join.upcase)
|
38
|
+
puts (res && !res.empty?) ? Export.format(res) : "Not found... go shop!"
|
39
|
+
res
|
40
|
+
end
|
41
|
+
else
|
42
|
+
if part = Part.create_or_increment(*txt)
|
43
|
+
puts "Ok, #{part.facts}"
|
44
|
+
else
|
45
|
+
puts "Problems creating part..."
|
46
|
+
end
|
47
|
+
part
|
48
|
+
end
|
49
|
+
end
|
18
50
|
|
19
51
|
def self.work(txt)
|
52
|
+
get_user
|
20
53
|
txt = txt.split(" ") unless txt.is_a? Array
|
21
54
|
parse = txt
|
22
55
|
case parse.join
|
@@ -24,24 +57,11 @@ module Stockr
|
|
24
57
|
when "web" then
|
25
58
|
puts "Starting websever on port."
|
26
59
|
require "stockr/web"
|
27
|
-
when "shop" then
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
"File saved! #{f}"
|
33
|
-
else
|
34
|
-
puts "Searching...#{txt.join}"
|
35
|
-
print_parts Part.search(txt.join.upcase)
|
36
|
-
end
|
37
|
-
else
|
38
|
-
if part = Part.create_or_increment(*parse)
|
39
|
-
return "Done. #{part.facts}"
|
40
|
-
else
|
41
|
-
"Problems creating part..."
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
60
|
+
when "shop" then puts Export.format(Part.missing)
|
61
|
+
when /load.*/ then Import.from_file txt[1] #ARGF
|
62
|
+
when /pull.*/ then Import.from_web
|
63
|
+
when /push.*/ then Export.to_web
|
64
|
+
else run(txt)
|
45
65
|
end
|
46
66
|
|
47
67
|
end
|
data/lib/stockr/export.rb
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
# Export Redis DB to various formats
|
4
4
|
#
|
5
5
|
#
|
6
|
+
|
7
|
+
require 'net/http/post/multipart'
|
8
|
+
|
6
9
|
module Stockr
|
7
10
|
|
8
11
|
class Export
|
@@ -17,18 +20,20 @@ module Stockr
|
|
17
20
|
@ts ||= Time.now.strftime("%y-%m-%d-%H-%M-%S")
|
18
21
|
end
|
19
22
|
|
20
|
-
def format
|
23
|
+
def format(data = Part.all)
|
24
|
+
return "Nada." unless data && !data.empty?
|
21
25
|
<<TXT
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
#
|
27
|
+
# Stockr Export
|
28
|
+
#
|
29
|
+
# #{Time.now.strftime("%d/%b/%Y %H:%M:%S")}
|
30
|
+
#
|
31
|
+
---------------------------------------------------------------------
|
27
32
|
|
28
|
-
#{
|
33
|
+
#{data.map(&:line).join("\n")}
|
29
34
|
|
30
|
-
|
31
|
-
Total: #{
|
35
|
+
---------------------------------------------------------------------
|
36
|
+
Total: #{data.size} Part(s). #{Part.sum(data)}
|
32
37
|
|
33
38
|
TXT
|
34
39
|
end
|
@@ -59,12 +64,32 @@ TXT
|
|
59
64
|
def xml
|
60
65
|
end
|
61
66
|
|
62
|
-
def write(txt, ext)
|
67
|
+
def write(txt, ext, path = nil)
|
63
68
|
fname = filename + ".#{ext}"
|
69
|
+
fname = path + fname if path
|
64
70
|
File.open(fname, "w") { |f| f << txt }
|
65
71
|
fname
|
66
72
|
end
|
67
73
|
|
74
|
+
def to_web
|
75
|
+
user, pass = Stockr.get_user unless user
|
76
|
+
file = write(format, :txt, "/tmp/")
|
77
|
+
puts "Exporting db to techub..."
|
78
|
+
url = URI.parse(TECHUB + "/push")
|
79
|
+
File.open(file) do |f|
|
80
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
81
|
+
req = Net::HTTP::Post::Multipart.new url.path, "file" => UploadIO.new(f, "text/plain", file)
|
82
|
+
req.basic_auth user, pass if pass
|
83
|
+
puts "Sending file..."
|
84
|
+
http.request(req)
|
85
|
+
puts req.body
|
86
|
+
end
|
87
|
+
puts "Done."
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
|
68
93
|
end
|
69
94
|
|
70
95
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "net/http"
|
2
|
+
# require "net/http"
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module Stockr
|
6
|
+
|
7
|
+
class Import
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def import(l)
|
12
|
+
puts "Importing #{l}" #if Debug
|
13
|
+
_, qty, name, price = l.match(/^\s*([0-9]*)x\s*([^\.\s]*)\s*\.*\s*(\d*\.?\d*)/).to_a
|
14
|
+
return unless qty || name
|
15
|
+
Part.find_or_create(qty, name, price)
|
16
|
+
end
|
17
|
+
|
18
|
+
def from_file(file)
|
19
|
+
File.open(file).each_line { |l| import(l) }
|
20
|
+
"Loaded"
|
21
|
+
end
|
22
|
+
|
23
|
+
def from_web(user = nil)
|
24
|
+
user, pass = Stockr.get_user unless user
|
25
|
+
puts "Downloading dump file...#{TECHUB}/#{user}.txt"
|
26
|
+
puts url = URI.parse("#{TECHUB}/#{user}.txt")
|
27
|
+
Net::HTTP.start(url.host, url.port) { |http|
|
28
|
+
req = Net::HTTP::Get.new("/#{user}.txt")
|
29
|
+
req.basic_auth user, pass if pass
|
30
|
+
res = http.request(req)
|
31
|
+
puts "File downloaded, parsing..."
|
32
|
+
res.body.each_line { |l| import(l) }
|
33
|
+
}
|
34
|
+
puts "Done"
|
35
|
+
# puts res.body
|
36
|
+
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/lib/stockr/part.rb
CHANGED
@@ -3,7 +3,10 @@
|
|
3
3
|
module Stockr
|
4
4
|
|
5
5
|
class Part
|
6
|
-
|
6
|
+
|
7
|
+
attr_reader :name, :qty, :price, :pkg, :kind
|
8
|
+
|
9
|
+
CASH = "$ %.3f"
|
7
10
|
|
8
11
|
def initialize(name, qty = 0, pr = 0)
|
9
12
|
@name = name.upcase
|
@@ -13,23 +16,31 @@ module Stockr
|
|
13
16
|
|
14
17
|
def save
|
15
18
|
return false unless name && !name.empty?
|
16
|
-
Store.write(name, { :qty => qty, :price => price })
|
19
|
+
Store.write(name, { :qty => qty, :price => price, :pkg => pkg })
|
17
20
|
end
|
18
21
|
|
19
|
-
def
|
20
|
-
out = "#{qty}x
|
22
|
+
def line
|
23
|
+
out = "#{qty}#{' ' * (5-qty.to_s.size)}x #{name} #{pkg} "
|
21
24
|
if price && !price.zero?
|
22
25
|
out << ("." * (50 - out.size))
|
23
|
-
out <<
|
24
|
-
out << " ($ %.3f)" % (price * qty) if qty != 1
|
26
|
+
out << CASH % price
|
27
|
+
out << " ($ %.3f)" % (price * qty) #if qty != 1
|
25
28
|
end
|
26
29
|
out
|
27
30
|
end
|
28
31
|
|
32
|
+
def facts
|
33
|
+
out = "#{qty}x #{name} #{pkg} #{CASH} (#{CASH})" % [price, price_total]
|
34
|
+
end
|
35
|
+
|
29
36
|
def qty=(v)
|
30
37
|
@qty = v
|
31
38
|
end
|
32
39
|
|
40
|
+
def pkg=(p)
|
41
|
+
@pkg = p
|
42
|
+
end
|
43
|
+
|
33
44
|
def price=(pr)
|
34
45
|
# BigDecimal.new()
|
35
46
|
@price = pr.kind_of?(Numeric) ? pr.to_f : pr.gsub(",", ".").to_f
|
@@ -43,37 +54,53 @@ module Stockr
|
|
43
54
|
"{name: '#{name}', qty: '#{qty}', price: '%.3f', total_price: '%.3f'}" % [price, price_total]
|
44
55
|
end
|
45
56
|
|
46
|
-
|
47
|
-
part = search(name, true) || new(name)
|
48
|
-
incr ? part.qty += q.to_i : part.qty = q.to_i
|
49
|
-
part.price = pr
|
50
|
-
part.save
|
51
|
-
part
|
52
|
-
end
|
57
|
+
class << self
|
53
58
|
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
def sum(ary = search("*"))
|
60
|
+
CASH % ary.reduce(0) { |i, p| i += p.price_total }
|
61
|
+
end
|
57
62
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
63
|
+
def find_or_create(q, name, pr=0, incr = false)
|
64
|
+
part = search(name, true) || new(name)
|
65
|
+
incr ? part.qty += q.to_i : part.qty = q.to_i
|
66
|
+
if pr =~ /\d/
|
67
|
+
part.price = pr
|
68
|
+
else
|
69
|
+
part.pkg = pr
|
62
70
|
end
|
63
|
-
|
64
|
-
|
65
|
-
nil
|
71
|
+
part.save
|
72
|
+
part
|
66
73
|
end
|
67
|
-
end
|
68
74
|
|
69
|
-
|
75
|
+
def create_or_increment(q, name, pr=0)
|
76
|
+
find_or_create(q, name, pr, true)
|
77
|
+
end
|
70
78
|
|
71
|
-
|
72
|
-
|
73
|
-
|
79
|
+
def search(txt, exact = false)
|
80
|
+
if res = Store.find(exact ? txt : "*#{txt}*")
|
81
|
+
objs = res.map do |k, r|
|
82
|
+
new(k, r["qty"], r["price"])
|
83
|
+
end
|
84
|
+
exact ? objs[0] : objs # FIXME: better way?
|
85
|
+
else
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def all; search(''); end
|
91
|
+
|
92
|
+
def list(txt = "*")
|
93
|
+
search(txt).map(&:line) rescue []
|
94
|
+
end
|
95
|
+
|
96
|
+
def find(txt)
|
97
|
+
search(txt, true)
|
98
|
+
end
|
99
|
+
|
100
|
+
def missing
|
101
|
+
all.select { |p| p.qty <= 0 }
|
102
|
+
end
|
74
103
|
|
75
|
-
def self.missing
|
76
|
-
all.select { |p| p.qty <= 0 }
|
77
104
|
end
|
78
105
|
|
79
106
|
|
data/lib/stockr/web.rb
CHANGED
@@ -11,7 +11,7 @@ get '/' do
|
|
11
11
|
parts = Part.all
|
12
12
|
@parts = parts.map(&:to_json)
|
13
13
|
@sum = parts.reduce(0) { |n, p| n += p.price_total }
|
14
|
-
|
14
|
+
|
15
15
|
erb <<INDEX
|
16
16
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
17
17
|
<html class="cufon-active cufon-ready"><head>
|
@@ -239,5 +239,5 @@ post '/' do
|
|
239
239
|
end
|
240
240
|
end
|
241
241
|
|
242
|
-
|
242
|
+
Sinatra::Application.run!
|
243
243
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Stockr Export
|
2
|
+
|
3
|
+
10-12-09-19-23-51
|
4
|
+
|
5
|
+
-------------------------------------------
|
6
|
+
|
7
|
+
100x 10K............................. 0.05 (5.00)
|
8
|
+
50x LM7805........................... 0.10 (5.00)
|
9
|
+
25x LM758............................ 1.00 (25.00)
|
10
|
+
|
11
|
+
-------------------------------------------
|
12
|
+
Total: 0
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Export" do
|
4
|
+
include Stockr
|
5
|
+
|
6
|
+
it "should export txt file" do
|
7
|
+
Time.should_receive(:now).exactly(2).times.and_return(Time.at(1291879432))
|
8
|
+
run("4 LM448")
|
9
|
+
run("txt").should eql("File saved! my_stockr_10-12-09-05-23-52.txt")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should export to html file" do
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
it "should import txt bkp" do
|
18
|
+
run("load ./spec/data/export.txt").should eql("Loaded")
|
19
|
+
Part.find("LM7805").qty.should eql(50)
|
20
|
+
Part.find("LM758").qty.should eql(25)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should import all values" do
|
24
|
+
run("load ./spec/data/export.txt").should eql("Loaded")
|
25
|
+
Part.all.size.should eql(3)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
end
|
30
|
+
|
data/spec/stockr/part_spec.rb
CHANGED
@@ -15,5 +15,18 @@ describe "Part" do
|
|
15
15
|
Part.new("IRF640", 10, "0,30").price.should be_within(0.1).of(0.3)
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
it "should list all parts" do
|
19
|
+
run("-2 LM447")
|
20
|
+
run("2 LM448")
|
21
|
+
Part.all.should have(2).parts
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should list missing parts" do
|
25
|
+
run("-2 LM447")
|
26
|
+
run("2 LM448")
|
27
|
+
Part.missing.should have(1).part
|
28
|
+
Part.missing[0].name.should eql("LM447")
|
29
|
+
# run("shop").should eql("-2x LM447 $ 0.000 ($ -0.000)")
|
30
|
+
end
|
31
|
+
|
19
32
|
end
|
data/spec/stockr_spec.rb
CHANGED
@@ -1,78 +1,82 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "Stockr" do
|
4
|
+
include Stockr
|
4
5
|
|
5
|
-
def
|
6
|
-
|
6
|
+
def find(t)
|
7
|
+
Part.find(t)
|
7
8
|
end
|
8
9
|
|
9
10
|
it "should add parts" do
|
10
|
-
run("2 LM358").should
|
11
|
-
run("LM358").should
|
11
|
+
run("2 LM358").should be_a Part
|
12
|
+
run("LM358").should have(1).part
|
12
13
|
end
|
13
14
|
|
14
|
-
it "should add
|
15
|
-
run("100 1K").should eql("
|
16
|
-
|
15
|
+
it "should add part names" do
|
16
|
+
run("100 1K").name.should eql("1K")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should add part qty" do
|
20
|
+
run("100 1K").qty.should eql(100)
|
17
21
|
end
|
18
22
|
|
19
23
|
it "should increment existing parts" do
|
20
|
-
run("2 ATMEGA32").should eql("
|
21
|
-
run("2 ATMEGA32").should eql(
|
22
|
-
|
24
|
+
run("2 ATMEGA32").name.should eql("ATMEGA32")
|
25
|
+
run("2 ATMEGA32").qty.should eql(4)
|
26
|
+
Part.all.size.should eql(1)
|
27
|
+
find("ATMEGA32").qty.should eql(4)
|
23
28
|
end
|
24
29
|
|
25
30
|
it "should decrement existing parts" do
|
26
|
-
run("4 LM447")
|
27
|
-
run("-2 LM447")
|
31
|
+
run("4 LM447")
|
32
|
+
run("-2 LM447")
|
33
|
+
Part.all.size.should eql(1)
|
34
|
+
find("LM447").qty.should eql(2)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should parse nicely missing parts" do
|
38
|
+
run("-2 4N35").qty.should eql(-2)
|
28
39
|
end
|
29
40
|
|
30
41
|
it "should add missing parts" do
|
31
|
-
run("-2 LM447")
|
32
|
-
|
42
|
+
run("-2 LM447")
|
43
|
+
find("LM447").qty.should eql(-2)
|
44
|
+
run("2 LM447")
|
45
|
+
find("LM447").qty.should be_zero
|
33
46
|
end
|
34
47
|
|
35
|
-
it "should
|
36
|
-
run("
|
37
|
-
run("2
|
38
|
-
run("shop").should eql("-2x LM447")
|
48
|
+
it "should add pkgs to parts" do
|
49
|
+
run("2 LM338 DIP").pkg.should eql("DIP")
|
50
|
+
run("2 LM338 DIP").price.should be_zero
|
39
51
|
end
|
40
52
|
|
41
53
|
it "should add prices to parts" do
|
42
|
-
run("1 LM447
|
54
|
+
run("1 LM447 1.50").price.should be_within(0.1).of(1.5)
|
43
55
|
end
|
44
56
|
|
45
57
|
it "should add prices to multiple parts (sum)" do
|
46
|
-
run("2 LM447 0.50").should
|
58
|
+
run("2 LM447 0.50").price.should be_within(0.1).of(0.5)
|
47
59
|
end
|
48
60
|
|
49
61
|
it "should upcase the part name" do
|
50
|
-
run("8 enc28j60").should eql("
|
62
|
+
run("8 enc28j60").name.should eql("ENC28J60")
|
51
63
|
end
|
52
64
|
|
53
65
|
it "should be case insensitive" do
|
54
|
-
run("2 LM447")
|
55
|
-
run("lm447").should eql("
|
66
|
+
run("2 LM447")
|
67
|
+
run("lm447")[0].name.should eql(find("LM447").name)
|
56
68
|
end
|
57
69
|
|
58
70
|
it "should search pattern" do
|
59
|
-
run("4 LM447")
|
60
|
-
run("4 LM448")
|
71
|
+
run("4 LM447")
|
72
|
+
run("4 LM448")
|
61
73
|
|
62
|
-
run("LM4").should
|
74
|
+
run("LM4").should have(2).parts
|
63
75
|
end
|
64
76
|
|
65
77
|
it "should not fault when not found" do
|
66
|
-
run("DUNNO").should
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should export txt file" do
|
70
|
-
Time.should_receive(:now).and_return(Time.at(1291879432))
|
71
|
-
run("4 LM448").should eql("Done. 4x LM448")
|
72
|
-
run("txt").should eql("File saved! my_stockr_10-12-09-05-23-52.txt")
|
78
|
+
run("DUNNO").should be_nil
|
73
79
|
end
|
74
80
|
|
75
|
-
it "should export to html file" do
|
76
|
-
end
|
77
81
|
|
78
82
|
end
|
data/stockr.gemspec
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{stockr}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Marcos Piccinini"]
|
12
|
+
s.date = %q{2010-12-11}
|
13
|
+
s.default_executable = %q{stockr}
|
14
|
+
s.description = %q{Help keep track of stuff (good for electronics)}
|
15
|
+
s.email = %q{x@nofxx.com}
|
16
|
+
s.executables = ["stockr"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".rspec",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"bin/stockr",
|
29
|
+
"lib/stockr.rb",
|
30
|
+
"lib/stockr/assets/bundle.js",
|
31
|
+
"lib/stockr/export.rb",
|
32
|
+
"lib/stockr/import.rb",
|
33
|
+
"lib/stockr/part.rb",
|
34
|
+
"lib/stockr/store.rb",
|
35
|
+
"lib/stockr/web.rb",
|
36
|
+
"spec/data/export.txt",
|
37
|
+
"spec/spec_helper.rb",
|
38
|
+
"spec/stockr/export_spec.rb",
|
39
|
+
"spec/stockr/part_spec.rb",
|
40
|
+
"spec/stockr_spec.rb"
|
41
|
+
]
|
42
|
+
s.homepage = %q{http://github.com/nofxx/stockr}
|
43
|
+
s.licenses = ["MIT"]
|
44
|
+
s.require_paths = ["lib"]
|
45
|
+
s.rubygems_version = %q{1.3.7}
|
46
|
+
s.summary = %q{Keep track of all your stuff}
|
47
|
+
s.test_files = [
|
48
|
+
"spec/spec_helper.rb",
|
49
|
+
"spec/stockr/export_spec.rb",
|
50
|
+
"spec/stockr/part_spec.rb",
|
51
|
+
"spec/stockr_spec.rb"
|
52
|
+
]
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_runtime_dependency(%q<redis>, [">= 0"])
|
60
|
+
s.add_runtime_dependency(%q<eletro>, [">= 0"])
|
61
|
+
s.add_runtime_dependency(%q<multipart-post>, [">= 0"])
|
62
|
+
s.add_development_dependency(%q<sinatra>, [">= 0"])
|
63
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.1.0"])
|
64
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
65
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
66
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
67
|
+
else
|
68
|
+
s.add_dependency(%q<redis>, [">= 0"])
|
69
|
+
s.add_dependency(%q<eletro>, [">= 0"])
|
70
|
+
s.add_dependency(%q<multipart-post>, [">= 0"])
|
71
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
72
|
+
s.add_dependency(%q<rspec>, ["~> 2.1.0"])
|
73
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
74
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
75
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
76
|
+
end
|
77
|
+
else
|
78
|
+
s.add_dependency(%q<redis>, [">= 0"])
|
79
|
+
s.add_dependency(%q<eletro>, [">= 0"])
|
80
|
+
s.add_dependency(%q<multipart-post>, [">= 0"])
|
81
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
82
|
+
s.add_dependency(%q<rspec>, ["~> 2.1.0"])
|
83
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
84
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
85
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 2
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Marcos Piccinini
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-11 00:00:00 -02:00
|
18
18
|
default_executable: stockr
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
prerelease: false
|
32
32
|
version_requirements: *id001
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: eletro
|
35
35
|
requirement: &id002 !ruby/object:Gem::Requirement
|
36
36
|
none: false
|
37
37
|
requirements:
|
@@ -40,70 +40,83 @@ dependencies:
|
|
40
40
|
segments:
|
41
41
|
- 0
|
42
42
|
version: "0"
|
43
|
-
type: :
|
43
|
+
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: *id002
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: multipart-post
|
48
48
|
requirement: &id003 !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
segments:
|
54
|
-
- 2
|
55
|
-
- 1
|
56
54
|
- 0
|
57
|
-
version:
|
58
|
-
type: :
|
55
|
+
version: "0"
|
56
|
+
type: :runtime
|
59
57
|
prerelease: false
|
60
58
|
version_requirements: *id003
|
61
59
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
60
|
+
name: sinatra
|
63
61
|
requirement: &id004 !ruby/object:Gem::Requirement
|
64
62
|
none: false
|
65
63
|
requirements:
|
66
|
-
- -
|
64
|
+
- - ">="
|
67
65
|
- !ruby/object:Gem::Version
|
68
66
|
segments:
|
69
|
-
- 1
|
70
|
-
- 0
|
71
67
|
- 0
|
72
|
-
version:
|
68
|
+
version: "0"
|
73
69
|
type: :development
|
74
70
|
prerelease: false
|
75
71
|
version_requirements: *id004
|
76
72
|
- !ruby/object:Gem::Dependency
|
77
|
-
name:
|
73
|
+
name: rspec
|
78
74
|
requirement: &id005 !ruby/object:Gem::Requirement
|
79
75
|
none: false
|
80
76
|
requirements:
|
81
77
|
- - ~>
|
82
78
|
- !ruby/object:Gem::Version
|
83
79
|
segments:
|
80
|
+
- 2
|
84
81
|
- 1
|
85
|
-
-
|
86
|
-
|
87
|
-
version: 1.5.1
|
82
|
+
- 0
|
83
|
+
version: 2.1.0
|
88
84
|
type: :development
|
89
85
|
prerelease: false
|
90
86
|
version_requirements: *id005
|
91
87
|
- !ruby/object:Gem::Dependency
|
92
|
-
name:
|
88
|
+
name: bundler
|
93
89
|
requirement: &id006 !ruby/object:Gem::Requirement
|
94
90
|
none: false
|
95
91
|
requirements:
|
96
|
-
- -
|
92
|
+
- - ~>
|
97
93
|
- !ruby/object:Gem::Version
|
98
94
|
segments:
|
95
|
+
- 1
|
99
96
|
- 0
|
100
|
-
|
97
|
+
- 0
|
98
|
+
version: 1.0.0
|
101
99
|
type: :development
|
102
100
|
prerelease: false
|
103
101
|
version_requirements: *id006
|
104
102
|
- !ruby/object:Gem::Dependency
|
105
|
-
name:
|
103
|
+
name: jeweler
|
106
104
|
requirement: &id007 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
segments:
|
110
|
+
- 1
|
111
|
+
- 5
|
112
|
+
- 1
|
113
|
+
version: 1.5.1
|
114
|
+
type: :development
|
115
|
+
prerelease: false
|
116
|
+
version_requirements: *id007
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rcov
|
119
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
107
120
|
none: false
|
108
121
|
requirements:
|
109
122
|
- - ">="
|
@@ -111,9 +124,9 @@ dependencies:
|
|
111
124
|
segments:
|
112
125
|
- 0
|
113
126
|
version: "0"
|
114
|
-
type: :
|
127
|
+
type: :development
|
115
128
|
prerelease: false
|
116
|
-
version_requirements: *
|
129
|
+
version_requirements: *id008
|
117
130
|
description: Help keep track of stuff (good for electronics)
|
118
131
|
email: x@nofxx.com
|
119
132
|
executables:
|
@@ -121,14 +134,12 @@ executables:
|
|
121
134
|
extensions: []
|
122
135
|
|
123
136
|
extra_rdoc_files:
|
124
|
-
- LICENSE.txt
|
125
137
|
- README.rdoc
|
126
138
|
files:
|
127
139
|
- .document
|
128
140
|
- .rspec
|
129
141
|
- Gemfile
|
130
142
|
- Gemfile.lock
|
131
|
-
- LICENSE.txt
|
132
143
|
- README.rdoc
|
133
144
|
- Rakefile
|
134
145
|
- VERSION
|
@@ -136,12 +147,16 @@ files:
|
|
136
147
|
- lib/stockr.rb
|
137
148
|
- lib/stockr/assets/bundle.js
|
138
149
|
- lib/stockr/export.rb
|
150
|
+
- lib/stockr/import.rb
|
139
151
|
- lib/stockr/part.rb
|
140
152
|
- lib/stockr/store.rb
|
141
153
|
- lib/stockr/web.rb
|
154
|
+
- spec/data/export.txt
|
142
155
|
- spec/spec_helper.rb
|
156
|
+
- spec/stockr/export_spec.rb
|
143
157
|
- spec/stockr/part_spec.rb
|
144
158
|
- spec/stockr_spec.rb
|
159
|
+
- stockr.gemspec
|
145
160
|
has_rdoc: true
|
146
161
|
homepage: http://github.com/nofxx/stockr
|
147
162
|
licenses:
|
@@ -156,7 +171,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
171
|
requirements:
|
157
172
|
- - ">="
|
158
173
|
- !ruby/object:Gem::Version
|
159
|
-
hash: -
|
174
|
+
hash: -51961578438735344
|
160
175
|
segments:
|
161
176
|
- 0
|
162
177
|
version: "0"
|
@@ -177,5 +192,6 @@ specification_version: 3
|
|
177
192
|
summary: Keep track of all your stuff
|
178
193
|
test_files:
|
179
194
|
- spec/spec_helper.rb
|
195
|
+
- spec/stockr/export_spec.rb
|
180
196
|
- spec/stockr/part_spec.rb
|
181
197
|
- spec/stockr_spec.rb
|
data/LICENSE.txt
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
Copyright (c) 2010 Marcos Piccinini
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
a copy of this software and associated documentation files (the
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
9
|
-
the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
included in all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|