erp_commerce 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GPL-3-LICENSE +674 -0
- data/README.rdoc +2 -0
- data/Rakefile +32 -0
- data/app/assets/javascripts/erp_commerce/application.js +9 -0
- data/app/assets/stylesheets/erp_commerce/application.css +7 -0
- data/app/controllers/erp_commerce/application_controller.rb +4 -0
- data/app/helpers/erp_commerce/application_helper.rb +4 -0
- data/app/models/credit_card.rb +54 -0
- data/app/models/credit_card_account.rb +4 -0
- data/app/models/credit_card_account_party_role.rb +8 -0
- data/app/models/credit_card_account_purpose.rb +6 -0
- data/app/models/credit_card_token.rb +12 -0
- data/app/models/extensions/charge_line.rb +3 -0
- data/app/models/extensions/currency.rb +3 -0
- data/app/models/extensions/financial_txn.rb +3 -0
- data/app/models/extensions/order_txn.rb +3 -0
- data/app/models/extensions/party.rb +21 -0
- data/app/models/extensions/product_instance.rb +5 -0
- data/app/models/extensions/product_type.rb +3 -0
- data/app/models/fee.rb +7 -0
- data/app/models/fee_type.rb +4 -0
- data/app/models/payment.rb +38 -0
- data/app/models/payment_gateway.rb +4 -0
- data/app/models/payment_gateway_action.rb +2 -0
- data/app/models/price.rb +25 -0
- data/app/models/price_component.rb +8 -0
- data/app/models/price_component_type.rb +3 -0
- data/app/models/pricing_plan.rb +37 -0
- data/app/models/pricing_plan_assignment.rb +6 -0
- data/app/models/pricing_plan_component.rb +36 -0
- data/app/models/valid_price_plan_component.rb +8 -0
- data/app/views/layouts/erp_commerce/application.html.erb +14 -0
- data/app/widgets/orders/base.rb +40 -0
- data/app/widgets/orders/javascript/orders.js +11 -0
- data/app/widgets/orders/views/index.html.erb +63 -0
- data/app/widgets/product_catalog/base.rb +56 -0
- data/app/widgets/product_catalog/javascript/product_catalog.js +62 -0
- data/app/widgets/product_catalog/views/add_to_cart.html.erb +10 -0
- data/app/widgets/product_catalog/views/index.html.erb +69 -0
- data/app/widgets/product_catalog/views/show.html.erb +23 -0
- data/app/widgets/shopping_cart/base.rb +178 -0
- data/app/widgets/shopping_cart/javascript/shopping_cart.js +107 -0
- data/app/widgets/shopping_cart/views/cart_items.html.erb +83 -0
- data/app/widgets/shopping_cart/views/confirmation.html.erb +10 -0
- data/app/widgets/shopping_cart/views/demographics.html.erb +142 -0
- data/app/widgets/shopping_cart/views/login.html.erb +1 -0
- data/app/widgets/shopping_cart/views/payment.html.erb +81 -0
- data/app/widgets/shopping_cart/views/price_summary.html.erb +4 -0
- data/config/routes.rb +2 -0
- data/db/data_migrations/20101011152441_payment_gateway_actions.rb +27 -0
- data/db/migrate/20100823174238_erp_commerce_base.rb +174 -0
- data/db/migrate/20100913154134_setup_payments.rb +57 -0
- data/db/migrate/20101103132342_pricing_migrations.rb +169 -0
- data/db/migrate/20110921150854_create_fees.rb +50 -0
- data/lib/erp_commerce/active_merchant_wrappers/brain_tree_gateway_wrapper.rb +66 -0
- data/lib/erp_commerce/active_merchant_wrappers/credit_card_validation.rb +34 -0
- data/lib/erp_commerce/active_merchant_wrappers.rb +2 -0
- data/lib/erp_commerce/engine.rb +15 -0
- data/lib/erp_commerce/extensions/active_record/acts_as_fee.rb +64 -0
- data/lib/erp_commerce/extensions/active_record/acts_as_priceable.rb +57 -0
- data/lib/erp_commerce/extensions.rb +2 -0
- data/lib/erp_commerce/order_helper.rb +254 -0
- data/lib/erp_commerce/version.rb +3 -0
- data/lib/erp_commerce.rb +8 -0
- data/lib/tasks/erp_commerce_tasks.rake +4 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +49 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +8 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/spec.rb +27 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/models/credit_card_account_party_role_spec.rb +11 -0
- data/spec/models/credit_card_account_purpose_spec.rb +11 -0
- data/spec/models/credit_card_account_spec.rb +11 -0
- data/spec/models/credit_card_spec.rb +11 -0
- data/spec/models/fee_spec.rb +11 -0
- data/spec/models/fee_type_spec.rb +11 -0
- data/spec/models/payment_gateway_action_spec.rb +11 -0
- data/spec/models/payment_gateway_spec.rb +11 -0
- data/spec/models/payment_spec.rb +11 -0
- data/spec/models/price_component_spec.rb +11 -0
- data/spec/models/price_component_type_spec.rb +11 -0
- data/spec/models/price_spec.rb +11 -0
- data/spec/models/pricing_plan_assignment_spec.rb +11 -0
- data/spec/models/pricing_plan_component_spec.rb +11 -0
- data/spec/models/pricing_plan_spec.rb +11 -0
- data/spec/models/valid_price_plan_component_spec.rb +11 -0
- data/spec/spec_helper.rb +60 -0
- metadata +285 -0
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ErpCommerce'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
28
|
+
require "rspec/core/rake_task"
|
29
|
+
RSpec::Core::RakeTask.new(:spec)
|
30
|
+
task :default => :spec
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into including all the files listed below.
|
2
|
+
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
3
|
+
// be included in the compiled file accessible from http://example.com/assets/application.js
|
4
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
5
|
+
// the compiled file.
|
6
|
+
//
|
7
|
+
//= require jquery
|
8
|
+
//= require jquery_ujs
|
9
|
+
//= require_tree .
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll automatically include all the stylesheets available in this directory
|
3
|
+
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
4
|
+
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
5
|
+
*= require_self
|
6
|
+
*= require_tree .
|
7
|
+
*/
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class CreditCard < ActiveRecord::Base
|
2
|
+
|
3
|
+
require 'attr_encrypted'
|
4
|
+
|
5
|
+
belongs_to :postal_address
|
6
|
+
has_many :payments
|
7
|
+
belongs_to :credit_card_account_party_role
|
8
|
+
|
9
|
+
#the function EncryptionKey.get_key is meant to be overridden to provide a means for implementations to specify their
|
10
|
+
#own encryption schemes and locations. It will default to a simple string for development and testing
|
11
|
+
attr_encrypted :private_card_number, :key => EncryptionKey.get_key, :marshall => true, :attribute => :crypted_private_card_number
|
12
|
+
|
13
|
+
# These methods are exposed for the purposes of displaying a version of the card number
|
14
|
+
# string containing the last four digits of the card number. The idea is to make it
|
15
|
+
# painfully obvious when any coder is using the private_card_number, which should
|
16
|
+
# be used only in limited circumstances.
|
17
|
+
|
18
|
+
def card_number
|
19
|
+
if self.private_card_number
|
20
|
+
n = self.private_card_number
|
21
|
+
'xxxx-xxxx-xxxx-' + n[n.length-4..n.length]
|
22
|
+
else
|
23
|
+
''
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Note that the setter method allows the same variable to be set, and delegates through
|
28
|
+
# the encryption process
|
29
|
+
|
30
|
+
def card_number=(num)
|
31
|
+
self.private_card_number=num
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_label
|
35
|
+
"#{card_type}: #{card_number}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
"#{card_type}: #{card_number}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def cardholder
|
43
|
+
return self.credit_card_account_party_role.party
|
44
|
+
end
|
45
|
+
|
46
|
+
def before_create
|
47
|
+
token = CreditCardToken.new
|
48
|
+
self.credit_card_token = token.cc_token.strip
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Party.class_eval do
|
2
|
+
|
3
|
+
#credit cards
|
4
|
+
has_many :credit_card_account_party_roles
|
5
|
+
|
6
|
+
# return primary credit card
|
7
|
+
def primary_credit_card
|
8
|
+
return get_credit_card('primary')
|
9
|
+
end
|
10
|
+
|
11
|
+
# return credit card by credit card account purpose using internal identifier
|
12
|
+
def get_credit_card(internal_identifier)
|
13
|
+
self.credit_card_account_party_roles.each do |ccapr|
|
14
|
+
if ccapr.credit_card_account.credit_card_account_purpose.internal_identifier.eql?(internal_identifier)
|
15
|
+
return ccapr.credit_card
|
16
|
+
end
|
17
|
+
end
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/app/models/fee.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
class Payment < ActiveRecord::Base
|
2
|
+
include AASM
|
3
|
+
|
4
|
+
belongs_to :financial_txn
|
5
|
+
has_many :payment_gateways
|
6
|
+
|
7
|
+
aasm_column :current_state
|
8
|
+
|
9
|
+
aasm_initial_state :pending
|
10
|
+
|
11
|
+
aasm_state :pending
|
12
|
+
aasm_state :declined
|
13
|
+
aasm_state :authorized
|
14
|
+
aasm_state :captured
|
15
|
+
aasm_state :authorization_reversed
|
16
|
+
|
17
|
+
aasm_event :authorize do
|
18
|
+
transitions :to => :authorized, :from => [:pending]
|
19
|
+
end
|
20
|
+
|
21
|
+
aasm_event :purchase do
|
22
|
+
transitions :to => :captured, :from => [:authorized, :pending]
|
23
|
+
end
|
24
|
+
|
25
|
+
aasm_event :decline do
|
26
|
+
transitions :to => :declined, :from => [:pending]
|
27
|
+
end
|
28
|
+
|
29
|
+
aasm_event :capture do
|
30
|
+
transitions :to => :captured, :from => [:authorized]
|
31
|
+
end
|
32
|
+
|
33
|
+
aasm_event :reverse_authorization do
|
34
|
+
transitions :to => :authorization_reversed, :from => [:authorized]
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
end
|
data/app/models/price.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Price < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :pricing_plan
|
4
|
+
belongs_to :priced_item, :polymorphic => true
|
5
|
+
has_many :price_components, :dependent => :destroy
|
6
|
+
belongs_to :money
|
7
|
+
|
8
|
+
alias :components :price_components
|
9
|
+
|
10
|
+
def get_price_components_by_type(type_iid)
|
11
|
+
self.price_components.select{|pc| pc.pricing_plan_component.price_component_type.internal_identifier == type_iid}
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_total_by_type(type_iid)
|
15
|
+
total = 0
|
16
|
+
|
17
|
+
components = self.price_components.select{|pc| pc.pricing_plan_component.price_component_type.internal_identifier == type_iid}
|
18
|
+
components.each do |component|
|
19
|
+
total = total + component.money.amount
|
20
|
+
end
|
21
|
+
|
22
|
+
total
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class PricingPlan < ActiveRecord::Base
|
2
|
+
|
3
|
+
has_many :valid_price_plan_components
|
4
|
+
has_many :pricing_plan_components, :through => :valid_price_plan_components
|
5
|
+
belongs_to :currency
|
6
|
+
|
7
|
+
alias :components :pricing_plan_components
|
8
|
+
|
9
|
+
def get_price( rule_ctx = nil )
|
10
|
+
|
11
|
+
price = Price.new
|
12
|
+
price.pricing_plan = self
|
13
|
+
|
14
|
+
#first check if this is a simple amount if so get the amount.
|
15
|
+
if self.is_simple_amount
|
16
|
+
price.money = Money.new(:amount => self.money_amount, :currency => self.currency)
|
17
|
+
|
18
|
+
#second check if a pricing calculation exists if so use it.
|
19
|
+
elsif !self.pricing_calculation.nil?
|
20
|
+
rule_ctx[:pricing_plan] = self
|
21
|
+
rule_ctx[:price] = price
|
22
|
+
eval(self.pricing_calculation)
|
23
|
+
|
24
|
+
#finanlly if this is not a simple amount and has no pricing calcuation use the price components associated to this plan
|
25
|
+
else
|
26
|
+
self.pricing_plan_components.each do |pricing_plan_component|
|
27
|
+
price_component = pricing_plan_component.get_price_component(rule_ctx)
|
28
|
+
price.components << price_component
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
price.description = self.description
|
33
|
+
|
34
|
+
price
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class PricingPlanComponent < ActiveRecord::Base
|
2
|
+
|
3
|
+
#these relationships essentially mean that pricing plan components can
|
4
|
+
#be shared across pricing plan. This is accomplished by using a cross-reference
|
5
|
+
#table called 'valid_price_plan_components'
|
6
|
+
has_many :valid_price_plan_components
|
7
|
+
has_many :pricing_plans, :through => :valid_price_plan_components
|
8
|
+
belongs_to :price_component_type
|
9
|
+
belongs_to :currency
|
10
|
+
|
11
|
+
def get_price_component( rule_ctx = nil )
|
12
|
+
|
13
|
+
#this will be relaced by an execution of the stored 'matching_rule' and 'pricing_calculation'
|
14
|
+
#although it might make sense to have an 'is_simple' flag and corresponding value so the price
|
15
|
+
#component can simply create one price component with one float value without invoking a rules
|
16
|
+
#engine or the interpreter
|
17
|
+
|
18
|
+
if self.is_simple_amount
|
19
|
+
component_amount = self.money_amount
|
20
|
+
else
|
21
|
+
component_amount = eval(self.pricing_calculation)
|
22
|
+
end
|
23
|
+
|
24
|
+
money = Money.new(:description => self.description, :amount => component_amount, :currency => self.currency)
|
25
|
+
|
26
|
+
price_component = PriceComponent.new(
|
27
|
+
:money => money,
|
28
|
+
:pricing_plan_component => self,
|
29
|
+
:description => self.description
|
30
|
+
)
|
31
|
+
|
32
|
+
price_component
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>ErpCommerce</title>
|
5
|
+
<%= stylesheet_link_tag "erp_commerce/application" %>
|
6
|
+
<%= javascript_include_tag "erp_commerce/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Widgets
|
2
|
+
module Orders
|
3
|
+
class Base < ErpApp::Widgets::Base
|
4
|
+
def index
|
5
|
+
@orders = OrderTxn.find_by_party_role('buyer', current_user.party)
|
6
|
+
@orders = @orders.select{|order| order.status != "Initialized"}
|
7
|
+
render
|
8
|
+
end
|
9
|
+
|
10
|
+
#should not be modified
|
11
|
+
#modify at your own risk
|
12
|
+
def locate
|
13
|
+
File.dirname(__FILE__)
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def title
|
18
|
+
"Orders"
|
19
|
+
end
|
20
|
+
|
21
|
+
def views_location
|
22
|
+
File.join(File.dirname(__FILE__),"/views")
|
23
|
+
end
|
24
|
+
|
25
|
+
def widget_name
|
26
|
+
File.basename(File.dirname(__FILE__))
|
27
|
+
end
|
28
|
+
|
29
|
+
def base_layout
|
30
|
+
begin
|
31
|
+
file = File.join(File.dirname(__FILE__),"/views/layouts/base.html.erb")
|
32
|
+
IO.read(file)
|
33
|
+
rescue
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end#Base
|
39
|
+
end#Orders
|
40
|
+
end#Widgets
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Compass.ErpApp.Widgets.Orders = {
|
2
|
+
add:function(){
|
3
|
+
Ext.getCmp('knitkitCenterRegion').addContentToActiveCodeMirror("<%= render_widget :orders %>");
|
4
|
+
}
|
5
|
+
}
|
6
|
+
|
7
|
+
Compass.ErpApp.Widgets.AvailableWidgets.push({
|
8
|
+
name:'Orders',
|
9
|
+
iconUrl:'/images/icons/package/package_48x48.png',
|
10
|
+
onClick:Compass.ErpApp.Widgets.Orders.add
|
11
|
+
});
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<style type="text/css">
|
2
|
+
#products-view {
|
3
|
+
font-family:'Lucida Grande','Lucida Sans Unicode',sans-serif;
|
4
|
+
text-align:center;
|
5
|
+
font-size:14px;
|
6
|
+
width:100%;
|
7
|
+
border-collapse: collapse;
|
8
|
+
border: 2px solid #CCCCCC;
|
9
|
+
}
|
10
|
+
|
11
|
+
#products-view a {
|
12
|
+
text-decoration:none;
|
13
|
+
}
|
14
|
+
|
15
|
+
#products-view img {
|
16
|
+
height:60px;
|
17
|
+
width:65px;
|
18
|
+
padding-right:15px;
|
19
|
+
}
|
20
|
+
|
21
|
+
#products-view div
|
22
|
+
{
|
23
|
+
float:left;
|
24
|
+
text-align:left;
|
25
|
+
}
|
26
|
+
|
27
|
+
#products-view th {
|
28
|
+
padding: 0 0.5em;
|
29
|
+
height:30px;
|
30
|
+
text-align:center;
|
31
|
+
background:url("/images/knitkit/footer.png") repeat-x scroll 0 0 #29425E;
|
32
|
+
}
|
33
|
+
|
34
|
+
.highlight:hover
|
35
|
+
{
|
36
|
+
background-color:#FFFFEE;
|
37
|
+
}
|
38
|
+
|
39
|
+
#products-view td+td {
|
40
|
+
border-left: 1px solid #CCC;
|
41
|
+
text-align: center;
|
42
|
+
}
|
43
|
+
</style>
|
44
|
+
<table id="products-view">
|
45
|
+
<thead>
|
46
|
+
<tr>
|
47
|
+
<th>Order Number</th>
|
48
|
+
<th>Order At</th>
|
49
|
+
<th>Status</th>
|
50
|
+
<th>Amount</th>
|
51
|
+
</tr>
|
52
|
+
</thead>
|
53
|
+
<tbody>
|
54
|
+
<% @orders.each do |order| %>
|
55
|
+
<tr>
|
56
|
+
<td><%=order.order_number%></td>
|
57
|
+
<td><%=order.created_at.to_time.strftime("%m/%d/%Y %I:%M%p")%></td>
|
58
|
+
<td><%=order.status%></td>
|
59
|
+
<td><%=number_to_currency(order.get_total_charges.sum{|money| money.amount})%></td>
|
60
|
+
</tr>
|
61
|
+
<% end %>
|
62
|
+
</tbody>
|
63
|
+
</table>
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Widgets
|
2
|
+
module ProductCatalog
|
3
|
+
class Base < ErpApp::Widgets::Base
|
4
|
+
def index
|
5
|
+
render
|
6
|
+
end
|
7
|
+
|
8
|
+
def back_to_catalog
|
9
|
+
render :update => {:id => "#{@uuid}_result", :view => 'index'}
|
10
|
+
end
|
11
|
+
|
12
|
+
def show
|
13
|
+
@product_type = ProductType.find(params[:id])
|
14
|
+
render :update => {:id => "#{@uuid}_result", :view => 'show'}
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_to_cart
|
18
|
+
@product_type = ProductType.find(params[:id])
|
19
|
+
@cart_items_url = params[:cart_items_url]
|
20
|
+
ErpCommerce::OrderHelper.new(self).add_to_cart(@product_type)
|
21
|
+
|
22
|
+
render :update => {:id => "#{@uuid}_result", :view => 'add_to_cart'}
|
23
|
+
end
|
24
|
+
|
25
|
+
#should not be modified
|
26
|
+
#modify at your own risk
|
27
|
+
def locate
|
28
|
+
File.dirname(__FILE__)
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def title
|
33
|
+
"Product Catalog"
|
34
|
+
end
|
35
|
+
|
36
|
+
def views_location
|
37
|
+
File.join(File.dirname(__FILE__),"/views")
|
38
|
+
end
|
39
|
+
|
40
|
+
def widget_name
|
41
|
+
File.basename(File.dirname(__FILE__))
|
42
|
+
end
|
43
|
+
|
44
|
+
def base_layout
|
45
|
+
begin
|
46
|
+
file = File.join(File.dirname(__FILE__),"/views/layouts/base.html.erb")
|
47
|
+
IO.read(file)
|
48
|
+
rescue
|
49
|
+
return nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end#Base
|
54
|
+
end#ProductCatalog
|
55
|
+
end#Widgets
|
56
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
Compass.ErpApp.Widgets.ProductCatalog = {
|
2
|
+
add:function(){
|
3
|
+
var addProductCatalogWidgetWindow = Ext.create("Ext.window.Window",{
|
4
|
+
layout:'fit',
|
5
|
+
width:300,
|
6
|
+
title:'Add Product Catalog Widget',
|
7
|
+
height:100,
|
8
|
+
buttonAlign:'center',
|
9
|
+
items: Ext.create("Ext.form.Panel",{
|
10
|
+
labelWidth: 100,
|
11
|
+
frame:false,
|
12
|
+
bodyStyle:'padding:5px 5px 0',
|
13
|
+
defaults: {
|
14
|
+
width: 225
|
15
|
+
},
|
16
|
+
items: [
|
17
|
+
{
|
18
|
+
xtype:'textfield',
|
19
|
+
fieldLabel:'Cart Items Url',
|
20
|
+
name:'cartItemsUrl',
|
21
|
+
hidden:false,
|
22
|
+
value:'/cart-items'
|
23
|
+
}
|
24
|
+
]
|
25
|
+
}),
|
26
|
+
buttons: [{
|
27
|
+
text:'Submit',
|
28
|
+
handler:function(button){
|
29
|
+
var window = button.findParentByType('window');
|
30
|
+
var formPanel = window.query('form')[0];
|
31
|
+
var basicForm = formPanel.getForm();
|
32
|
+
var cartItemsUrl = basicForm.findField('cartItemsUrl').getValue();
|
33
|
+
var data = {
|
34
|
+
cartItemsUrl:cartItemsUrl
|
35
|
+
};
|
36
|
+
|
37
|
+
var tpl = new Ext.XTemplate("<%= render_widget :product_catalog,\n",
|
38
|
+
" :action => :index,\n",
|
39
|
+
" :params => {:cart_items_url => '{cartItemsUrl}'} %>");
|
40
|
+
|
41
|
+
//add rendered template to center region editor
|
42
|
+
Ext.getCmp('knitkitCenterRegion').addContentToActiveCodeMirror(tpl.apply(data));
|
43
|
+
addProductCatalogWidgetWindow.close();
|
44
|
+
}
|
45
|
+
},
|
46
|
+
{
|
47
|
+
text: 'Close',
|
48
|
+
handler: function(){
|
49
|
+
addProductCatalogWidgetWindow.close();
|
50
|
+
}
|
51
|
+
}]
|
52
|
+
|
53
|
+
});
|
54
|
+
addProductCatalogWidgetWindow.show();
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
Compass.ErpApp.Widgets.AvailableWidgets.push({
|
59
|
+
name:'Product Catalog',
|
60
|
+
iconUrl:'/images/icons/product/product_48x48.png',
|
61
|
+
onClick:Compass.ErpApp.Widgets.ProductCatalog.add
|
62
|
+
});
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<%= @product_type.description %>
|
2
|
+
<br/>
|
3
|
+
<p><%= raw @product_type.find_description_by_iid('long_description').description %></p>
|
4
|
+
<br/>
|
5
|
+
Added to cart
|
6
|
+
<br/>
|
7
|
+
<%=link_to_remote 'Continue Shopping', build_widget_url(:index)%> | <a href="<%=@cart_items_url%>">Go to Cart</a>
|
8
|
+
<script type="text/javascript">
|
9
|
+
Compass.ErpApp.Widgets.refreshWidget('shopping_cart', 'price_summary');
|
10
|
+
</script>
|