effective_orders 4.5.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1004 -0
- data/app/assets/images/effective_orders/stripe.png +0 -0
- data/app/assets/javascripts/effective_orders.js +6 -0
- data/app/assets/javascripts/effective_orders/customers.js.coffee +32 -0
- data/app/assets/javascripts/effective_orders/providers/stripe.js.coffee +77 -0
- data/app/assets/javascripts/effective_orders/subscriptions.js.coffee +81 -0
- data/app/assets/stylesheets/effective_orders.scss +2 -0
- data/app/assets/stylesheets/effective_orders/_cart.scss +4 -0
- data/app/assets/stylesheets/effective_orders/_order.scss +58 -0
- data/app/controllers/admin/customers_controller.rb +24 -0
- data/app/controllers/admin/order_items_controller.rb +16 -0
- data/app/controllers/admin/orders_controller.rb +223 -0
- data/app/controllers/effective/carts_controller.rb +85 -0
- data/app/controllers/effective/concerns/purchase.rb +62 -0
- data/app/controllers/effective/customers_controller.rb +20 -0
- data/app/controllers/effective/orders_controller.rb +162 -0
- data/app/controllers/effective/providers/cheque.rb +22 -0
- data/app/controllers/effective/providers/free.rb +33 -0
- data/app/controllers/effective/providers/mark_as_paid.rb +33 -0
- data/app/controllers/effective/providers/moneris.rb +60 -0
- data/app/controllers/effective/providers/paypal.rb +33 -0
- data/app/controllers/effective/providers/phone.rb +22 -0
- data/app/controllers/effective/providers/pretend.rb +26 -0
- data/app/controllers/effective/providers/refund.rb +33 -0
- data/app/controllers/effective/providers/stripe.rb +72 -0
- data/app/controllers/effective/subscripter_controller.rb +18 -0
- data/app/controllers/effective/webhooks_controller.rb +109 -0
- data/app/datatables/admin/effective_customers_datatable.rb +22 -0
- data/app/datatables/admin/effective_orders_datatable.rb +100 -0
- data/app/datatables/effective_orders_datatable.rb +79 -0
- data/app/helpers/effective_carts_helper.rb +113 -0
- data/app/helpers/effective_orders_helper.rb +143 -0
- data/app/helpers/effective_paypal_helper.rb +49 -0
- data/app/helpers/effective_stripe_helper.rb +85 -0
- data/app/helpers/effective_subscriptions_helper.rb +34 -0
- data/app/mailers/effective/orders_mailer.rb +196 -0
- data/app/models/concerns/acts_as_purchasable.rb +118 -0
- data/app/models/concerns/acts_as_subscribable.rb +90 -0
- data/app/models/concerns/acts_as_subscribable_buyer.rb +49 -0
- data/app/models/effective/access_denied.rb +17 -0
- data/app/models/effective/cart.rb +88 -0
- data/app/models/effective/cart_item.rb +40 -0
- data/app/models/effective/customer.rb +92 -0
- data/app/models/effective/order.rb +541 -0
- data/app/models/effective/order_item.rb +63 -0
- data/app/models/effective/product.rb +23 -0
- data/app/models/effective/sold_out_validator.rb +7 -0
- data/app/models/effective/subscripter.rb +185 -0
- data/app/models/effective/subscription.rb +95 -0
- data/app/models/effective/tax_rate_calculator.rb +48 -0
- data/app/views/admin/customers/_actions.html.haml +2 -0
- data/app/views/admin/customers/index.html.haml +6 -0
- data/app/views/admin/customers/show.html.haml +6 -0
- data/app/views/admin/order_items/index.html.haml +3 -0
- data/app/views/admin/orders/_datatable_actions.html.haml +18 -0
- data/app/views/admin/orders/_form.html.haml +35 -0
- data/app/views/admin/orders/_form_note_internal.html.haml +7 -0
- data/app/views/admin/orders/_order_actions.html.haml +9 -0
- data/app/views/admin/orders/_order_item_fields.html.haml +14 -0
- data/app/views/admin/orders/checkout.html.haml +3 -0
- data/app/views/admin/orders/edit.html.haml +6 -0
- data/app/views/admin/orders/index.html.haml +6 -0
- data/app/views/admin/orders/new.html.haml +4 -0
- data/app/views/admin/orders/show.html.haml +4 -0
- data/app/views/effective/carts/_cart.html.haml +28 -0
- data/app/views/effective/carts/_cart_actions.html.haml +3 -0
- data/app/views/effective/carts/show.html.haml +17 -0
- data/app/views/effective/customers/_customer.html.haml +72 -0
- data/app/views/effective/customers/_form.html.haml +21 -0
- data/app/views/effective/customers/edit.html.haml +4 -0
- data/app/views/effective/customers/update.js.erb +5 -0
- data/app/views/effective/orders/_checkout_actions.html.haml +3 -0
- data/app/views/effective/orders/_checkout_step1.html.haml +4 -0
- data/app/views/effective/orders/_checkout_step2.html.haml +37 -0
- data/app/views/effective/orders/_datatable_actions.html.haml +2 -0
- data/app/views/effective/orders/_fields.html.haml +31 -0
- data/app/views/effective/orders/_fields_note.html.haml +7 -0
- data/app/views/effective/orders/_fields_terms.html.haml +8 -0
- data/app/views/effective/orders/_order.html.haml +11 -0
- data/app/views/effective/orders/_order_actions.html.haml +18 -0
- data/app/views/effective/orders/_order_deferred.html.haml +9 -0
- data/app/views/effective/orders/_order_footer.html.haml +1 -0
- data/app/views/effective/orders/_order_header.html.haml +23 -0
- data/app/views/effective/orders/_order_items.html.haml +72 -0
- data/app/views/effective/orders/_order_notes.html.haml +17 -0
- data/app/views/effective/orders/_order_payment.html.haml +24 -0
- data/app/views/effective/orders/_order_shipping.html.haml +30 -0
- data/app/views/effective/orders/_orders_table.html.haml +23 -0
- data/app/views/effective/orders/cheque/_form.html.haml +4 -0
- data/app/views/effective/orders/declined.html.haml +12 -0
- data/app/views/effective/orders/deferred.html.haml +13 -0
- data/app/views/effective/orders/deferred/_form.html.haml +16 -0
- data/app/views/effective/orders/edit.html.haml +3 -0
- data/app/views/effective/orders/free/_form.html.haml +5 -0
- data/app/views/effective/orders/index.html.haml +3 -0
- data/app/views/effective/orders/mark_as_paid/_form.html.haml +23 -0
- data/app/views/effective/orders/moneris/_form.html.haml +47 -0
- data/app/views/effective/orders/new.html.haml +3 -0
- data/app/views/effective/orders/paypal/_form.html.haml +5 -0
- data/app/views/effective/orders/phone/_form.html.haml +4 -0
- data/app/views/effective/orders/pretend/_form.html.haml +8 -0
- data/app/views/effective/orders/purchased.html.haml +11 -0
- data/app/views/effective/orders/refund/_form.html.haml +5 -0
- data/app/views/effective/orders/show.html.haml +6 -0
- data/app/views/effective/orders/stripe/_element.html.haml +8 -0
- data/app/views/effective/orders/stripe/_form.html.haml +31 -0
- data/app/views/effective/orders_mailer/order_error.html.haml +11 -0
- data/app/views/effective/orders_mailer/order_receipt_to_admin.html.haml +2 -0
- data/app/views/effective/orders_mailer/order_receipt_to_buyer.html.haml +2 -0
- data/app/views/effective/orders_mailer/payment_request_to_buyer.html.haml +13 -0
- data/app/views/effective/orders_mailer/pending_order_invoice_to_buyer.html.haml +13 -0
- data/app/views/effective/orders_mailer/refund_notification_to_admin.html.haml +15 -0
- data/app/views/effective/orders_mailer/subscription_canceled.html.haml +9 -0
- data/app/views/effective/orders_mailer/subscription_created.html.haml +13 -0
- data/app/views/effective/orders_mailer/subscription_event_to_admin.html.haml +13 -0
- data/app/views/effective/orders_mailer/subscription_payment_failed.html.haml +9 -0
- data/app/views/effective/orders_mailer/subscription_payment_succeeded.html.haml +9 -0
- data/app/views/effective/orders_mailer/subscription_trial_expired.html.haml +5 -0
- data/app/views/effective/orders_mailer/subscription_trialing.html.haml +7 -0
- data/app/views/effective/orders_mailer/subscription_updated.html.haml +13 -0
- data/app/views/effective/subscripter/_form.html.haml +60 -0
- data/app/views/effective/subscripter/_plan.html.haml +23 -0
- data/app/views/layouts/effective_orders_mailer_layout.html.haml +25 -0
- data/config/effective_orders.rb +279 -0
- data/config/routes.rb +70 -0
- data/db/migrate/01_create_effective_orders.rb.erb +137 -0
- data/lib/effective_orders.rb +243 -0
- data/lib/effective_orders/engine.rb +60 -0
- data/lib/effective_orders/version.rb +3 -0
- data/lib/generators/effective_orders/install_generator.rb +63 -0
- data/lib/generators/templates/effective_orders_mailer_preview.rb +120 -0
- data/lib/tasks/effective_orders_tasks.rake +69 -0
- metadata +276 -0
|
Binary file
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
stripeCustomerChangeCardHandler = (key, form) ->
|
|
2
|
+
StripeCheckout.configure
|
|
3
|
+
key: key
|
|
4
|
+
closed: -> EffectiveForm.reset(form) unless form.hasClass('stripe-success')
|
|
5
|
+
token: (token, args) ->
|
|
6
|
+
if token.error
|
|
7
|
+
message = "An error ocurred when contacting Stripe. Your card has not been charged. Please refresh the page and try again. #{token.error.message}"
|
|
8
|
+
|
|
9
|
+
form.removeClass('stripe-success')
|
|
10
|
+
form.find('.invalid-feedback').html(message).show()
|
|
11
|
+
alert(message)
|
|
12
|
+
else
|
|
13
|
+
form.find("input[name$='[stripe_token]']").val('' + token['id'])
|
|
14
|
+
form.addClass('stripe-success').submit() # Submits the form. As this is a remote form, submits via JS
|
|
15
|
+
|
|
16
|
+
# When we click 'Change credit card', make sure the form collects a credit card
|
|
17
|
+
$(document).on 'click', ".effective-orders-stripe-update-card[type='submit']", (event) ->
|
|
18
|
+
$form = $(event.currentTarget).closest('form')
|
|
19
|
+
|
|
20
|
+
# Get stripe data payload
|
|
21
|
+
stripe = $form.data('stripe')
|
|
22
|
+
return unless stripe?
|
|
23
|
+
|
|
24
|
+
# Okay, we're good to call stripe
|
|
25
|
+
event.preventDefault()
|
|
26
|
+
EffectiveForm.submitting($form) # Disable and spin while we popup stripe
|
|
27
|
+
|
|
28
|
+
stripeCustomerChangeCardHandler(stripe.key, $form).open
|
|
29
|
+
image: stripe.image
|
|
30
|
+
name: stripe.name
|
|
31
|
+
email: stripe.email
|
|
32
|
+
panelLabel: 'Update Card Details'
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
this.StripeForm ||= class StripeForm
|
|
2
|
+
constructor: ->
|
|
3
|
+
@form = null
|
|
4
|
+
@paymentIntent = null
|
|
5
|
+
|
|
6
|
+
@data = null
|
|
7
|
+
@stripe = null
|
|
8
|
+
@card = null
|
|
9
|
+
|
|
10
|
+
initialize: ->
|
|
11
|
+
@form = $('form[data-stripe-form]').first()
|
|
12
|
+
return false unless @form.length > 0
|
|
13
|
+
|
|
14
|
+
@paymentIntent = @form.find("input[name$='[payment_intent_id]']").first()
|
|
15
|
+
@data = @form.data('stripe-form')
|
|
16
|
+
@stripe = Stripe(@data.key)
|
|
17
|
+
@card = @stripe.elements().create('card', @style())
|
|
18
|
+
|
|
19
|
+
@mount()
|
|
20
|
+
|
|
21
|
+
style: ->
|
|
22
|
+
style: {
|
|
23
|
+
base: { color: '#32325d', fontSize: '16px', },
|
|
24
|
+
invalid: { color: '#dc3545', iconColor: '#dc3545' }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
mount: ->
|
|
28
|
+
@card.mount('#stripe-card-element')
|
|
29
|
+
|
|
30
|
+
@card.addEventListener('change', (error) ->
|
|
31
|
+
$('#stripe-card-errors').text(if error.message then error.message else '')
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
@form.on('click', '[type=submit]', (event) => @submit(event))
|
|
35
|
+
|
|
36
|
+
submit: (event) ->
|
|
37
|
+
event.preventDefault()
|
|
38
|
+
|
|
39
|
+
payment = if @shouldUseNewCard() then @useNewCard() else @useExistingCard()
|
|
40
|
+
|
|
41
|
+
$.active = $.active + 1
|
|
42
|
+
|
|
43
|
+
payment.then((result) =>
|
|
44
|
+
if result.error
|
|
45
|
+
@errorPayment(result.error)
|
|
46
|
+
else if result.paymentIntent.status == 'succeeded'
|
|
47
|
+
@submitPayment(result.paymentIntent)
|
|
48
|
+
).then((result) =>
|
|
49
|
+
$.active = $.active - 1
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
shouldUseNewCard: ->
|
|
53
|
+
@form.get(0).checkValidity() &&
|
|
54
|
+
@paymentIntent.val().length == 0 &&
|
|
55
|
+
(@data.token_required || @form.children('.collapse.show').length > 0)
|
|
56
|
+
|
|
57
|
+
useNewCard: ->
|
|
58
|
+
@stripe.confirmCardPayment(@data.client_secret, {
|
|
59
|
+
payment_method: {
|
|
60
|
+
card: @card,
|
|
61
|
+
billing_details: { email: @data.email }
|
|
62
|
+
},
|
|
63
|
+
setup_future_usage: 'off_session'
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
useExistingCard: ->
|
|
67
|
+
@stripe.confirmCardPayment(@data.client_secret, { payment_method: @data.payment_method })
|
|
68
|
+
|
|
69
|
+
submitPayment: (payment) ->
|
|
70
|
+
@paymentIntent.val(payment['id'])
|
|
71
|
+
@form.submit()
|
|
72
|
+
|
|
73
|
+
errorPayment: (error) ->
|
|
74
|
+
$('#stripe-card-errors').text(error.message)
|
|
75
|
+
EffectiveForm.invalidate(@form);
|
|
76
|
+
|
|
77
|
+
$ -> (new StripeForm()).initialize()
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
stripeSubscriptionHandler = (key, form) ->
|
|
2
|
+
StripeCheckout.configure
|
|
3
|
+
key: key
|
|
4
|
+
closed: -> EffectiveForm.reset(form) unless form.hasClass('stripe-success')
|
|
5
|
+
token: (token, args) ->
|
|
6
|
+
if token.error
|
|
7
|
+
message = "An error ocurred when contacting Stripe. Your card has not been charged. Your plan has not changed. Please refresh the page and try again. #{token.error.message}"
|
|
8
|
+
|
|
9
|
+
form.removeClass('stripe-success')
|
|
10
|
+
form.find('.invalid-feedback').html(message).show()
|
|
11
|
+
alert(message)
|
|
12
|
+
else
|
|
13
|
+
form.find("input[name$='[stripe_token]']").val('' + token['id'])
|
|
14
|
+
form.addClass('stripe-success').submit() # Submits the form. As this is a remote form, submits via JS
|
|
15
|
+
|
|
16
|
+
# This updates the form whenever a quantity change is made
|
|
17
|
+
$(document).on 'change keyup', '.effective-orders-subscripter-plan-quantity', (event) ->
|
|
18
|
+
$obj = $(event.currentTarget)
|
|
19
|
+
$plan = $obj.closest('.effective-orders-stripe-plan')
|
|
20
|
+
return unless $plan.length == 1
|
|
21
|
+
|
|
22
|
+
# Assign the quantity to each quantity field
|
|
23
|
+
$plan.closest('form')
|
|
24
|
+
.find(".effective-orders-stripe-plan:not([data-plan-id='#{$plan.data('id')}'])")
|
|
25
|
+
.find("input[name$='[quantity]']").val($obj.val())
|
|
26
|
+
|
|
27
|
+
quantity = $obj.val() || 0
|
|
28
|
+
|
|
29
|
+
$plan.closest('form').find(".effective-orders-stripe-plan").each ->
|
|
30
|
+
# Assign all totals
|
|
31
|
+
plan = $(this)
|
|
32
|
+
amount = parseInt(plan.data('amount'))
|
|
33
|
+
interval = plan.data('interval')
|
|
34
|
+
|
|
35
|
+
total = (quantity * amount)
|
|
36
|
+
total = '$' + (total / 100.0).toFixed(2)
|
|
37
|
+
|
|
38
|
+
plan.find('#effective_subscripter_total_amount').text(total)
|
|
39
|
+
|
|
40
|
+
# Assign savings if present
|
|
41
|
+
savings = parseInt(plan.data('savings'))
|
|
42
|
+
|
|
43
|
+
if savings > 0
|
|
44
|
+
total_savings = '$' + ((quantity * savings) / 100.0).toFixed(2)
|
|
45
|
+
plan.find('.subscripter-total-savings').find('span').text(total_savings)
|
|
46
|
+
|
|
47
|
+
# Hijack submit and get a stripe token
|
|
48
|
+
$(document).on 'click', ".effective-orders-stripe-token-required[type='submit'],[data-choose-stripe-plan-id]", (event) ->
|
|
49
|
+
$obj = $(event.currentTarget)
|
|
50
|
+
$form = $obj.closest('form')
|
|
51
|
+
|
|
52
|
+
# Get stripe data payload
|
|
53
|
+
stripe = $form.data('stripe')
|
|
54
|
+
return unless stripe?
|
|
55
|
+
|
|
56
|
+
plans = $form.data('plans')
|
|
57
|
+
return unless plans?
|
|
58
|
+
|
|
59
|
+
# If we're doing choose button mode
|
|
60
|
+
if $obj.data('choose-stripe-plan-id')
|
|
61
|
+
$form.find("input[name$='[stripe_plan_id]']").val($obj.data('choose-stripe-plan-id'))
|
|
62
|
+
return true unless $obj.hasClass('effective-orders-stripe-token-required')
|
|
63
|
+
|
|
64
|
+
# Make sure there is a plan selected
|
|
65
|
+
selected_plan_id = $form.find("input[name$='[stripe_plan_id]']:checked").val() || $form.find("input[name$='[stripe_plan_id]']").val() || ''
|
|
66
|
+
return unless selected_plan_id.length > 0
|
|
67
|
+
|
|
68
|
+
# Match plan
|
|
69
|
+
plan = plans.find (plan, _) => plan.id == selected_plan_id
|
|
70
|
+
return unless plan?
|
|
71
|
+
|
|
72
|
+
# Okay, we're good to call stripe
|
|
73
|
+
event.preventDefault()
|
|
74
|
+
EffectiveForm.submitting($form) # Disable and spin while we popup stripe
|
|
75
|
+
|
|
76
|
+
stripeSubscriptionHandler(stripe.key, $form).open
|
|
77
|
+
image: stripe.image
|
|
78
|
+
name: stripe.name
|
|
79
|
+
email: stripe.email
|
|
80
|
+
description: plan.name
|
|
81
|
+
panelLabel: 'Update Plan'
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
.effective-order {
|
|
2
|
+
table {
|
|
3
|
+
clear: both;
|
|
4
|
+
margin-bottom: 25px;
|
|
5
|
+
|
|
6
|
+
tfoot {
|
|
7
|
+
> tr:first-child {
|
|
8
|
+
border-top: 20px solid transparent;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
th {
|
|
12
|
+
border: none;
|
|
13
|
+
text-align: right;
|
|
14
|
+
padding-right: 65px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
td {
|
|
18
|
+
text-align: right;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.actions { border: none; }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.price { text-align: right; }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Print - Resend Receipt. Ontop of order.
|
|
29
|
+
.effective-order-actions {
|
|
30
|
+
text-align: right;
|
|
31
|
+
margin-bottom: 0.5rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.effective-order-change-items {
|
|
35
|
+
margin-bottom: 1rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.effective-order-admin-purchase-actions {
|
|
39
|
+
margin-top: 0.5rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
form.new_effective_order {
|
|
43
|
+
.checkbox { margin-top: 30px; }
|
|
44
|
+
.remove-nested-fields { margin-top: 30px; }
|
|
45
|
+
a.remove_fields.dynamic { float: right; }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@media print {
|
|
49
|
+
.effective-orders-page-content { display: none; }
|
|
50
|
+
|
|
51
|
+
.effective-order-actions { display: none; }
|
|
52
|
+
.effective-order-purchase-actions { display: none; }
|
|
53
|
+
.effective-order-admin-purchase-actions { display: none; }
|
|
54
|
+
|
|
55
|
+
.effective-heading { display: none; }
|
|
56
|
+
.effective-admin-heading { display: none; }
|
|
57
|
+
.effective-order-internal-note-form { display: none; }
|
|
58
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class CustomersController < ApplicationController
|
|
3
|
+
before_action :authenticate_user!
|
|
4
|
+
|
|
5
|
+
layout (EffectiveOrders.layout.kind_of?(Hash) ? EffectiveOrders.layout[:admin_customers] : EffectiveOrders.layout)
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@datatable = Admin::EffectiveCustomersDatatable.new(self)
|
|
9
|
+
|
|
10
|
+
@page_title = 'Customers'
|
|
11
|
+
|
|
12
|
+
EffectiveOrders.authorize!(self, :admin, :effective_orders)
|
|
13
|
+
EffectiveOrders.authorize!(self, :index, Effective::Customer)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def show
|
|
17
|
+
@customer = Effective::Customer.find(params[:id])
|
|
18
|
+
|
|
19
|
+
@page_title ||= @customer.to_s
|
|
20
|
+
EffectiveOrders.authorize!(self, :show, Effective::Customer)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class OrderItemsController < ApplicationController
|
|
3
|
+
before_action :authenticate_user!
|
|
4
|
+
|
|
5
|
+
layout (EffectiveOrders.layout.kind_of?(Hash) ? EffectiveOrders.layout[:admin_orders] : EffectiveOrders.layout)
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@datatable = Admin::EffectiveOrderItemsDatatable.new(self)
|
|
9
|
+
|
|
10
|
+
@page_title = 'Order Items'
|
|
11
|
+
|
|
12
|
+
EffectiveOrders.authorize!(self, :admin, :effective_orders)
|
|
13
|
+
EffectiveOrders.authorize!(self, :index, Effective::OrderItem)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
module Admin
|
|
2
|
+
class OrdersController < ApplicationController
|
|
3
|
+
before_action :authenticate_user!
|
|
4
|
+
|
|
5
|
+
layout (EffectiveOrders.layout.kind_of?(Hash) ? EffectiveOrders.layout[:admin_orders] : EffectiveOrders.layout)
|
|
6
|
+
|
|
7
|
+
def new
|
|
8
|
+
@order = Effective::Order.new
|
|
9
|
+
|
|
10
|
+
if params[:user_id]
|
|
11
|
+
@order.user = User.where(id: params[:user_id]).first
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if params[:duplicate_id]
|
|
15
|
+
@duplicate = Effective::Order.deep.find(params[:duplicate_id])
|
|
16
|
+
EffectiveOrders.authorize!(self, :show, @duplicate)
|
|
17
|
+
|
|
18
|
+
@order.add(@duplicate)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
@page_title = 'New Order'
|
|
22
|
+
|
|
23
|
+
raise 'please install cocoon gem to use this page' unless defined?(Cocoon)
|
|
24
|
+
|
|
25
|
+
authorize_effective_order!
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def create
|
|
29
|
+
@user = User.find_by_id(order_params[:user_id])
|
|
30
|
+
@order = Effective::Order.new(user: @user)
|
|
31
|
+
|
|
32
|
+
authorize_effective_order!
|
|
33
|
+
error = nil
|
|
34
|
+
|
|
35
|
+
Effective::Order.transaction do
|
|
36
|
+
begin
|
|
37
|
+
(order_params[:order_items_attributes] || {}).each do |_, item_attrs|
|
|
38
|
+
purchasable = Effective::Product.new(item_attrs[:purchasable_attributes])
|
|
39
|
+
@order.add(purchasable, quantity: item_attrs[:quantity])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@order.attributes = order_params.except(:order_items_attributes, :user_id)
|
|
43
|
+
@order.pending!
|
|
44
|
+
|
|
45
|
+
message = 'Successfully created order'
|
|
46
|
+
message << ". A request for payment has been sent to #{@order.emails_send_to}" if @order.send_payment_request_to_buyer?
|
|
47
|
+
flash[:success] = message
|
|
48
|
+
|
|
49
|
+
redirect_to(admin_redirect_path) and return
|
|
50
|
+
rescue => e
|
|
51
|
+
error = e.message
|
|
52
|
+
raise ActiveRecord::Rollback
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@page_title = 'New Order'
|
|
57
|
+
flash.now[:danger] = flash_danger(@order)
|
|
58
|
+
render :new
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def edit
|
|
62
|
+
@order = Effective::Order.find(params[:id])
|
|
63
|
+
@page_title ||= @order.to_s
|
|
64
|
+
|
|
65
|
+
authorize_effective_order!
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def update
|
|
69
|
+
@order = Effective::Order.find(params[:id])
|
|
70
|
+
|
|
71
|
+
@page_title ||= @order.to_s
|
|
72
|
+
|
|
73
|
+
authorize_effective_order!
|
|
74
|
+
|
|
75
|
+
Effective::Order.transaction do
|
|
76
|
+
begin
|
|
77
|
+
@order.assign_attributes(order_params)
|
|
78
|
+
@order.save!
|
|
79
|
+
redirect_to(admin_redirect_path) and return
|
|
80
|
+
rescue => e
|
|
81
|
+
raise ActiveRecord::Rollback
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
flash.now[:danger] = "Unable to update order: #{@order.errors.full_messages.to_sentence}"
|
|
86
|
+
render :edit
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def show
|
|
90
|
+
@order = Effective::Order.find(params[:id])
|
|
91
|
+
|
|
92
|
+
@page_title ||= @order.to_s
|
|
93
|
+
|
|
94
|
+
authorize_effective_order!
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# The show page posts to this action
|
|
98
|
+
# See Effective::OrdersController checkout
|
|
99
|
+
def checkout
|
|
100
|
+
@order = Effective::Order.find(params[:id])
|
|
101
|
+
|
|
102
|
+
authorize_effective_order!
|
|
103
|
+
|
|
104
|
+
@page_title ||= 'Checkout'
|
|
105
|
+
|
|
106
|
+
if request.get?
|
|
107
|
+
@order.assign_confirmed_if_valid!
|
|
108
|
+
render :checkout and return
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
Effective::Order.transaction do
|
|
112
|
+
begin
|
|
113
|
+
@order.assign_attributes(checkout_params)
|
|
114
|
+
@order.confirm!
|
|
115
|
+
redirect_to(effective_orders.checkout_admin_order_path(@order)) and return
|
|
116
|
+
rescue => e
|
|
117
|
+
raise ActiveRecord::Rollback
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
flash.now[:danger] = "Unable to proceed: #{flash_errors(@order)}. Please try again."
|
|
122
|
+
render :checkout
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def index
|
|
126
|
+
@datatable = Admin::EffectiveOrdersDatatable.new(self)
|
|
127
|
+
|
|
128
|
+
@page_title = 'Orders'
|
|
129
|
+
|
|
130
|
+
authorize_effective_order!
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def destroy
|
|
134
|
+
@order = Effective::Order.all.not_purchased.find(params[:id])
|
|
135
|
+
|
|
136
|
+
authorize_effective_order!
|
|
137
|
+
|
|
138
|
+
if @order.destroy
|
|
139
|
+
flash[:success] = 'Successfully deleted order'
|
|
140
|
+
else
|
|
141
|
+
flash[:danger] = "Unable to delete order: #{@order.errors.full_messages.to_sentence}"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
redirect_to(effective_orders.admin_orders_path)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def send_payment_request
|
|
148
|
+
@order = Effective::Order.pending.find(params[:id])
|
|
149
|
+
authorize_effective_order!
|
|
150
|
+
|
|
151
|
+
if @order.send_payment_request_to_buyer!
|
|
152
|
+
flash[:success] = "A request for payment has been sent to #{@order.emails_send_to}"
|
|
153
|
+
else
|
|
154
|
+
flash[:danger] = 'Unable to send payment request'
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
if respond_to?(:redirect_back)
|
|
158
|
+
redirect_back(fallback_location: effective_orders.admin_order_path(@order))
|
|
159
|
+
elsif request.referrer.present?
|
|
160
|
+
redirect_to :back
|
|
161
|
+
else
|
|
162
|
+
redirect_to effective_orders.admin_order_path(@order)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def bulk_send_payment_request
|
|
167
|
+
@orders = Effective::Order.pending.where(id: params[:ids])
|
|
168
|
+
|
|
169
|
+
begin
|
|
170
|
+
authorize_effective_order!
|
|
171
|
+
|
|
172
|
+
@orders.each { |order| order.send_payment_request_to_buyer! }
|
|
173
|
+
render json: { status: 200, message: "Successfully sent #{@orders.length} payment request emails"}
|
|
174
|
+
rescue => e
|
|
175
|
+
render json: { status: 500, message: "Bulk send payment request error: #{e.message}" }
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
private
|
|
180
|
+
|
|
181
|
+
def order_params
|
|
182
|
+
params.require(:effective_order).permit(:user_id, :cc,
|
|
183
|
+
:send_payment_request_to_buyer, :note_internal, :note_to_buyer,
|
|
184
|
+
:payment_provider, :payment_card, :payment, :send_mark_as_paid_email_to_buyer,
|
|
185
|
+
order_items_attributes: [
|
|
186
|
+
:quantity, :_destroy, purchasable_attributes: [
|
|
187
|
+
:name, :price, :tax_exempt
|
|
188
|
+
]
|
|
189
|
+
]
|
|
190
|
+
)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def checkout_params
|
|
194
|
+
params.require(:effective_order).permit(EffectiveOrders.permitted_params)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def authorize_effective_order!
|
|
198
|
+
EffectiveOrders.authorize!(self, :admin, :effective_orders)
|
|
199
|
+
EffectiveOrders.authorize!(self, action_name.to_sym, @order || Effective::Order)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def admin_redirect_path
|
|
203
|
+
# Allow an app to define effective_orders_admin_redirect_path in their ApplicationController
|
|
204
|
+
path = if self.respond_to?(:effective_orders_admin_redirect_path)
|
|
205
|
+
effective_orders_admin_redirect_path(params[:commit], @order)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
return path if path.present?
|
|
209
|
+
|
|
210
|
+
case params[:commit].to_s
|
|
211
|
+
when 'Save' ; effective_orders.admin_order_path(@order)
|
|
212
|
+
|
|
213
|
+
when 'Continue' ; effective_orders.admin_orders_path
|
|
214
|
+
when 'Add New' ; effective_orders.new_admin_order_path(user_id: @order.user.try(:to_param))
|
|
215
|
+
when 'Duplicate' ; effective_orders.new_admin_order_path(duplicate_id: @order.to_param)
|
|
216
|
+
when 'Checkout' ; effective_orders.checkout_admin_order_path(@order.to_param)
|
|
217
|
+
|
|
218
|
+
else effective_orders.admin_order_path(@order)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
end
|
|
223
|
+
end
|