diff --git a/app/controllers/discourse_donations/charges_controller.rb b/app/controllers/discourse_donations/charges_controller.rb
index 017be3f..b157130 100644
--- a/app/controllers/discourse_donations/charges_controller.rb
+++ b/app/controllers/discourse_donations/charges_controller.rb
@@ -48,6 +48,7 @@ module DiscourseDonations
begin
Rails.logger.debug "Creating a Stripe charge for #{user_params[:amount]}"
opts = {
+ cause: user_params[:cause],
email: @email,
token: user_params[:stripeToken],
amount: user_params[:amount]
@@ -153,7 +154,7 @@ module DiscourseDonations
end
def user_params
- params.permit(:user_id, :name, :username, :email, :password, :stripeToken, :type, :amount, :create_account)
+ params.permit(:user_id, :name, :username, :email, :password, :stripeToken, :cause, :type, :amount, :create_account)
end
def set_user
diff --git a/app/jobs/jobs.rb b/app/jobs/jobs.rb
index e804950..1a1620c 100644
--- a/app/jobs/jobs.rb
+++ b/app/jobs/jobs.rb
@@ -1 +1,2 @@
load File.expand_path('../regular/donation_user.rb', __FILE__)
+load File.expand_path('../scheduled/update_category_donation_statistics.rb', __FILE__)
diff --git a/app/jobs/scheduled/update_category_donation_statistics.rb b/app/jobs/scheduled/update_category_donation_statistics.rb
new file mode 100644
index 0000000..c22f613
--- /dev/null
+++ b/app/jobs/scheduled/update_category_donation_statistics.rb
@@ -0,0 +1,69 @@
+module Jobs
+ class UpdateCategoryDonationStatistics < ::Jobs::Scheduled
+ every 1.hour
+
+ def execute(args)
+ return unless SiteSetting.discourse_donations_cause_category
+
+ ::Stripe.api_key = SiteSetting.discourse_donations_secret_key
+ totals = {}
+ backers = {}
+ categories = []
+
+ raw_charges = ::Stripe::Charge.list(
+ expand: ['data.invoice.subscription', 'data.customer']
+ )
+ raw_charges = raw_charges.is_a?(Object) ? raw_charges['data'] : []
+
+ raw_charges.each do |c|
+ cause_base = c['invoice'] && c['invoice']['subscription'] ? c['invoice']['subscription'] : c
+ category_id = cause_base['metadata']['discourse_cause'].to_i
+
+ backer_base = c['customer']
+ backer_user_id = backer_base['metadata']['discourse_user_id'].to_i
+ backer_email = backer_base['email']
+
+ if category_id > 0 && Category.exists?(id: category_id)
+ categories.push(category_id)
+
+ current = totals[category_id] || {}
+ amount = c['amount'].to_i
+ date = Time.at(c['created']).to_datetime
+
+ totals[category_id] ||= {}
+ totals[category_id][:total] ||= 0
+ totals[category_id][:month] ||= 0
+
+ totals[category_id][:total] += amount
+
+ if date.month == Date.today.month
+ totals[category_id][:month] += amount
+ end
+
+ backers[category_id] ||= []
+
+ if backer_user_id > 0 && User.exists?(id: backer_user_id)
+ backers[category_id].push(backer_user_id) unless backers[category_id].include? backer_user_id
+ elsif user = User.find_by_email(backer_email)
+ backers[category_id].push(user.id) unless backers[category_id].include? user.id
+ end
+ end
+ end
+
+ categories.each do |category_id|
+ category = Category.find(category_id)
+
+ if totals[category_id]
+ category.custom_fields['donations_total'] = totals[category_id][:total]
+ category.custom_fields['donations_month'] = totals[category_id][:month]
+ end
+
+ if backers[category_id]
+ category.custom_fields['donations_backers'] = backers[category_id]
+ end
+
+ category.save_custom_fields(true)
+ end
+ end
+ end
+end
diff --git a/app/services/discourse_donations/stripe.rb b/app/services/discourse_donations/stripe.rb
index cf7288e..fec2d2c 100644
--- a/app/services/discourse_donations/stripe.rb
+++ b/app/services/discourse_donations/stripe.rb
@@ -41,7 +41,11 @@ module DiscourseDonations
amount: opts[:amount],
description: @description,
currency: @currency,
- receipt_email: customer.email
+ receipt_email: customer.email,
+ metadata: {
+ discourse_cause: opts[:cause],
+ discourse_user_id: user.id
+ }
)
@charge
@@ -72,7 +76,11 @@ module DiscourseDonations
customer: customer.id,
items: [{
plan: plan_id
- }]
+ }],
+ metadata: {
+ discourse_cause: opts[:cause],
+ discourse_user_id: user.id
+ }
)
end
@@ -186,10 +194,18 @@ module DiscourseDonations
end
if !customer && opts[:create]
- customer = ::Stripe::Customer.create(
+ customer_opts = {
email: opts[:email],
source: opts[:source]
- )
+ }
+
+ if user
+ customer_opts[:metadata] = {
+ discourse_user_id: user.id
+ }
+ end
+
+ customer = ::Stripe::Customer.create(customer_opts)
if user
user.custom_fields['stripe_customer_id'] = customer.id
diff --git a/assets/javascripts/discourse/components/donation-list.js.es6 b/assets/javascripts/discourse/components/donation-list.js.es6
index 3b9b4da..57ec8f9 100644
--- a/assets/javascripts/discourse/components/donation-list.js.es6
+++ b/assets/javascripts/discourse/components/donation-list.js.es6
@@ -1,8 +1,5 @@
-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'),
hasCharges: Ember.computed.notEmpty('charges')
-})
+});
diff --git a/assets/javascripts/discourse/components/donation-row.js.es6 b/assets/javascripts/discourse/components/donation-row.js.es6
index 56533f5..9c00574 100644
--- a/assets/javascripts/discourse/components/donation-row.js.es6
+++ b/assets/javascripts/discourse/components/donation-row.js.es6
@@ -1,7 +1,7 @@
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 { default as computed } from 'ember-addons/ember-computed-decorators';
import showModal from "discourse/lib/show-modal";
export default Ember.Component.extend({
@@ -60,7 +60,7 @@ export default Ember.Component.extend({
period(anchor, interval) {
return I18n.t(`discourse_donations.period.${interval}`, {
anchor: formatAnchor(interval, moment.unix(anchor))
- })
+ });
},
cancelSubscription() {
@@ -93,4 +93,4 @@ export default Ember.Component.extend({
});
}
}
-})
+});
diff --git a/assets/javascripts/discourse/components/stripe-card.js.es6 b/assets/javascripts/discourse/components/stripe-card.js.es6
index 2708ca1..c123caa 100644
--- a/assets/javascripts/discourse/components/stripe-card.js.es6
+++ b/assets/javascripts/discourse/components/stripe-card.js.es6
@@ -1,7 +1,7 @@
import { ajax } from 'discourse/lib/ajax';
import { formatAnchor, zeroDecimalCurrencies } from '../lib/donation-utilities';
import { default as computed } from 'ember-addons/ember-computed-decorators';
-import { emailValid } from "discourse/lib/utilities";
+import { emailValid as emailValidHelper } from "discourse/lib/utilities";
export default Ember.Component.extend({
result: [],
@@ -29,6 +29,34 @@ export default Ember.Component.extend({
});
},
+ @computed
+ causes() {
+ const categoryEnabled = Discourse.SiteSettings.discourse_donations_cause_category;
+
+ if (categoryEnabled) {
+ let categoryIds = Discourse.SiteSettings.discourse_donations_causes_categories.split('|');
+
+ if (categoryIds.length) {
+ categoryIds = categoryIds.map(Number);
+ return this.site
+ .get("categoriesList")
+ .filter(c => {
+ return categoryIds.indexOf(c.id) > -1;
+ }).map(c => {
+ return {
+ id: c.id,
+ name: c.name
+ };
+ });
+ } else {
+ return [];
+ }
+ } else {
+ const causes = Discourse.SiteSettings.discourse_donations_causes;
+ return causes ? causes.split('|') : [];
+ }
+ },
+
@computed('types')
donationTypes(types) {
return types.map((type) => {
@@ -97,7 +125,7 @@ export default Ember.Component.extend({
@computed('email')
emailValid(email) {
- return emailValid(email);
+ return emailValidHelper(email);
},
@computed('email', 'emailValid')
@@ -110,9 +138,14 @@ export default Ember.Component.extend({
return currentUser || emailValid;
},
- @computed('userReady', 'stripeReady')
- formIncomplete(userReady, stripeReady) {
- return !userReady || !stripeReady;
+ @computed('cause')
+ causeValid(cause) {
+ return cause || !Discourse.SiteSettings.discourse_donations_cause_required;
+ },
+
+ @computed('userReady', 'stripeReady', 'causeValid')
+ formIncomplete(userReady, stripeReady, causeValid) {
+ return !userReady || !stripeReady || !causeValid;
},
@computed('transactionInProgress', 'formIncomplete')
@@ -181,6 +214,7 @@ export default Ember.Component.extend({
let params = {
stripeToken: data.token.id,
+ cause: self.get('cause'),
type: self.get('type'),
amount,
email: self.get('email'),
diff --git a/assets/javascripts/discourse/connectors/below-site-header/donations-category-header-container.hbs b/assets/javascripts/discourse/connectors/below-site-header/donations-category-header-container.hbs
new file mode 100644
index 0000000..8de7bcd
--- /dev/null
+++ b/assets/javascripts/discourse/connectors/below-site-header/donations-category-header-container.hbs
@@ -0,0 +1,3 @@
+{{#if siteSettings.discourse_donations_cause_category}}
+ {{mount-widget widget="category-header-widget"}}
+{{/if}}
diff --git a/assets/javascripts/discourse/connectors/category-custom-settings/donations_category_settings.hbs b/assets/javascripts/discourse/connectors/category-custom-settings/donations_category_settings.hbs
new file mode 100644
index 0000000..42048b2
--- /dev/null
+++ b/assets/javascripts/discourse/connectors/category-custom-settings/donations_category_settings.hbs
@@ -0,0 +1,11 @@
+{{#if siteSettings.discourse_donations_cause_category}}
+