mirror of
https://github.com/discourse/discourse-subscriptions.git
synced 2025-03-06 09:39:51 +00:00
various
This commit is contained in:
parent
fd0b53c67c
commit
1b1eb215e4
@ -1,14 +1,20 @@
|
||||
module DiscourseDonations
|
||||
class ChargesController < ::ApplicationController
|
||||
skip_before_action :verify_authenticity_token, only: [:create]
|
||||
|
||||
before_action :ensure_logged_in, only: [:cancel_subscription]
|
||||
before_action :set_user, only: [:index, :create]
|
||||
before_action :set_email, only: [:create]
|
||||
before_action :set_email, only: [:index, :create, :cancel_subscription]
|
||||
|
||||
def index
|
||||
if @user && @user.stripe_customer_id
|
||||
result = DiscourseDonations::Stripe.new(secret_key, stripe_options).list(@user)
|
||||
else
|
||||
result = {}
|
||||
|
||||
if current_user
|
||||
stripe = DiscourseDonations::Stripe.new(secret_key, stripe_options)
|
||||
|
||||
list_result = stripe.list(current_user, email: current_user.email)
|
||||
|
||||
result = list_result if list_result.present?
|
||||
end
|
||||
|
||||
render json: success_json.merge(result)
|
||||
@ -36,7 +42,7 @@ module DiscourseDonations
|
||||
end
|
||||
|
||||
Rails.logger.debug "Creating a Stripe payment"
|
||||
payment = DiscourseDonations::Stripe.new(secret_key, stripe_options)
|
||||
stripe = DiscourseDonations::Stripe.new(secret_key, stripe_options)
|
||||
result = {}
|
||||
|
||||
begin
|
||||
@ -48,17 +54,27 @@ module DiscourseDonations
|
||||
}
|
||||
|
||||
if user_params[:type] === 'once'
|
||||
result[:payment] = payment.charge(@user, opts)
|
||||
result[:charge] = stripe.charge(@user, opts)
|
||||
else
|
||||
opts[:type] = user_params[:type]
|
||||
result[:subscription] = payment.subscribe(@user, opts)
|
||||
|
||||
subscription = stripe.subscribe(@user, opts)
|
||||
|
||||
if subscription && subscription['id']
|
||||
invoices = stripe.invoices_for_subscription(@user,
|
||||
email: opts[:email],
|
||||
subscription_id: subscription['id']
|
||||
)
|
||||
end
|
||||
|
||||
result[:subscription] = {}
|
||||
result[:subscription][:subscription] = subscription if subscription
|
||||
result[:subscription][:invoices] = invoices if invoices
|
||||
end
|
||||
|
||||
rescue ::Stripe::CardError => e
|
||||
err = e.json_body[:error]
|
||||
|
||||
puts "HERE IS THE ERROR: #{e.inspect}"
|
||||
|
||||
output['messages'] << "There was an error (#{err[:type]})."
|
||||
output['messages'] << "Error code: #{err[:code]}" if err[:code]
|
||||
output['messages'] << "Decline code: #{err[:decline_code]}" if err[:decline_code]
|
||||
@ -68,18 +84,16 @@ module DiscourseDonations
|
||||
end
|
||||
|
||||
if (result[:charge] && result[:charge]['paid'] == true) ||
|
||||
(result[:subscription] && result[:subscription]['status'] === 'active')
|
||||
(result[:subscription] && result[:subscription][:subscription] &&
|
||||
result[:subscription][:subscription]['status'] === 'active')
|
||||
|
||||
output['messages'] << I18n.t('donations.payment.success')
|
||||
|
||||
if result[:charge]
|
||||
if (result[:charge] && result[:charge]['receipt_number']) ||
|
||||
(result[:subscription] && result[:subscription][:invoices].first['receipt_number'])
|
||||
output['messages'] << " #{I18n.t('donations.payment.receipt_sent', email: @email)}"
|
||||
end
|
||||
|
||||
if result[:subscription]
|
||||
output['messages'] << " #{I18n.t('donations.payment.invoice_sent', email: @email)}"
|
||||
end
|
||||
|
||||
output['charge'] = result[:charge] if result[:charge]
|
||||
output['subscription'] = result[:subscription] if result[:subscription]
|
||||
|
||||
@ -95,6 +109,20 @@ module DiscourseDonations
|
||||
render json: output
|
||||
end
|
||||
|
||||
def cancel_subscription
|
||||
params.require(:subscription_id)
|
||||
|
||||
stripe = DiscourseDonations::Stripe.new(secret_key, stripe_options)
|
||||
|
||||
result = stripe.cancel_subscription(params[:subscription_id])
|
||||
|
||||
if result[:success]
|
||||
render json: success_json.merge(subscription: result[:subscription])
|
||||
else
|
||||
render json: failed_json.merge(message: result[:message])
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_account
|
||||
@ -132,16 +160,20 @@ module DiscourseDonations
|
||||
user = current_user
|
||||
|
||||
if user_params[:user_id].present?
|
||||
user = User.find(user_params[:user_id])
|
||||
if record = User.find_by(user_params[:user_id])
|
||||
user = record
|
||||
end
|
||||
end
|
||||
|
||||
@user = user
|
||||
end
|
||||
|
||||
def set_email
|
||||
email = nil
|
||||
|
||||
if user_params[:email].present?
|
||||
email = user_params[:email]
|
||||
else
|
||||
elsif @user
|
||||
email = @user.try(:email)
|
||||
end
|
||||
|
||||
|
@ -9,7 +9,13 @@ module DiscourseDonations
|
||||
end
|
||||
|
||||
def checkoutCharge(user = nil, email, token, amount)
|
||||
customer = customer(user, email, token)
|
||||
customer = customer(user,
|
||||
email: email,
|
||||
source: token,
|
||||
create: true
|
||||
)
|
||||
|
||||
return if !customer
|
||||
|
||||
charge = ::Stripe::Charge.create(
|
||||
customer: customer.id,
|
||||
@ -22,7 +28,13 @@ module DiscourseDonations
|
||||
end
|
||||
|
||||
def charge(user = nil, opts)
|
||||
customer = customer(user, opts[:email], opts[:token])
|
||||
customer = customer(user,
|
||||
email: opts[:email],
|
||||
source: opts[:token],
|
||||
create: true
|
||||
)
|
||||
|
||||
return if !customer
|
||||
|
||||
@charge = ::Stripe::Charge.create(
|
||||
customer: customer.id,
|
||||
@ -36,28 +48,40 @@ module DiscourseDonations
|
||||
end
|
||||
|
||||
def subscribe(user = nil, opts)
|
||||
customer = customer(user, opts[:email], opts[:token])
|
||||
customer = customer(user,
|
||||
email: opts[:email],
|
||||
source: opts[:token],
|
||||
create: true
|
||||
)
|
||||
|
||||
return if !customer
|
||||
|
||||
type = opts[:type]
|
||||
amount = opts[:amount]
|
||||
|
||||
plans = ::Stripe::Plan.list
|
||||
type = opts[:type]
|
||||
plan_id = create_plan_id(type)
|
||||
plan_id = create_plan_id(type, amount)
|
||||
|
||||
unless plans.data && plans.data.any? { |p| p['id'] === plan_id }
|
||||
result = create_plan(type, opts[:amount])
|
||||
result = create_plan(type, amount)
|
||||
|
||||
plan_id = result['id']
|
||||
end
|
||||
|
||||
@subscription = ::Stripe::Subscription.create(
|
||||
::Stripe::Subscription.create(
|
||||
customer: customer.id,
|
||||
items: [{ plan: plan_id }]
|
||||
items: [{
|
||||
plan: plan_id
|
||||
}]
|
||||
)
|
||||
|
||||
@subscription
|
||||
end
|
||||
|
||||
def list(user)
|
||||
customer = customer(user)
|
||||
result = {}
|
||||
def list(user, opts = {})
|
||||
customer = customer(user, opts)
|
||||
|
||||
return if !customer
|
||||
|
||||
result = { customer: customer }
|
||||
|
||||
raw_invoices = ::Stripe::Invoice.list(customer: customer.id)
|
||||
raw_invoices = raw_invoices.is_a?(Object) ? raw_invoices['data'] : []
|
||||
@ -66,7 +90,8 @@ module DiscourseDonations
|
||||
raw_charges = raw_charges.is_a?(Object) ? raw_charges['data'] : []
|
||||
|
||||
if raw_invoices.any?
|
||||
raw_subscriptions = ::Stripe::Subscription.list(customer: customer.id)['data']
|
||||
raw_subscriptions = ::Stripe::Subscription.list(customer: customer.id, status: 'all')
|
||||
raw_subscriptions = raw_subscriptions.is_a?(Object) ? raw_subscriptions['data'] : []
|
||||
|
||||
if raw_subscriptions.any?
|
||||
subscriptions = []
|
||||
@ -97,30 +122,90 @@ module DiscourseDonations
|
||||
result
|
||||
end
|
||||
|
||||
def customer(user, email = nil, source = nil)
|
||||
if user && user.stripe_customer_id
|
||||
::Stripe::Customer.retrieve(user.stripe_customer_id)
|
||||
def invoices_for_subscription(user, opts)
|
||||
customer = customer(user,
|
||||
email: opts[:email]
|
||||
)
|
||||
|
||||
invoices = []
|
||||
|
||||
if customer
|
||||
result = ::Stripe::Invoice.list(
|
||||
customer: customer.id,
|
||||
subscription: opts[:subscription_id]
|
||||
)
|
||||
|
||||
invoices = result['data'] if result['data']
|
||||
end
|
||||
|
||||
invoices
|
||||
end
|
||||
|
||||
def cancel_subscription(subscription_id)
|
||||
if subscription = ::Stripe::Subscription.retrieve(subscription_id)
|
||||
result = subscription.delete
|
||||
|
||||
if result['status'] === 'canceled'
|
||||
{ success: true, subscription: subscription }
|
||||
else
|
||||
{ success: false, message: I18n.t('donations.subscription.error.not_cancelled') }
|
||||
end
|
||||
else
|
||||
{ success: false, message: I18n.t('donations.subscription.error.not_found') }
|
||||
end
|
||||
end
|
||||
|
||||
def customer(user, opts = {})
|
||||
customer = nil
|
||||
|
||||
if user && user.stripe_customer_id
|
||||
begin
|
||||
customer = ::Stripe::Customer.retrieve(user.stripe_customer_id)
|
||||
rescue ::Stripe::StripeError => e
|
||||
user.custom_fields['stripe_customer_id'] = nil
|
||||
user.save_custom_fields(true)
|
||||
customer = nil
|
||||
end
|
||||
end
|
||||
|
||||
if !customer && opts[:email]
|
||||
begin
|
||||
customers = ::Stripe::Customer.list(email: opts[:email])
|
||||
|
||||
if customers && customers['data']
|
||||
customer = customers['data'].first if customers['data'].any?
|
||||
end
|
||||
|
||||
if customer && user
|
||||
user.custom_fields['stripe_customer_id'] = customer.id
|
||||
user.save_custom_fields(true)
|
||||
end
|
||||
rescue ::Stripe::StripeError => e
|
||||
customer = nil
|
||||
end
|
||||
end
|
||||
|
||||
if !customer && opts[:create]
|
||||
customer = ::Stripe::Customer.create(
|
||||
email: email,
|
||||
source: source
|
||||
email: opts[:email],
|
||||
source: opts[:source]
|
||||
)
|
||||
|
||||
if user
|
||||
user.custom_fields['stripe_customer_id'] = customer.id
|
||||
user.save_custom_fields(true)
|
||||
end
|
||||
end
|
||||
|
||||
customer
|
||||
end
|
||||
end
|
||||
|
||||
def successful?
|
||||
@charge[:paid]
|
||||
end
|
||||
|
||||
def create_plan(type, amount)
|
||||
id = create_plan_id(type)
|
||||
id = create_plan_id(type, amount)
|
||||
nickname = id.gsub(/_/, ' ').titleize
|
||||
|
||||
products = ::Stripe::Product.list(type: 'service')
|
||||
@ -151,15 +236,15 @@ module DiscourseDonations
|
||||
end
|
||||
|
||||
def product_id
|
||||
@product_id ||= "#{SiteSetting.title}_recurring_donation"
|
||||
@product_id ||= "#{SiteSetting.title}_recurring_donation".freeze
|
||||
end
|
||||
|
||||
def product_name
|
||||
@product_name ||= I18n.t('discourse_donations.recurring', site_title: SiteSetting.title)
|
||||
@product_name ||= I18n.t('donations.recurring', site_title: SiteSetting.title)
|
||||
end
|
||||
|
||||
def create_plan_id(type)
|
||||
"discourse_donation_recurring_#{type}"
|
||||
def create_plan_id(type, amount)
|
||||
"discourse_donation_recurring_#{type}_#{amount}".freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,3 +1,6 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: 'donation-list',
|
||||
hasSubscriptions: Ember.computed.notEmpty('subscriptions'),
|
||||
|
96
assets/javascripts/discourse/components/donation-row.js.es6
Normal file
96
assets/javascripts/discourse/components/donation-row.js.es6
Normal file
@ -0,0 +1,96 @@
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import { formatAnchor, formatAmount } from '../lib/donation-utilities';
|
||||
import { default as computed, observes, on } from 'ember-addons/ember-computed-decorators';
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNameBindings: [':donation-row', 'canceled', 'updating'],
|
||||
includePrefix: Ember.computed.or('invoice', 'charge'),
|
||||
canceled: Ember.computed.equal('subscription.status', 'canceled'),
|
||||
|
||||
@computed('subscription', 'invoice', 'charge', 'customer')
|
||||
data(subscription, invoice, charge, customer) {
|
||||
if (subscription) {
|
||||
return $.extend({}, subscription.plan, {
|
||||
anchor: subscription.billing_cycle_anchor
|
||||
});
|
||||
} else if (invoice) {
|
||||
let receiptSent = false;
|
||||
|
||||
if (invoice.receipt_number && customer.email) {
|
||||
receiptSent = true;
|
||||
}
|
||||
|
||||
return $.extend({}, invoice.lines.data[0], {
|
||||
anchor: invoice.date,
|
||||
invoiceLink: invoice.invoice_pdf,
|
||||
receiptSent
|
||||
});
|
||||
} else if (charge) {
|
||||
let receiptSent = false;
|
||||
|
||||
if (charge.receipt_number && charge.receipt_email) {
|
||||
receiptSent = true;
|
||||
}
|
||||
|
||||
return $.extend({}, charge, {
|
||||
anchor: charge.created,
|
||||
receiptSent
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@computed('data.currency')
|
||||
currency(currency) {
|
||||
return currency ? currency.toUpperCase() : null;
|
||||
},
|
||||
|
||||
@computed('data.amount', 'currency')
|
||||
amount(amount, currency) {
|
||||
return formatAmount(amount, currency);
|
||||
},
|
||||
|
||||
@computed('data.interval')
|
||||
interval(interval) {
|
||||
return interval || 'once';
|
||||
},
|
||||
|
||||
@computed('data.anchor', 'interval')
|
||||
period(anchor, interval) {
|
||||
return I18n.t(`discourse_donations.period.${interval}`, {
|
||||
anchor: formatAnchor(interval, moment.unix(anchor))
|
||||
})
|
||||
},
|
||||
|
||||
cancelSubscription() {
|
||||
const subscriptionId = this.get('subscription.id');
|
||||
this.set('updating', true);
|
||||
|
||||
ajax('/donate/charges/cancel-subscription', {
|
||||
data: {
|
||||
subscription_id: subscriptionId
|
||||
},
|
||||
method: 'put'
|
||||
}).then(result => {
|
||||
if (result.success) {
|
||||
this.set('subscription', result.subscription);
|
||||
}
|
||||
}).catch(popupAjaxError).finally(() => {
|
||||
this.set('updating', false);
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
cancelSubscription() {
|
||||
showModal('cancel-subscription', {
|
||||
model: {
|
||||
currency: this.get('currency'),
|
||||
amount: this.get('amount'),
|
||||
period: this.get('period'),
|
||||
confirm: () => this.cancelSubscription()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
@ -175,7 +175,7 @@ export default Ember.Component.extend({
|
||||
const transactionFeeEnabled = settings.discourse_donations_enable_transaction_fee;
|
||||
let amount = transactionFeeEnabled ? this.get('totalAmount') : this.get('amount');
|
||||
|
||||
if (zeroDecimalCurrencies.indexOf(setting.discourse_donations_currency) === -1) {
|
||||
if (zeroDecimalCurrencies.indexOf(settings.discourse_donations_currency) === -1) {
|
||||
amount = amount * 100;
|
||||
}
|
||||
|
||||
@ -189,22 +189,26 @@ export default Ember.Component.extend({
|
||||
};
|
||||
|
||||
if(!self.get('paymentSuccess')) {
|
||||
ajax('/donate/charges', { data: params, method: 'post' }).then(d => {
|
||||
let donation = d.donation;
|
||||
|
||||
if (donation) {
|
||||
if (donation.object === 'subscription') {
|
||||
let subscriptions = this.get('subscriptions') || [];
|
||||
subscriptions.push(donation);
|
||||
this.set('subscriptions', subscriptions);
|
||||
} else if (donation.object === 'charge') {
|
||||
let charges = this.get('charges') || [];
|
||||
charges.push(donation);
|
||||
this.set('charges', charges);
|
||||
}
|
||||
ajax('/donate/charges', {
|
||||
data: params,
|
||||
method: 'post'
|
||||
}).then(result => {
|
||||
if (result.subscription) {
|
||||
let subscription = $.extend({}, result.subscription, {
|
||||
new: true
|
||||
});
|
||||
this.get('subscriptions').unshiftObject(subscription);
|
||||
}
|
||||
|
||||
self.concatMessages(d.messages);
|
||||
if (result.charge) {
|
||||
let charge = $.extend({}, result.charge, {
|
||||
new: true
|
||||
});
|
||||
this.get('charges').unshiftObject(charge);
|
||||
}
|
||||
|
||||
self.concatMessages(result.messages);
|
||||
|
||||
self.endTranscation();
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
confirm() {
|
||||
this.get('model.confirm')();
|
||||
this.send('closeModal');
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.send('closeModal');
|
||||
}
|
||||
}
|
||||
})
|
@ -1,11 +1,53 @@
|
||||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import { getOwner } from 'discourse-common/lib/get-owner';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
loadingDonations: false,
|
||||
loadDonationsDisabled: Ember.computed.not('emailVaild'),
|
||||
|
||||
@computed('charges', 'subscriptions')
|
||||
@computed('charges.[]', 'subscriptions.[]')
|
||||
hasDonations(charges, subscriptions) {
|
||||
return (charges && charges.length > 0) ||
|
||||
(subscriptions && subscriptions.length > 0);
|
||||
},
|
||||
|
||||
@computed('email')
|
||||
emailVaild(email) {
|
||||
return emailValid(email);
|
||||
},
|
||||
|
||||
actions: {
|
||||
loadDonations() {
|
||||
let email = this.get('email');
|
||||
|
||||
this.set('loadingDonations', true);
|
||||
|
||||
ajax('/donate/charges', {
|
||||
data: { email },
|
||||
type: 'GET'
|
||||
}).then((result) => {
|
||||
this.setProperties({
|
||||
charges: Ember.A(result.charges),
|
||||
subscriptions: Ember.A(result.subscriptions),
|
||||
customer: result.customer
|
||||
});
|
||||
}).catch(popupAjaxError).finally(() => {
|
||||
this.setProperties({
|
||||
loadingDonations: false,
|
||||
hasEmailResult: true
|
||||
});
|
||||
|
||||
Ember.run.later(() => {
|
||||
this.set('hasEmailResult', false);
|
||||
}, 6000)
|
||||
})
|
||||
},
|
||||
|
||||
showLogin() {
|
||||
const controller = getOwner(this).lookup('route:application');
|
||||
controller.send('showLogin');
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1,56 +0,0 @@
|
||||
import { registerHelper } from "discourse-common/lib/helpers";
|
||||
import { formatAnchor, formatAmount } from '../lib/donation-utilities';
|
||||
|
||||
registerHelper("donation-subscription", function([subscription]) {
|
||||
let currency = subscription.plan.currency.toUpperCase();
|
||||
let html = currency;
|
||||
|
||||
html += ` ${formatAmount(subscription.plan.amount, currency)} `;
|
||||
|
||||
html += I18n.t(`discourse_donations.period.${subscription.plan.interval}`, {
|
||||
anchor: formatAnchor(subscription.plan.interval, moment.unix(subscription.billing_cycle_anchor))
|
||||
});
|
||||
|
||||
return new Handlebars.SafeString(html);
|
||||
});
|
||||
|
||||
registerHelper("donation-invoice", function([invoice]) {
|
||||
let details = invoice.lines.data[0];
|
||||
let html = I18n.t('discourse_donations.invoice_prefix');
|
||||
let currency = details.currency.toUpperCase();
|
||||
|
||||
html += ` ${currency}`;
|
||||
|
||||
html += ` ${formatAmount(details.amount, currency)} `;
|
||||
|
||||
html += I18n.t(`discourse_donations.period.once`, {
|
||||
anchor: formatAnchor('once', moment.unix(invoice.date))
|
||||
});
|
||||
|
||||
if (invoice.invoice_pdf) {
|
||||
html += ` (<a href='${invoice.invoice_pdf}' target='_blank'>${I18n.t('discourse_donations.invoice')}</a>)`;
|
||||
}
|
||||
|
||||
return new Handlebars.SafeString(html);
|
||||
});
|
||||
|
||||
registerHelper("donation-charge", function([charge]) {
|
||||
let html = I18n.t('discourse_donations.invoice_prefix');
|
||||
let currency = charge.currency.toUpperCase();
|
||||
|
||||
html += ` ${currency}`;
|
||||
|
||||
html += ` ${formatAmount(charge.amount, currency)} `;
|
||||
|
||||
html += I18n.t(`discourse_donations.period.once`, {
|
||||
anchor: formatAnchor('once', moment.unix(charge.created))
|
||||
});
|
||||
|
||||
if (charge.receipt_email) {
|
||||
html += `. ${I18n.t('discourse_donations.receipt', {
|
||||
email: charge.receipt_email
|
||||
})}`;
|
||||
}
|
||||
|
||||
return new Handlebars.SafeString(html);
|
||||
});
|
@ -4,15 +4,24 @@ import { ajax } from 'discourse/lib/ajax';
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
setupController(controller) {
|
||||
let charges = [];
|
||||
let subscriptions = [];
|
||||
let customer = {};
|
||||
|
||||
controller.set('loadingDonations', true);
|
||||
|
||||
ajax('/donate/charges').then((result) => {
|
||||
if (result && (result.charges || result.subscriptions)) {
|
||||
controller.setProperties({
|
||||
charges: result.charges,
|
||||
subscriptions: result.subscriptions
|
||||
});
|
||||
if (result) {
|
||||
charges = result.charges;
|
||||
subscriptions = result.subscriptions;
|
||||
customer = result.customer;
|
||||
}
|
||||
|
||||
controller.setProperties({
|
||||
charges: Ember.A(charges),
|
||||
subscriptions: Ember.A(subscriptions),
|
||||
customer
|
||||
});
|
||||
}).catch(popupAjaxError).finally(() => {
|
||||
controller.set('loadingDonations', false);
|
||||
})
|
||||
|
@ -3,12 +3,11 @@
|
||||
<div class="underline">{{i18n 'discourse_donations.donations.subscriptions'}}</div>
|
||||
<ul>
|
||||
{{#each subscriptions as |s|}}
|
||||
<li>{{donation-subscription s.subscription}}</li>
|
||||
|
||||
<li>{{donation-row subscription=s.subscription customer=customer new=s.new}}</li>
|
||||
{{#if s.invoices}}
|
||||
<ul>
|
||||
{{#each s.invoices as |invoice|}}
|
||||
<li>{{donation-invoice invoice}}</li>
|
||||
<li>{{donation-row invoice=invoice customer=customer new=s.new}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
@ -22,7 +21,7 @@
|
||||
<div class='underline'>{{i18n 'discourse_donations.donations.charges'}}</div>
|
||||
<ul>
|
||||
{{#each charges as |charge|}}
|
||||
<li>{{donation-charge charge}}</li>
|
||||
<li>{{donation-row charge=charge customer=customer new=charge.new}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -0,0 +1,39 @@
|
||||
{{#if includePrefix}}
|
||||
<span>{{i18n 'discourse_donations.invoice_prefix'}}</span>
|
||||
{{/if}}
|
||||
|
||||
<span>{{currency}}</span>
|
||||
|
||||
<span>{{amount}}</span>
|
||||
|
||||
<span>{{period}}</span>
|
||||
|
||||
{{#if invoice}}
|
||||
<a href='{{data.invoiceLink}}' target='_blank'>({{i18n 'discourse_donations.invoice'}})</a>
|
||||
{{/if}}
|
||||
|
||||
{{#if currentUser}}
|
||||
{{#if subscription}}
|
||||
{{#if updating}}
|
||||
{{loading-spinner size='small'}}
|
||||
{{else}}
|
||||
{{#unless canceled}}
|
||||
<a {{action 'cancelSubscription'}}>
|
||||
{{i18n 'cancel'}}
|
||||
</a>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if receiptSent}}
|
||||
<span>–</span>
|
||||
<span>{{i18n 'discourse_donations.receipt' email=customer.email}}</span>
|
||||
{{/if}}
|
||||
|
||||
{{#if new}}
|
||||
<span class="new-flag">
|
||||
{{d-icon 'circle'}}
|
||||
<span>{{i18n 'new_item'}}</span>
|
||||
</span>
|
||||
{{/if}}
|
@ -33,6 +33,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class='control-label'>
|
||||
{{i18n 'discourse_donations.transaction_fee.total'}}
|
||||
|
@ -8,17 +8,29 @@
|
||||
{{stripe-card charges=charges subscriptions=subscriptions}}
|
||||
</div>
|
||||
|
||||
{{#if currentUser}}
|
||||
<div class="donations-page-donations">
|
||||
<div class="donations-page-donations">
|
||||
<h3>{{i18n 'discourse_donations.donations.title'}}</h3>
|
||||
{{#if loadingDonations}}
|
||||
<span>{{i18n 'discourse_donations.donations.loading'}}</span>
|
||||
{{loading-spinner size='small'}}
|
||||
{{else}}
|
||||
{{#if currentUser}}
|
||||
{{#if hasDonations}}
|
||||
{{donation-list charges=charges subscriptions=subscriptions}}
|
||||
{{donation-list charges=charges subscriptions=subscriptions customer=customer}}
|
||||
{{else}}
|
||||
{{i18n 'discourse_donations.donations.none'}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if hasDonations}}
|
||||
{{donation-list charges=charges subscriptions=subscriptions customer=customer}}
|
||||
{{else}}
|
||||
{{#if hasEmailResult}}
|
||||
{{i18n 'discourse_donations.donations.none_email' email=email}}
|
||||
{{else}}
|
||||
{{input value=email placeholder=(i18n 'email')}}
|
||||
{{d-button action='loadDonations' label='discourse_donations.donations.load' disabled=loadDonationsDisabled}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
@ -0,0 +1,11 @@
|
||||
{{#d-modal-body title='discourse_donations.subscription.cancel.title'}}
|
||||
{{i18n 'discourse_donations.subscription.cancel.description' site=siteSettings.title
|
||||
currency=model.currency
|
||||
amount=model.amount
|
||||
period=model.period}}
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
{{d-button action='confirm' label='yes_value' class='btn-primary'}}
|
||||
{{d-button action='cancel' label='no_value'}}
|
||||
</div>
|
@ -61,11 +61,15 @@ div.stripe-errors {
|
||||
.donation-list {
|
||||
.subscription-list, .charge-list {
|
||||
margin-bottom: 10px;
|
||||
display: inline-block;
|
||||
|
||||
> ul {
|
||||
margin: 10px 0;
|
||||
list-style: none;
|
||||
|
||||
.spinner {
|
||||
height: 5px;
|
||||
width: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,3 +79,32 @@ div.stripe-errors {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.donation-row {
|
||||
span {
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
&.canceled {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
&.updating {
|
||||
color: $primary-low;
|
||||
}
|
||||
|
||||
.new-flag {
|
||||
color: $tertiary;
|
||||
margin-left: 5px;
|
||||
|
||||
.fa {
|
||||
line-height: 16px;
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
> * {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,11 +27,17 @@ en:
|
||||
title: "Make a Donation"
|
||||
amount: Amount
|
||||
card: Card
|
||||
submit: Make Payment
|
||||
submit: Donate
|
||||
submit_with_create_account: Make Payment and Create Account
|
||||
invoice: "Invoice"
|
||||
invoice: "invoice"
|
||||
invoice_prefix: "You gave"
|
||||
receipt: "Receipt sent to {{email}}."
|
||||
subscription:
|
||||
cancel:
|
||||
title: "Cancel Recurring Donation"
|
||||
description: >
|
||||
Are you sure you want to cancel your recurring donation to {{site}}
|
||||
of {{currency}} {{amount}} {{period}}?
|
||||
email_instructions: "Required to send you a receipt. Not used for marketing."
|
||||
transaction_fee:
|
||||
label: "Include transaction fee of {{currency}} {{transactionFee}}"
|
||||
@ -52,6 +58,9 @@ en:
|
||||
year: "every year on {{anchor}}"
|
||||
donations:
|
||||
title: "Your Donations"
|
||||
load: "Load Donations"
|
||||
loading: "Loading donations"
|
||||
charges: "Once Off"
|
||||
subscriptions: "Recurring"
|
||||
none: "You haven't made a donation yet."
|
||||
none_email: "There are no donations for {{email}}."
|
||||
|
@ -1,7 +1,11 @@
|
||||
en:
|
||||
donations:
|
||||
recurring: "%{site_title} recurring donation"
|
||||
recurring: "%{site_title} Recurring Donation"
|
||||
payment:
|
||||
success: 'Thank you, your donation has been successful.'
|
||||
receipt_sent: 'A receipt has been sent to %{email}.'
|
||||
invoice_sent: 'An invoice has been sent to %{email}.'
|
||||
subscription:
|
||||
error:
|
||||
not_found: "Subscription not found."
|
||||
not_cancelled: "Subscription not cancelled."
|
||||
|
@ -1,5 +1,8 @@
|
||||
DiscourseDonations::Engine.routes.draw do
|
||||
get '/' => 'charges#index'
|
||||
|
||||
resources :charges, only: [:index, :create]
|
||||
put '/charges/cancel-subscription' => 'charges#cancel_subscription'
|
||||
|
||||
resources :checkout, only: [:create]
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user