boutique 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/README.md +1 -2
- data/boutique +72 -1
- data/config.ru +7 -0
- data/lib/boutique.rb +2 -1
- data/test/model_test.rb +1 -0
- metadata +30 -8
data/README.md
CHANGED
@@ -74,7 +74,7 @@ the included command line application.
|
|
74
74
|
% boutique --stats productcode
|
75
75
|
% boutique --expire
|
76
76
|
% boutique --expire id
|
77
|
-
% boutique --
|
77
|
+
% boutique --delete id
|
78
78
|
|
79
79
|
Development
|
80
80
|
===========
|
@@ -85,7 +85,6 @@ via `rake`.
|
|
85
85
|
TODO
|
86
86
|
====
|
87
87
|
|
88
|
-
* boutique command line
|
89
88
|
* email customer + recover action
|
90
89
|
* email exceptions to developer
|
91
90
|
|
data/boutique
CHANGED
@@ -2,15 +2,82 @@
|
|
2
2
|
require 'optparse'
|
3
3
|
require File.expand_path('lib/boutique', File.dirname(__FILE__))
|
4
4
|
require 'dm-migrations'
|
5
|
+
require 'date'
|
6
|
+
require 'fileutils'
|
5
7
|
|
6
8
|
ENV['BOUTIQUE_CMD'] = '1'
|
7
|
-
load(ENV['BOUTIQUE_CONFIG'] || 'config.ru')
|
8
9
|
|
9
10
|
module Boutique
|
10
11
|
class Command
|
12
|
+
def self.delete(id)
|
13
|
+
purchase = expire(id)
|
14
|
+
purchase.destroy if !purchase.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.expire(id)
|
18
|
+
load_config
|
19
|
+
purchase = Boutique::Purchase.get(id.to_i)
|
20
|
+
if purchase.nil?
|
21
|
+
puts "Purchase #{id} not found"
|
22
|
+
return
|
23
|
+
end
|
24
|
+
purchase.downloads.each do |download|
|
25
|
+
FileUtils.rm_rf(File.dirname(
|
26
|
+
"#{Boutique.config.download_dir}#{download.sub(Boutique.config.download_path, '')}"))
|
27
|
+
end
|
28
|
+
purchase
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.expire_old
|
32
|
+
load_config
|
33
|
+
threshold = (Date.today - 1).strftime("%Y%m%d")
|
34
|
+
dirs = Dir.glob("#{Boutique.config.download_dir}/*").
|
35
|
+
map {|f| File.basename(f) }.
|
36
|
+
select {|f| f < threshold }
|
37
|
+
dirs.each {|d| FileUtils.rm_rf("#{Boutique.config.download_dir}/#{d}") }
|
38
|
+
|
39
|
+
Boutique::Purchase.all(
|
40
|
+
:transaction_id => nil,
|
41
|
+
:created_at.lt => (Date.today - 1)).destroy
|
42
|
+
end
|
43
|
+
|
11
44
|
def self.migrate
|
45
|
+
load_config rescue DataObjects::SyntaxError
|
12
46
|
DataMapper.auto_upgrade!
|
13
47
|
end
|
48
|
+
|
49
|
+
def self.stats(code)
|
50
|
+
load_config
|
51
|
+
product = Boutique::Product.first(:code => code)
|
52
|
+
if product.nil?
|
53
|
+
puts "Product #{code} not found"
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "Code: #{product.code}"
|
58
|
+
puts "Name: #{product.name}"
|
59
|
+
puts "Files: #{product.files.join("\n ")}"
|
60
|
+
printf("Price: $%.2f\n" % product.price)
|
61
|
+
puts "Return: #{product.return_url}"
|
62
|
+
|
63
|
+
puts ('-' * 40)
|
64
|
+
|
65
|
+
purchases = product.purchases
|
66
|
+
puts "* #{purchases.select {|p| p.completed?}.size} purchases have been completed"
|
67
|
+
puts "* #{purchases.reduce(0) {|sum,p| sum + p.counter}} downloads linked"
|
68
|
+
|
69
|
+
puts ('-' * 40)
|
70
|
+
|
71
|
+
puts "id, links, email" if purchases.size > 0
|
72
|
+
purchases.sort_by {|p| p.counter }.reverse.each do |purchase|
|
73
|
+
puts "* #{purchase.id}, #{purchase.counter}, #{purchase.email}" if purchase.completed?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def self.load_config
|
79
|
+
load(ENV['BOUTIQUE_CONFIG'] || 'config.ru')
|
80
|
+
end
|
14
81
|
end
|
15
82
|
end
|
16
83
|
|
@@ -18,7 +85,11 @@ ARGV.options do |o|
|
|
18
85
|
o.set_summary_indent(' ')
|
19
86
|
o.banner = "Usage: #{File.basename($0)} [OPTION]"
|
20
87
|
o.define_head "Admin for boutique"
|
88
|
+
o.on('-d', '--delete [id]', 'delete purchase') { |id| Boutique::Command.delete(id); exit }
|
89
|
+
o.on('-e', '--expire [id]', 'expire purchase') { |id| Boutique::Command.expire(id); exit }
|
90
|
+
o.on('-E', '--expire-old', 'expire old data') { Boutique::Command.expire_old; exit }
|
21
91
|
o.on('-m', '--migrate', 'initial migration') { Boutique::Command.migrate; exit }
|
92
|
+
o.on('-s', '--stats [product]', String, 'show stats on product') { |p| Boutique::Command.stats(p); exit }
|
22
93
|
o.on('-h', '--help', 'show this help message') { puts o; exit }
|
23
94
|
o.parse!
|
24
95
|
puts o
|
data/config.ru
CHANGED
@@ -15,4 +15,11 @@ Boutique.configure(!ENV['BOUTIQUE_CMD'].nil?) do |c|
|
|
15
15
|
c.pp_url 'http://localhost'
|
16
16
|
end
|
17
17
|
|
18
|
+
Boutique.product('readme') do |p|
|
19
|
+
p.name 'README document'
|
20
|
+
p.files File.expand_path('README.md', File.dirname(__FILE__))
|
21
|
+
p.price 1.5
|
22
|
+
p.return_url 'http://localhost'
|
23
|
+
end
|
24
|
+
|
18
25
|
run Boutique::App if !ENV['BOUTIQUE_CMD']
|
data/lib/boutique.rb
CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'sinatra/base'
|
3
3
|
require 'dm-core'
|
4
4
|
require 'dm-types'
|
5
|
+
require 'dm-timestamps'
|
5
6
|
require 'cgi'
|
6
7
|
require 'date'
|
7
8
|
require 'digest/sha1'
|
@@ -9,7 +10,7 @@ require 'json'
|
|
9
10
|
require 'openssl'
|
10
11
|
|
11
12
|
module Boutique
|
12
|
-
VERSION = '0.0.
|
13
|
+
VERSION = '0.0.3'
|
13
14
|
|
14
15
|
class << self
|
15
16
|
def configure(setup_db=true)
|
data/test/model_test.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boutique
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: .
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
16
|
-
requirement: &
|
16
|
+
requirement: &70293142732840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,32 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70293142732840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: data_mapper
|
27
|
+
requirement: &70293142731600 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70293142731600
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: pony
|
38
|
+
requirement: &70293142730680 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70293142730680
|
25
47
|
- !ruby/object:Gem::Dependency
|
26
48
|
name: minitest
|
27
|
-
requirement: &
|
49
|
+
requirement: &70293142729840 !ruby/object:Gem::Requirement
|
28
50
|
none: false
|
29
51
|
requirements:
|
30
52
|
- - ! '>='
|
@@ -32,10 +54,10 @@ dependencies:
|
|
32
54
|
version: '0'
|
33
55
|
type: :development
|
34
56
|
prerelease: false
|
35
|
-
version_requirements: *
|
57
|
+
version_requirements: *70293142729840
|
36
58
|
- !ruby/object:Gem::Dependency
|
37
59
|
name: shotgun
|
38
|
-
requirement: &
|
60
|
+
requirement: &70293142729040 !ruby/object:Gem::Requirement
|
39
61
|
none: false
|
40
62
|
requirements:
|
41
63
|
- - ! '>='
|
@@ -43,7 +65,7 @@ dependencies:
|
|
43
65
|
version: '0'
|
44
66
|
type: :development
|
45
67
|
prerelease: false
|
46
|
-
version_requirements: *
|
68
|
+
version_requirements: *70293142729040
|
47
69
|
description: A Sinatra module which accepts payments via PayPal and gives customers
|
48
70
|
a secret URL to download your product.
|
49
71
|
email:
|