promo 0.0.1
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/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +122 -0
- data/Rakefile +1 -0
- data/config/locale/promo.en.yml +8 -0
- data/config/locale/promo.pt.yml +8 -0
- data/lib/generators/promo/install/install_generator.rb +20 -0
- data/lib/generators/promo/install/templates/1_create_promo_promocode.rb +19 -0
- data/lib/generators/promo/install/templates/2_create_promo_history.rb +10 -0
- data/lib/promo.rb +15 -0
- data/lib/promo/history.rb +8 -0
- data/lib/promo/promocode.rb +150 -0
- data/lib/promo/usage.rb +52 -0
- data/lib/promo/version.rb +3 -0
- data/promo.gemspec +24 -0
- data/spec/lib/promo/history_spec.rb +0 -0
- data/spec/lib/promo/promocode_spec.rb +0 -0
- data/spec/lib/promo/usage_spec.rb +0 -0
- data/spec/lib/promo_spec.rb +0 -0
- data/spec/spec_helper.rb +0 -0
- metadata +121 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Pedro Ivo
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# Promo
|
2
|
+
|
3
|
+
A gem to generate and use coupons and promocodes
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'promo'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install promo
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
First you need to create the migrations needed in the gem:
|
22
|
+
|
23
|
+
# rails generate promo:install
|
24
|
+
|
25
|
+
Objects must always be created through generate method instead using new.
|
26
|
+
Here you may define some options:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
promo = Promo::Promocode.generate(options)
|
30
|
+
|
31
|
+
options.multiple: false
|
32
|
+
options.quantity: 1
|
33
|
+
options.type: :percentage
|
34
|
+
options.status: :valid
|
35
|
+
options.expires: 4.weeks
|
36
|
+
options.code: SecureRandom.hex(4)
|
37
|
+
options.product: Some model with has_many :promocodes, as: :product
|
38
|
+
```
|
39
|
+
|
40
|
+
### Associated models
|
41
|
+
|
42
|
+
#### Cart / Order
|
43
|
+
While in a ecommerce, you might have a Cart and Order models (or any correspondency). thus you must associate these models in order to accept the promocodes associated.
|
44
|
+
|
45
|
+
In a simple example, we might define a Cart model as:
|
46
|
+
```ruby
|
47
|
+
class Cart < ActiveRecord::Base
|
48
|
+
has_many :cart_items, dependent: :destroy
|
49
|
+
has_one :promo_history, :class_name => 'Promo::History'
|
50
|
+
has_one :promocode, through: :promo_history
|
51
|
+
...
|
52
|
+
end
|
53
|
+
|
54
|
+
```
|
55
|
+
|
56
|
+
And then, after the checkout that Cart model suppose to be transformed (or coppied) to a Order object, something like:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class Order < ActiveRecord::Base
|
60
|
+
has_many :order_items, dependent: :destroy
|
61
|
+
has_one :promo_history, :class_name => 'Promo::History'
|
62
|
+
has_one :promocode, through: :promo_history
|
63
|
+
...
|
64
|
+
end
|
65
|
+
|
66
|
+
```
|
67
|
+
|
68
|
+
#### Products
|
69
|
+
|
70
|
+
As a promocode may be associated with any kind of product, in the model you want allow it, you must define as
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
class Product < ActiveRecord::Base
|
74
|
+
has_many :promocodes, as: :product
|
75
|
+
|
76
|
+
has_many :cart_item, as: :product
|
77
|
+
has_many :order_item, as: :product
|
78
|
+
|
79
|
+
has_many :carts, through: :cart_item
|
80
|
+
has_many :orders, through: :order_item
|
81
|
+
...
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
### Then you can calculate the discount by
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
class Cart < ActiveRecord::Base
|
89
|
+
def recalculate
|
90
|
+
self.update_attribute(:total_value, cart_items.map{ |i| i.product.value }.reduce(:+))
|
91
|
+
self.update_attribute(:discount_value, Promo::Usage.discount_for(promocode: self.promocode, product_list: product_list))
|
92
|
+
self.update_attribute(:final_value, self.total_value-self.discount_value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
### Example application
|
98
|
+
I've created a sample application with a basic product/cart/order model to test the gem, and also might be used as base for any simple ecommerce:
|
99
|
+
|
100
|
+
http://github.com/x1s/promo-example-cart
|
101
|
+
|
102
|
+
### Administration view
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
# if you require 'sinatra' you get the DSL extended to Object
|
106
|
+
gem 'sinatra', '>= 1.3.0', :require => nil
|
107
|
+
```
|
108
|
+
|
109
|
+
Add the following to your config/routes.rb:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
require 'promo/web'
|
113
|
+
mount Promo::Web => '/promo'
|
114
|
+
```
|
115
|
+
|
116
|
+
## Contributing
|
117
|
+
|
118
|
+
1. Fork it ( http://github.com/x1s/promo/fork )
|
119
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
120
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
121
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
122
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
promocode:
|
2
|
+
messages:
|
3
|
+
already_used: 'Promocode already used'
|
4
|
+
invalid: 'Invalid Promocode'
|
5
|
+
expired: 'This promocode has expired'
|
6
|
+
invalid_use: 'Invalid use of this promocode'
|
7
|
+
not_valid_for: 'This promocode is not valid for'
|
8
|
+
must_have_product: 'Product associated with this Promocode not found'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
promocode:
|
2
|
+
messages:
|
3
|
+
already_used: 'Promocode já utilizado'
|
4
|
+
invalid: 'Promocode inválido'
|
5
|
+
expired: 'Este promocode já expirou'
|
6
|
+
invalid_use: 'Uso invalido do cupão'
|
7
|
+
not_valid_for: 'Este cupão não é valido para este uso'
|
8
|
+
must_have_product: 'O produto associado ao promocode não foi encontrado'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Promo
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
desc 'Creates the models to the file'
|
7
|
+
|
8
|
+
def self.source_root
|
9
|
+
@_promo_source_root ||= File.expand_path("../templates", __FILE__)
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_migration_files
|
13
|
+
time = Time.now.strftime("%Y%m%d%H%M%S").to_i
|
14
|
+
template '1_create_promo_promocode.rb', File.join('db', 'migrate', "#{time}_create_promo_promocode.rb")
|
15
|
+
template '2_create_promo_history.rb', File.join('db', 'migrate', "#{time+1}_create_promo_history.rb")
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreatePromoPromocode < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :promo_promocodes do |t|
|
4
|
+
t.references :product, polymorphic: true, index: true
|
5
|
+
t.references :cart, polymorphic: true, index: true
|
6
|
+
t.references :order, polymorphic: true, index: true
|
7
|
+
t.integer :value, default: 0
|
8
|
+
t.integer :promo_type, null: false
|
9
|
+
t.integer :status, default: 1
|
10
|
+
t.integer :quantity, default: 1
|
11
|
+
t.integer :used, default: 0
|
12
|
+
t.datetime :expires, null: false
|
13
|
+
t.string :code, null: false, index: true
|
14
|
+
t.datetime :used_at
|
15
|
+
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class CreatePromoHistory < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :promo_histories do |t|
|
4
|
+
t.references :cart, polymorphic: true, index: true
|
5
|
+
t.references :order, polymorphic: true, index: true
|
6
|
+
t.references :promo_promocode, index: true
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/promo.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "promo/version"
|
2
|
+
|
3
|
+
require 'promo/promocode'
|
4
|
+
require 'promo/history'
|
5
|
+
require 'promo/usage'
|
6
|
+
|
7
|
+
module Promo
|
8
|
+
end
|
9
|
+
|
10
|
+
class PromocodeException < StandardError; end
|
11
|
+
class UsedPromocode < PromocodeException; end
|
12
|
+
class ExpiredPromocode < PromocodeException; end
|
13
|
+
class InvalidPromocode < PromocodeException; end
|
14
|
+
class InvalidPromoProduct < PromocodeException; end
|
15
|
+
|
@@ -0,0 +1,150 @@
|
|
1
|
+
module Promo
|
2
|
+
class Promocode < ActiveRecord::Base
|
3
|
+
self.table_name = 'promo_promocodes'
|
4
|
+
# Forbide direct creation of objects
|
5
|
+
private_class_method :create
|
6
|
+
|
7
|
+
belongs_to :product, polymorphic: true
|
8
|
+
|
9
|
+
has_many :histories, :class_name => 'Promo::History', :foreign_key => "promo_promocode_id"
|
10
|
+
has_many :carts, through: :histories
|
11
|
+
has_many :orders, through: :histories
|
12
|
+
|
13
|
+
validates :code, uniqueness: true
|
14
|
+
|
15
|
+
STATUS = { valid: 0, expired: 1, invalid: 2, used: 3}
|
16
|
+
TYPE = { percentage: 1, fixed_value: 0 }
|
17
|
+
|
18
|
+
scope :last, -> { where(status: STATUS[:valid]).order(id: :desc).limit(10) }
|
19
|
+
scope :used, -> { where(status: STATUS[:used]).order(used_at: :desc) }
|
20
|
+
scope :invalid, -> { where(status: STATUS[:invalid]).order(used_at: :desc) }
|
21
|
+
scope :expired, -> { where("status = ? OR expires < ?", STATUS[:expired], Time.now).order(expires: :desc) }
|
22
|
+
|
23
|
+
# Objects must always be created through generate method instead using new.
|
24
|
+
# here you may define some options:
|
25
|
+
# options.multiple: false
|
26
|
+
# options.quantity: 1
|
27
|
+
# options.type: :percentage
|
28
|
+
# options.status: :valid
|
29
|
+
# options.expires: 4.weeks
|
30
|
+
# options.code: SecureRandom.hex(4)
|
31
|
+
# options.product: Some model with has_many :promocodes, as: :product
|
32
|
+
# options.product_type: Associate the promocode with a class of product (any product of that class)
|
33
|
+
def self.generate(options={})
|
34
|
+
options[:multiple] ||= false
|
35
|
+
options[:quantity] ||= 1
|
36
|
+
options[:quantity] = 1 if options[:quantity].to_i <= 0
|
37
|
+
options[:promo_type] ||= TYPE[:percentage]
|
38
|
+
options[:status] ||= STATUS[:valid]
|
39
|
+
options[:expires] ||= Time.now + 4.weeks
|
40
|
+
|
41
|
+
if options[:code].blank?
|
42
|
+
options[:code] = generate_code
|
43
|
+
generated_code = true
|
44
|
+
else
|
45
|
+
generated_code = false
|
46
|
+
options[:code] = generate_code(0,options[:code])
|
47
|
+
end
|
48
|
+
|
49
|
+
multiple = options[:multiple]
|
50
|
+
options.delete(:multiple)
|
51
|
+
|
52
|
+
if multiple
|
53
|
+
ret = []
|
54
|
+
many = options[:quantity].to_i
|
55
|
+
options[:quantity] = 1
|
56
|
+
many.times do |item|
|
57
|
+
opt = options.dup
|
58
|
+
opt[:code] = generate_code if generated_code
|
59
|
+
opt[:code] = generate_code(0,options[:code]+item.to_s) if !generated_code
|
60
|
+
ret << create!(opt)
|
61
|
+
end
|
62
|
+
return ret
|
63
|
+
end
|
64
|
+
create!(options)
|
65
|
+
end
|
66
|
+
|
67
|
+
#--------------------------
|
68
|
+
|
69
|
+
def use (options={})
|
70
|
+
is_valid? options
|
71
|
+
|
72
|
+
self.used += 1
|
73
|
+
self.status = STATUS[:used] if self.quantity == self.used
|
74
|
+
self.used_at = Time.now
|
75
|
+
save
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
def invalidate!
|
80
|
+
update_attributes(status: STATUS[:invalid], used_at: Time.now)
|
81
|
+
end
|
82
|
+
|
83
|
+
#--------------------------
|
84
|
+
|
85
|
+
def has_product?
|
86
|
+
!self.product.nil?
|
87
|
+
end
|
88
|
+
|
89
|
+
def is_percentage?
|
90
|
+
self.promo_type == TYPE[:percentage]
|
91
|
+
end
|
92
|
+
|
93
|
+
def is_fixed_value?
|
94
|
+
self.promo_type == TYPE[:fixed_value]
|
95
|
+
end
|
96
|
+
|
97
|
+
def is_expired?
|
98
|
+
return true if self.status == STATUS[:expired]
|
99
|
+
return false if self.expires > Time.now
|
100
|
+
update_attribute(:status, STATUS[:expired])
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Validates the use of this promocode
|
106
|
+
# Options:
|
107
|
+
# product_list: Array with products, mandatory when the promocode is associated with
|
108
|
+
# a specific product or a specific category of products
|
109
|
+
#
|
110
|
+
def is_valid?(options={})
|
111
|
+
raise UsedPromocode.new 'promocode.messages.already_used' if self.status == STATUS[:used]
|
112
|
+
raise InvalidPromocode.new 'promocode.messages.invalid' if self.status != STATUS[:valid]
|
113
|
+
raise ExpiredPromocode.new 'promocode.messages.expired' if is_expired?
|
114
|
+
|
115
|
+
# Validating use with a specific product associated
|
116
|
+
if self.has_product?
|
117
|
+
logger.debug "#------------ Promocode associated with a product"
|
118
|
+
raise InvalidPromocode.new 'promocode.messages.invalid_use' if options[:product_list].nil?
|
119
|
+
if self.product && !options[:product_list].include?(self.product)
|
120
|
+
logger.debug "#--------------- Product associated not found on the list"
|
121
|
+
raise InvalidPromoProduct.new 'promocode.messages.not_valid_for'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Validating use with when a class of product is associated with the promocode
|
126
|
+
# not a specific product (no product_id defined)
|
127
|
+
if self.product_id.nil? && !self.product_type.nil?
|
128
|
+
logger.debug "#------------ Promocode associated with a class"
|
129
|
+
raise InvalidPromocode.new 'promocode.messages.invalid_use' if options[:product_list].nil?
|
130
|
+
if options[:product_list].none? { |p| p.class.to_s == self.product_type }
|
131
|
+
logger.debug "#--------------- Class associated not found on the list"
|
132
|
+
raise InvalidPromoProduct.new 'promocode.messages.must_have_course'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
# Returns the promocode if it's valid
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
139
|
+
# Generate random codes
|
140
|
+
def self.generate_code(size=4,code="")
|
141
|
+
code = SecureRandom.hex(size) if code.empty?
|
142
|
+
code = code+SecureRandom.hex(size) unless code.empty?
|
143
|
+
# Validates if the code is already created, then add something to the name
|
144
|
+
if Promo::Promocode.where(code: code).first
|
145
|
+
code = code+SecureRandom.hex(1)
|
146
|
+
end
|
147
|
+
code
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
data/lib/promo/usage.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Promo
|
2
|
+
class Usage
|
3
|
+
class << self
|
4
|
+
# Validates the use of any promocode
|
5
|
+
# Options (Hash):
|
6
|
+
# code: string with the code used
|
7
|
+
# product_list: array with the products to be evaluated
|
8
|
+
def validate (options={})
|
9
|
+
promocode = Promo::Promocode.where(code: options[:code]).first
|
10
|
+
raise InvalidPromocode.new 'promocode.messages.invalid' if promocode.nil?
|
11
|
+
promocode.is_valid? options
|
12
|
+
end
|
13
|
+
|
14
|
+
# Calculates the discounts to any list of products
|
15
|
+
# Options (Hash):
|
16
|
+
# promocode: Pomo::Promocode object
|
17
|
+
# product_list: array with the products to be evaluated
|
18
|
+
def discount_for (options={})
|
19
|
+
return 0 if options[:promocode].nil?
|
20
|
+
promocode = options[:promocode]
|
21
|
+
product_list = options[:product_list]
|
22
|
+
|
23
|
+
return discount_for_product(promocode, product_list) if promocode.has_product?
|
24
|
+
if promocode.is_percentage?
|
25
|
+
calculate_percentage product_list.map(&:value).reduce(:+), promocode.value
|
26
|
+
else
|
27
|
+
promocode.value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Calculates the dicount for a specific product in the list
|
32
|
+
# previously associated with the current promocode
|
33
|
+
# Parameters:
|
34
|
+
# promocode: Pomo::Promocode object
|
35
|
+
# product_list: array with the products to be evaluated
|
36
|
+
def discount_for_product promocode, product_list
|
37
|
+
product = promocode.product
|
38
|
+
return 0 unless product_list.include? product
|
39
|
+
if promocode.is_percentage?
|
40
|
+
calculate_percentage(product.value,promocode.value)
|
41
|
+
else
|
42
|
+
promocode.value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#calculates the percentage to a specific value
|
47
|
+
def calculate_percentage(value, percent)
|
48
|
+
(value * (percent.to_f/100)).to_i
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/promo.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'promo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "promo"
|
8
|
+
spec.version = Promo::VERSION
|
9
|
+
spec.authors = ["Pedro Ivo"]
|
10
|
+
spec.email = ["pedroivo@x1s.eti.br"]
|
11
|
+
spec.summary = %q{Create coupons and promocodes}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = "http://github.com/x1s"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/spec_helper.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: promo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Pedro Ivo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-02-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.5'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.5'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: ''
|
63
|
+
email:
|
64
|
+
- pedroivo@x1s.eti.br
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- .rspec
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE.txt
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- config/locale/promo.en.yml
|
76
|
+
- config/locale/promo.pt.yml
|
77
|
+
- lib/generators/promo/install/install_generator.rb
|
78
|
+
- lib/generators/promo/install/templates/1_create_promo_promocode.rb
|
79
|
+
- lib/generators/promo/install/templates/2_create_promo_history.rb
|
80
|
+
- lib/promo.rb
|
81
|
+
- lib/promo/history.rb
|
82
|
+
- lib/promo/promocode.rb
|
83
|
+
- lib/promo/usage.rb
|
84
|
+
- lib/promo/version.rb
|
85
|
+
- promo.gemspec
|
86
|
+
- spec/lib/promo/history_spec.rb
|
87
|
+
- spec/lib/promo/promocode_spec.rb
|
88
|
+
- spec/lib/promo/usage_spec.rb
|
89
|
+
- spec/lib/promo_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
homepage: http://github.com/x1s
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 1.8.23
|
113
|
+
signing_key:
|
114
|
+
specification_version: 3
|
115
|
+
summary: Create coupons and promocodes
|
116
|
+
test_files:
|
117
|
+
- spec/lib/promo/history_spec.rb
|
118
|
+
- spec/lib/promo/promocode_spec.rb
|
119
|
+
- spec/lib/promo/usage_spec.rb
|
120
|
+
- spec/lib/promo_spec.rb
|
121
|
+
- spec/spec_helper.rb
|