merchant_sidekick 0.4.2
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 +12 -0
- data/Changelog.md +38 -0
- data/Gemfile +2 -0
- data/MIT-LICENSE +19 -0
- data/README.md +88 -0
- data/Rakefile +10 -0
- data/lib/merchant_sidekick.rb +45 -0
- data/lib/merchant_sidekick/active_merchant/credit_card_payment.rb +117 -0
- data/lib/merchant_sidekick/active_merchant/gateways/authorize_net_gateway.rb +26 -0
- data/lib/merchant_sidekick/active_merchant/gateways/base.rb +29 -0
- data/lib/merchant_sidekick/active_merchant/gateways/bogus_gateway.rb +19 -0
- data/lib/merchant_sidekick/active_merchant/gateways/paypal_gateway.rb +43 -0
- data/lib/merchant_sidekick/addressable/address.rb +400 -0
- data/lib/merchant_sidekick/addressable/addressable.rb +353 -0
- data/lib/merchant_sidekick/buyer.rb +99 -0
- data/lib/merchant_sidekick/gateway.rb +81 -0
- data/lib/merchant_sidekick/install.rb +19 -0
- data/lib/merchant_sidekick/invoice.rb +179 -0
- data/lib/merchant_sidekick/line_item.rb +128 -0
- data/lib/merchant_sidekick/migrations/addressable.rb +47 -0
- data/lib/merchant_sidekick/migrations/billing.rb +100 -0
- data/lib/merchant_sidekick/migrations/shopping_cart.rb +28 -0
- data/lib/merchant_sidekick/money.rb +38 -0
- data/lib/merchant_sidekick/order.rb +244 -0
- data/lib/merchant_sidekick/payment.rb +59 -0
- data/lib/merchant_sidekick/purchase_invoice.rb +180 -0
- data/lib/merchant_sidekick/purchase_order.rb +350 -0
- data/lib/merchant_sidekick/railtie.rb +7 -0
- data/lib/merchant_sidekick/sales_invoice.rb +56 -0
- data/lib/merchant_sidekick/sales_order.rb +122 -0
- data/lib/merchant_sidekick/sellable.rb +88 -0
- data/lib/merchant_sidekick/seller.rb +93 -0
- data/lib/merchant_sidekick/shopping_cart/cart.rb +225 -0
- data/lib/merchant_sidekick/shopping_cart/line_item.rb +152 -0
- data/lib/merchant_sidekick/version.rb +3 -0
- data/merchant_sidekick.gemspec +37 -0
- data/spec/address_spec.rb +153 -0
- data/spec/addressable_spec.rb +250 -0
- data/spec/buyer_spec.rb +203 -0
- data/spec/cart_line_item_spec.rb +58 -0
- data/spec/cart_spec.rb +213 -0
- data/spec/config/merchant_sidekick.yml +10 -0
- data/spec/credit_card_payment_spec.rb +175 -0
- data/spec/fixtures/addresses.yml +97 -0
- data/spec/fixtures/line_items.yml +18 -0
- data/spec/fixtures/orders.yml +24 -0
- data/spec/fixtures/payments.yml +17 -0
- data/spec/fixtures/products.yml +12 -0
- data/spec/fixtures/users.yml +11 -0
- data/spec/gateway_spec.rb +136 -0
- data/spec/invoice_spec.rb +79 -0
- data/spec/line_item_spec.rb +65 -0
- data/spec/order_spec.rb +85 -0
- data/spec/payment_spec.rb +14 -0
- data/spec/purchase_invoice_spec.rb +70 -0
- data/spec/purchase_order_spec.rb +191 -0
- data/spec/sales_invoice_spec.rb +58 -0
- data/spec/sales_order_spec.rb +107 -0
- data/spec/schema.rb +28 -0
- data/spec/sellable_spec.rb +34 -0
- data/spec/seller_spec.rb +201 -0
- data/spec/spec_helper.rb +255 -0
- metadata +201 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
class CreateMerchantSidekickAddressableTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :addresses do |t|
|
4
|
+
t.integer "addressable_id"
|
5
|
+
t.string "addressable_type"
|
6
|
+
t.integer "academic_title_id"
|
7
|
+
t.string "gender", :limit => 1
|
8
|
+
t.string "first_name"
|
9
|
+
t.string "middle_name"
|
10
|
+
t.string "last_name"
|
11
|
+
t.text "street"
|
12
|
+
t.string "city"
|
13
|
+
t.string "postal_code"
|
14
|
+
t.string "province"
|
15
|
+
t.string "province_code", :limit => 2
|
16
|
+
t.string "country"
|
17
|
+
t.string "country_code", :limit => 2
|
18
|
+
t.string "company_name"
|
19
|
+
t.text "note"
|
20
|
+
t.string "phone"
|
21
|
+
t.string "mobile"
|
22
|
+
t.string "fax"
|
23
|
+
t.string "type"
|
24
|
+
end
|
25
|
+
|
26
|
+
add_index :addresses, ["academic_title_id"], :name => "index_addresses_on_academic_title_id"
|
27
|
+
add_index :addresses, ["addressable_id", "addressable_type"], :name => "fk_addresses_addressable"
|
28
|
+
add_index :addresses, ["city"], :name => "index_addresses_on_city"
|
29
|
+
add_index :addresses, ["company_name"], :name => "index_addresses_on_company_name"
|
30
|
+
add_index :addresses, ["country"], :name => "index_addresses_on_country"
|
31
|
+
add_index :addresses, ["country_code"], :name => "index_addresses_on_country_code"
|
32
|
+
add_index :addresses, ["fax"], :name => "index_addresses_on_fax"
|
33
|
+
add_index :addresses, ["first_name"], :name => "index_addresses_on_first_name"
|
34
|
+
add_index :addresses, ["gender"], :name => "index_addresses_on_gender"
|
35
|
+
add_index :addresses, ["last_name"], :name => "index_addresses_on_last_name"
|
36
|
+
add_index :addresses, ["middle_name"], :name => "index_addresses_on_middle_name"
|
37
|
+
add_index :addresses, ["mobile"], :name => "index_addresses_on_mobile"
|
38
|
+
add_index :addresses, ["phone"], :name => "index_addresses_on_phone"
|
39
|
+
add_index :addresses, ["province"], :name => "index_addresses_on_state"
|
40
|
+
add_index :addresses, ["province_code"], :name => "index_addresses_on_state_code"
|
41
|
+
add_index :addresses, ["type"], :name => "index_addresses_on_type"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.down
|
45
|
+
drop_table :addresses
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class CreateMerchantSidekickBillingTables < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
create_table :line_items do |t|
|
5
|
+
t.integer "order_id"
|
6
|
+
t.integer "invoice_id"
|
7
|
+
t.integer "sellable_id"
|
8
|
+
t.string "sellable_type"
|
9
|
+
t.integer "net_cents", :default => 0, :null => false
|
10
|
+
t.integer "tax_cents", :default => 0, :null => false
|
11
|
+
t.integer "gross_cents", :default => 0, :null => false
|
12
|
+
t.string "currency", :default => "USD", :null => false
|
13
|
+
t.decimal "tax_rate", :precision => 15, :scale => 10, :default => 0.0, :null => false
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
add_index :line_items, "order_id"
|
17
|
+
add_index :line_items, "invoice_id"
|
18
|
+
add_index :line_items, ["sellable_id", "sellable_type"]
|
19
|
+
|
20
|
+
|
21
|
+
create_table :orders do |t|
|
22
|
+
t.integer "buyer_id"
|
23
|
+
t.string "buyer_type"
|
24
|
+
t.integer "seller_id"
|
25
|
+
t.string "seller_type"
|
26
|
+
t.integer "invoice_id"
|
27
|
+
t.integer "net_cents", :default => 0, :null => false
|
28
|
+
t.integer "tax_cents", :default => 0, :null => false
|
29
|
+
t.integer "gross_cents", :default => 0, :null => false
|
30
|
+
t.string "currency", :limit => 3, :default => "USD", :null => false
|
31
|
+
t.string "type"
|
32
|
+
t.string "status", :default => "created", :null => false
|
33
|
+
t.string "number"
|
34
|
+
t.string "description"
|
35
|
+
t.datetime "canceled_at"
|
36
|
+
t.timestamps
|
37
|
+
end
|
38
|
+
add_index :orders, ["buyer_id", "buyer_type"]
|
39
|
+
add_index :orders, ["seller_id", "seller_type"]
|
40
|
+
add_index :orders, "status"
|
41
|
+
add_index :orders, "type"
|
42
|
+
|
43
|
+
|
44
|
+
create_table :invoices do |t|
|
45
|
+
t.integer "buyer_id"
|
46
|
+
t.string "buyer_type"
|
47
|
+
t.integer "seller_id"
|
48
|
+
t.string "seller_type"
|
49
|
+
t.integer "net_cents", :default => 0, :null => false
|
50
|
+
t.integer "tax_cents", :default => 0, :null => false
|
51
|
+
t.integer "gross_cents", :default => 0, :null => false
|
52
|
+
t.string "currency", :default => "USD", :null => false
|
53
|
+
t.string "type"
|
54
|
+
t.string "number"
|
55
|
+
t.string "status", :default => "pending", :null => false
|
56
|
+
t.datetime "paid_at"
|
57
|
+
t.integer "order_id"
|
58
|
+
t.datetime "authorized_at"
|
59
|
+
t.timestamps
|
60
|
+
end
|
61
|
+
add_index :invoices, ["buyer_id", "buyer_type"]
|
62
|
+
add_index :invoices, "number"
|
63
|
+
add_index :invoices, "order_id"
|
64
|
+
add_index :invoices, ["seller_id", "seller_type"]
|
65
|
+
add_index :invoices, "type"
|
66
|
+
|
67
|
+
|
68
|
+
#--- payments
|
69
|
+
create_table :payments do |t|
|
70
|
+
t.integer "payable_id"
|
71
|
+
t.string "payable_type"
|
72
|
+
t.boolean "success"
|
73
|
+
t.string "reference"
|
74
|
+
t.string "message"
|
75
|
+
t.string "action"
|
76
|
+
t.string "params"
|
77
|
+
t.boolean "test"
|
78
|
+
t.integer "cents", :default => 0, :null => false
|
79
|
+
t.string "currency", :limit => 3, :default => "USD", :null => false
|
80
|
+
t.integer "position"
|
81
|
+
t.string "type"
|
82
|
+
t.string "paypal_account"
|
83
|
+
t.string "uuid"
|
84
|
+
t.timestamps
|
85
|
+
end
|
86
|
+
add_index :payments, "action"
|
87
|
+
add_index :payments, ["payable_id", "payable_type"]
|
88
|
+
add_index :payments, "position"
|
89
|
+
add_index :payments, "reference"
|
90
|
+
add_index :payments, "uuid"
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.down
|
94
|
+
drop_table :gateways
|
95
|
+
drop_table :payments
|
96
|
+
drop_table :invoices
|
97
|
+
drop_table :orders
|
98
|
+
drop_table :line_items
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class CreateMerchantSidekickShoppingCartTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :cart_line_items do |t|
|
4
|
+
t.string "item_number"
|
5
|
+
t.string "name"
|
6
|
+
t.string "description"
|
7
|
+
t.integer "quantity", :default => 1, :null => false
|
8
|
+
t.string "unit", :default => "piece", :null => false
|
9
|
+
t.integer "pieces", :default => 0, :null => false
|
10
|
+
t.integer "cents", :default => 0, :null => false
|
11
|
+
t.string "currency", :limit => 3, :default => "USD", :null => false
|
12
|
+
t.boolean "taxable", :default => false, :null => false
|
13
|
+
t.integer "product_id", :null => false
|
14
|
+
t.string "product_type", :null => false
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
add_index :cart_line_items, "item_number"
|
18
|
+
add_index :cart_line_items, "name"
|
19
|
+
add_index :cart_line_items, "unit"
|
20
|
+
add_index :cart_line_items, "pieces"
|
21
|
+
add_index :cart_line_items, ["product_id", "product_type"]
|
22
|
+
add_index :cart_line_items, "quantity"
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.down
|
26
|
+
drop_table :cart_line_items
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module MerchantSidekick
|
2
|
+
module Money
|
3
|
+
def money(name, options = {})
|
4
|
+
options = {:cents => "#{name}_cents".to_sym}.merge(options)
|
5
|
+
mapping = [[options[:cents].to_s, 'cents']]
|
6
|
+
mapping << ([options[:currency].to_s, 'currency_as_string']) if options[:currency]
|
7
|
+
|
8
|
+
composed_of name,
|
9
|
+
:class_name => "::Money",
|
10
|
+
:mapping => mapping,
|
11
|
+
:constructor => Proc.new {|cents, currency| ::Money.new(cents || 0, currency || ::Money.default_currency)},
|
12
|
+
:converter => Proc.new {|value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money")}
|
13
|
+
|
14
|
+
if options[:currency]
|
15
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
16
|
+
def currency
|
17
|
+
::Money::Currency.wrap(self[:#{options[:currency]}])
|
18
|
+
end
|
19
|
+
|
20
|
+
def currency_as_string
|
21
|
+
self[:#{options[:currency]}]
|
22
|
+
end
|
23
|
+
END
|
24
|
+
else
|
25
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
26
|
+
def currency
|
27
|
+
::Money.default_currency
|
28
|
+
end
|
29
|
+
|
30
|
+
def currency_as_string
|
31
|
+
::Money.default_currency.to_s
|
32
|
+
end
|
33
|
+
END
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
# Baseclass of all orders which can be:
|
2
|
+
#
|
3
|
+
# * Purchase Order: outbound orders, i.e. a user buys a product from the merchant
|
4
|
+
# * Sales Order: inbound order i.e. the merchant sells a product to a user
|
5
|
+
#
|
6
|
+
module MerchantSidekick
|
7
|
+
class Order < ActiveRecord::Base
|
8
|
+
include AASM
|
9
|
+
self.table_name = "orders"
|
10
|
+
|
11
|
+
belongs_to :seller, :polymorphic => true
|
12
|
+
belongs_to :buyer, :polymorphic => true
|
13
|
+
has_many :line_items, :dependent => :destroy, :class_name => "::MerchantSidekick::LineItem"
|
14
|
+
has_many :payments, :as => :payable, :class_name => "::MerchantSidekick::Payment"
|
15
|
+
has_many :invoices, :foreign_key => :order_id, :class_name => "::MerchantSidekick::Invoice"
|
16
|
+
|
17
|
+
money :net_amount, :cents => :net_cents, :currency => :currency
|
18
|
+
money :tax_amount, :cents => :tax_cents, :currency => :currency
|
19
|
+
money :gross_amount, :cents => :gross_cents, :currency => :currency
|
20
|
+
has_address :origin, :billing, :shipping
|
21
|
+
|
22
|
+
#--- state machine
|
23
|
+
aasm :column => "status" do
|
24
|
+
state :created, :enter => :enter_created, :exit => :exit_created, :initial => true
|
25
|
+
state :pending, :enter => :enter_pending, :exit => :exit_pending
|
26
|
+
state :approved, :enter => :enter_approved, :exit => :exit_approved
|
27
|
+
state :shipping, :enter => :enter_shipping, :exit => :exit_shipping
|
28
|
+
state :shipped, :enter => :enter_shipped, :exit => :exit_shipped
|
29
|
+
state :received, :enter => :enter_received, :exit => :exit_received
|
30
|
+
state :returning, :enter => :enter_returning, :exit => :exit_returning
|
31
|
+
state :returned, :enter => :enter_returned, :exit => :exit_returned
|
32
|
+
state :refunded, :enter => :enter_refunded, :exit => :exit_refunded
|
33
|
+
state :canceled, :enter => :enter_canceled, :exit => :exit_canceled
|
34
|
+
|
35
|
+
event :process_payment do
|
36
|
+
transitions :from => :created, :to => :pending, :guard => :guard_process_payment_from_created
|
37
|
+
end
|
38
|
+
|
39
|
+
event :approve_payment do
|
40
|
+
transitions :from => :pending, :to => :approved, :guard => :guard_approve_payment_from_pending
|
41
|
+
end
|
42
|
+
|
43
|
+
event :process_shipping do
|
44
|
+
transitions :from => :approved, :to => :shipping, :guard => :guard_process_shipping_from_approved
|
45
|
+
end
|
46
|
+
|
47
|
+
event :ship do
|
48
|
+
transitions :from => :shipping, :to => :shipped, :guard => :guard_ship_from_shipping
|
49
|
+
end
|
50
|
+
|
51
|
+
event :confirm_reception do
|
52
|
+
transitions :from => :shipped, :to => :received, :guard => :guard_confirm_reception_from_shipped
|
53
|
+
end
|
54
|
+
|
55
|
+
event :reject do
|
56
|
+
transitions :from => :received, :to => :returning, :guard => :guard_reject_from_received
|
57
|
+
end
|
58
|
+
|
59
|
+
event :confirm_return do
|
60
|
+
transitions :from => :returning, :to => :returned, :guard => :guard_confirm_return_from_returning
|
61
|
+
transitions :from => :shipped, :to => :returned, :guard => :guard_confirm_return_from_shipped
|
62
|
+
end
|
63
|
+
|
64
|
+
event :refund do
|
65
|
+
transitions :from => :returned, :to => :refunded, :guard => :guard_refund_from_returned
|
66
|
+
end
|
67
|
+
|
68
|
+
event :cancel do
|
69
|
+
transitions :from => :created, :to => :canceled, :guard => :guard_cancel_from_created
|
70
|
+
transitions :from => :pending, :to => :canceled, :guard => :guard_cancel_from_pending
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# state transition callbacks, to be overwritten
|
75
|
+
def enter_created; end
|
76
|
+
def enter_pending; end
|
77
|
+
def enter_approved; end
|
78
|
+
def enter_shipping; end
|
79
|
+
def enter_shipped; end
|
80
|
+
def enter_received; end
|
81
|
+
def enter_returning; end
|
82
|
+
def enter_returned; end
|
83
|
+
def enter_refunded; end
|
84
|
+
def enter_canceled; end
|
85
|
+
|
86
|
+
def exit_created; end
|
87
|
+
def exit_pending; end
|
88
|
+
def exit_approved; end
|
89
|
+
def exit_shipping; end
|
90
|
+
def exit_shipped; end
|
91
|
+
def exit_received; end
|
92
|
+
def exit_returning; end
|
93
|
+
def exit_returned; end
|
94
|
+
def exit_refunded; end
|
95
|
+
def exit_canceled; end
|
96
|
+
|
97
|
+
# event guard callbacks, to be overwritten
|
98
|
+
def guard_process_payment_from_created; true; end
|
99
|
+
def guard_approve_payment_from_pending; true; end
|
100
|
+
def guard_process_shipping_from_approved; true; end
|
101
|
+
def guard_ship_from_shipping; true; end
|
102
|
+
def guard_confirm_reception_from_shipped; true; end
|
103
|
+
def guard_reject_from_received; true; end
|
104
|
+
def guard_confirm_return_from_returning; true; end
|
105
|
+
def guard_confirm_return_from_shipped; true; end
|
106
|
+
def guard_refund_from_returned; true; end
|
107
|
+
def guard_cancel_from_created; true; end
|
108
|
+
def guard_cancel_from_pending; true; end
|
109
|
+
|
110
|
+
#--- callbacks
|
111
|
+
before_save :total, :number
|
112
|
+
|
113
|
+
#--- class methods
|
114
|
+
class << self
|
115
|
+
|
116
|
+
# hex digest 16 char in length
|
117
|
+
# TODO change this to customize number schema
|
118
|
+
def generate_unique_id
|
119
|
+
value = Digest::MD5.hexdigest("#{Time.now.utc.to_i}#{rand(2 ** 128)}")[0..6]
|
120
|
+
value.encode! 'utf-8'
|
121
|
+
value
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
#--- instance methods
|
127
|
+
|
128
|
+
alias_method :current_state, :aasm_current_state
|
129
|
+
|
130
|
+
def number
|
131
|
+
self[:number] ||= Order.generate_unique_id
|
132
|
+
end
|
133
|
+
|
134
|
+
# abstract overriden in sublcasses
|
135
|
+
# returns the invoice instance
|
136
|
+
def invoice
|
137
|
+
raise "deprecated as we use has_many :invoices association"
|
138
|
+
end
|
139
|
+
|
140
|
+
# abstract to be overriden inside puchase and sales orders
|
141
|
+
def build_invoice
|
142
|
+
raise "override in purchase_order or sales_order"
|
143
|
+
end
|
144
|
+
|
145
|
+
# Builds billing, shipping and origin addresses
|
146
|
+
def build_addresses(options={})
|
147
|
+
raise "override in purchase_order or sales_order"
|
148
|
+
end
|
149
|
+
|
150
|
+
# Net total amount
|
151
|
+
def net_total
|
152
|
+
self.net_amount = line_items.inject(0.to_money) {|sum,l| sum + l.net_amount }
|
153
|
+
end
|
154
|
+
|
155
|
+
# Calculates tax and sets the tax_amount attribute
|
156
|
+
# It adds tax_amount across all line_items
|
157
|
+
def tax_total
|
158
|
+
self.tax_amount = line_items.inject(0.to_money) {|sum,l| sum + l.tax_amount }
|
159
|
+
self.tax_amount
|
160
|
+
end
|
161
|
+
|
162
|
+
# Gross amount including tax
|
163
|
+
def gross_total
|
164
|
+
self.gross_amount = self.net_total + self.tax_total
|
165
|
+
end
|
166
|
+
|
167
|
+
# Same as gross_total with tax
|
168
|
+
def total
|
169
|
+
self.gross_total
|
170
|
+
end
|
171
|
+
|
172
|
+
# is the number of line items stored in the order, though not to be
|
173
|
+
# confused by the items_count
|
174
|
+
def line_items_count
|
175
|
+
self.line_items.count
|
176
|
+
end
|
177
|
+
|
178
|
+
# total number of items purchased
|
179
|
+
def items_count
|
180
|
+
counter = 0
|
181
|
+
self.line_items.each do |item|
|
182
|
+
if item.sellable && item.sellable.respond_to?(:quantity)
|
183
|
+
counter += item.sellable.quantity
|
184
|
+
else
|
185
|
+
counter += 1
|
186
|
+
end
|
187
|
+
end
|
188
|
+
counter
|
189
|
+
end
|
190
|
+
|
191
|
+
# updates the order and all contained line_items after an address has changed
|
192
|
+
# or an order item was added or removed. The order can only be evaluated if the
|
193
|
+
# created state is active. The order is saved if it is an existing order.
|
194
|
+
# Returns true if evaluation happend, false if not.
|
195
|
+
def evaluate
|
196
|
+
if :created == current_state
|
197
|
+
self.line_items.each(&:evaluate)
|
198
|
+
self.calculate
|
199
|
+
return save(false) unless new_record?
|
200
|
+
end
|
201
|
+
false
|
202
|
+
end
|
203
|
+
|
204
|
+
# adds a line item or sellable to order and updates the order
|
205
|
+
def push(an_item_or_sellable)
|
206
|
+
if !an_item_or_sellable.is_a?(LineItem) && an_item_or_sellable.respond_to?(:price)
|
207
|
+
li = LineItem.new(:sellable => an_item_or_sellable, :order => self)
|
208
|
+
elsif an_item_or_sellable.is_a?(LineItem)
|
209
|
+
li = an_item_or_sellable
|
210
|
+
end
|
211
|
+
if li
|
212
|
+
self.line_items.push(li)
|
213
|
+
self.evaluate
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
protected
|
218
|
+
|
219
|
+
# Recalculates the order, adding order lines, tax and gross totals
|
220
|
+
def calculate
|
221
|
+
self.total
|
222
|
+
end
|
223
|
+
|
224
|
+
# override in subclass
|
225
|
+
def to_invoice_class_name
|
226
|
+
end
|
227
|
+
|
228
|
+
# override in subclass
|
229
|
+
def purchase_order?
|
230
|
+
false
|
231
|
+
end
|
232
|
+
|
233
|
+
# override in subclass
|
234
|
+
def sales_order?
|
235
|
+
false
|
236
|
+
end
|
237
|
+
|
238
|
+
def push_payment(a_payment)
|
239
|
+
a_payment.payable = self
|
240
|
+
self.payments.push(a_payment)
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
end
|