diff --git a/app/controllers/admin/plans_controller.rb b/app/controllers/admin/plans_controller.rb index 4f7c8b7..818156e 100644 --- a/app/controllers/admin/plans_controller.rb +++ b/app/controllers/admin/plans_controller.rb @@ -48,6 +48,22 @@ module DiscoursePatrons end end + def update + begin + plan = ::Stripe::Plan.update( + params[:id], + nickname: params[:nickname], + trial_period_days: params[:trial_period_days], + metadata: { group_name: params[:metadata][:group_name] } + ) + + render_json_dump plan + + rescue ::Stripe::InvalidRequestError => e + return render_json_error e.message + end + end + def destroy begin plan = ::Stripe::Plan.delete(params[:id]) diff --git a/app/controllers/admin/products_controller.rb b/app/controllers/admin/products_controller.rb index 211226a..66ffd03 100644 --- a/app/controllers/admin/products_controller.rb +++ b/app/controllers/admin/products_controller.rb @@ -19,9 +19,13 @@ module DiscoursePatrons def create begin - product = ::Stripe::Product.create( - product_params.merge(type: 'service') - ) + create_params = product_params.merge!(type: 'service') + + if params[:statement_descriptor].blank? + create_params.except!(:statement_descriptor) + end + + product = ::Stripe::Product.create(create_params) render_json_dump product @@ -71,8 +75,8 @@ module DiscoursePatrons def product_params { name: params[:name], - statement_descriptor: params[:statement_descriptor], active: params[:active], + statement_descriptor: params[:statement_descriptor] } end end diff --git a/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 b/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 index 5ddcf94..80ff5aa 100644 --- a/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 @@ -1,6 +1,17 @@ +import computed from "ember-addons/ember-computed-decorators"; import DiscourseURL from "discourse/lib/url"; export default Ember.Controller.extend({ + @computed("model.plan.isNew") + planFieldDisabled(isNew) { + return !isNew; + }, + + @computed("model.product.id") + productId(id) { + return id; + }, + redirect(product_id) { DiscourseURL.redirectTo(`/admin/plugins/discourse-patrons/products/${product_id}`); }, @@ -11,8 +22,19 @@ export default Ember.Controller.extend({ }, createPlan() { - const product_id = this.get('model.plan.product'); - this.get('model.plan').save().then(() => this.redirect(product_id)); + // TODO: set default group name beforehand + if (this.get("model.plan.metadata.group_name") === undefined) { + this.set( + "model.plan.metadata", + { group_name: this.get("model.groups.firstObject.name") } + ); + } + + this.get('model.plan').save().then(() => this.redirect(this.productId)); + }, + + updatePlan() { + this.get('model.plan').update().then(() => this.redirect(this.productId)); } } }); diff --git a/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show.js.es6 b/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show.js.es6 index 2f15386..8a61647 100644 --- a/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-plugins-discourse-patrons-products-show.js.es6 @@ -1,34 +1,26 @@ import { popupAjaxError } from "discourse/lib/ajax-error"; export default Ember.Controller.extend({ - redirect() { - this.transitionToRoute("adminPlugins.discourse-patrons.products"); - }, - actions: { cancelProduct() { - this.redirect(); + this.transitionToRoute("adminPlugins.discourse-patrons.products"); }, createProduct() { - // TODO: set default group name beforehand - if (this.get("model.product.metadata.group_name") === undefined) { - this.set( - "model.product.metadata", - { group_name: this.get("model.groups.firstObject.name") } - ); - } - this.get("model.product") .save() - .then(() => this.redirect()) + .then(product => { + this.transitionToRoute("adminPlugins.discourse-patrons.products.show", product.id); + }) .catch(popupAjaxError); }, updateProduct() { this.get("model.product") .update() - .then(() => this.redirect()) + .then(() => { + this.transitionToRoute("adminPlugins.discourse-patrons.products"); + }) .catch(popupAjaxError); } } diff --git a/assets/javascripts/discourse/models/admin-plan.js.es6 b/assets/javascripts/discourse/models/admin-plan.js.es6 index ac23d9c..10ed2b2 100644 --- a/assets/javascripts/discourse/models/admin-plan.js.es6 +++ b/assets/javascripts/discourse/models/admin-plan.js.es6 @@ -2,6 +2,7 @@ import computed from "ember-addons/ember-computed-decorators"; import { ajax } from "discourse/lib/ajax"; const AdminPlan = Discourse.Model.extend({ + isNew: false, name: "", interval: "month", amount: 0, @@ -13,6 +14,16 @@ const AdminPlan = Discourse.Model.extend({ return moment.unix(created).format(); }, + @computed("trial_period_days") + parseTrialPeriodDays(trial_period_days) { + if(trial_period_days) { + return parseInt(0 + trial_period_days); + } + else { + return 0; + } + }, + destroy() { return ajax(`/patrons/admin/plans/${this.id}`, { method: "delete" }); }, @@ -22,12 +33,22 @@ const AdminPlan = Discourse.Model.extend({ nickname: this.nickname, interval: this.interval, amount: this.amount, - trial_period_days: this.trial_period_days, + trial_period_days: this.parseTrialPeriodDays, product: this.product, metadata: this.metadata, }; return ajax("/patrons/admin/plans", { method: "post", data }); + }, + + update() { + const data = { + nickname: this.nickname, + trial_period_days: this.parseTrialPeriodDays, + metadata: this.metadata, + }; + + return ajax(`/patrons/admin/plans/${this.id}`, { method: "patch", data }); } }); diff --git a/assets/javascripts/discourse/models/admin-product.js.es6 b/assets/javascripts/discourse/models/admin-product.js.es6 index 9f1f68d..28202c6 100644 --- a/assets/javascripts/discourse/models/admin-product.js.es6 +++ b/assets/javascripts/discourse/models/admin-product.js.es6 @@ -22,7 +22,9 @@ const AdminProduct = Discourse.Model.extend({ active: this.active }; - return ajax("/patrons/admin/products", { method: "post", data }); + return ajax("/patrons/admin/products", { method: "post", data }).then(product => + AdminProduct.create(product) + ); }, update() { diff --git a/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 b/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 index 4d6f566..73cebf3 100644 --- a/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 +++ b/assets/javascripts/discourse/routes/admin-plugins-discourse-patrons-products-show-plans-show.js.es6 @@ -8,7 +8,7 @@ export default Discourse.Route.extend({ let plan; if(id === 'new') { - plan = AdminPlan.create({ product: product.get('id') }); + plan = AdminPlan.create({ isNew: true, product: product.get('id') }); } else { plan = AdminPlan.find(id); diff --git a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-index.hbs b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-index.hbs index bf17fd4..1644d9e 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-index.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-index.hbs @@ -9,17 +9,15 @@ - - + {{#each model as |product|}} - - +
{{i18n 'discourse_patrons.admin.products.product.name'}}{{i18n 'discourse_patrons.admin.products.product.group'}} {{i18n 'discourse_patrons.admin.products.product.created_at'}}{{i18n 'discourse_patrons.admin.products.product.active'}}{{i18n 'discourse_patrons.admin.products.product.active'}}
{{product.name}}{{product.metadata.group_name}} {{format-date product.createdFormatted}}{{product.active}}{{product.active}} {{#link-to "adminPlugins.discourse-patrons.products.show" product.id class="btn no-text btn-icon"}} {{d-icon "far-edit"}} diff --git a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show-plans-show.hbs b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show-plans-show.hbs index a5a99bd..76a1b90 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show-plans-show.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show-plans-show.hbs @@ -22,7 +22,7 @@

- {{input type="text" name="name" value=model.plan.amount}} + {{input type="text" name="name" value=model.plan.amount disabled=planFieldDisabled}}

{{d-button label="cancel" action=(action "cancelPlan" model.plan.product) icon="times"}} - {{d-button label="discourse_patrons.admin.plans.operations.create" action="createPlan" icon="plus" class="btn btn-primary"}} + + {{#if model.plan.isNew}} + {{d-button label="discourse_patrons.admin.plans.operations.create" action="createPlan" icon="plus" class="btn btn-primary"}} + {{else}} + {{d-button label="discourse_patrons.admin.plans.operations.update" action="updatePlan" icon="check" class="btn btn-primary"}} + {{/if}}
diff --git a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show.hbs b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show.hbs index 3626701..1e6cf49 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-discourse-patrons-products-show.hbs @@ -20,53 +20,54 @@

-

{{i18n 'discourse_patrons.admin.plans.title'}}

+{{#unless model.product.isNew}} +

{{i18n 'discourse_patrons.admin.plans.title'}}

+ +

+ + + + + + + + + + {{#each model.plans as |plan|}} + + + + + + + + + {{/each}} -

-

{{i18n 'discourse_patrons.admin.plans.plan.nickname'}}{{i18n 'discourse_patrons.admin.plans.plan.interval'}}{{i18n 'discourse_patrons.admin.plans.plan.created_at'}}{{i18n 'discourse_patrons.admin.plans.plan.group'}}{{i18n 'discourse_patrons.admin.plans.plan.amount'}} + {{#link-to "adminPlugins.discourse-patrons.products.show.plans.show" model.product.id "new" class="btn"}} + {{i18n 'discourse_patrons.admin.plans.operations.add'}} + {{/link-to}} +
{{plan.nickname}}{{plan.interval}}{{format-date plan.createdFormatted}}{{plan.metadata.group_name}}{{plan.amount}} + {{#link-to "adminPlugins.discourse-patrons.products.show.plans.show" model.product.id plan.id class="btn no-text btn-icon"}} + {{d-icon "far-edit"}} + {{/link-to}} + {{d-button + action=(route-action "destroyPlan") + actionParam=plan + icon="trash-alt" + class="btn-danger btn no-text btn-icon"}} +
- - - - - - - - - {{#each model.plans as |plan|}} - - - - - - - {{/each}} - - - - -
{{i18n 'discourse_patrons.admin.plans.plan.nickname'}}{{i18n 'discourse_patrons.admin.plans.plan.interval'}}{{i18n 'discourse_patrons.admin.plans.plan.created_at'}}{{i18n 'discourse_patrons.admin.plans.plan.group'}}{{i18n 'discourse_patrons.admin.plans.plan.amount'}} - {{#link-to "adminPlugins.discourse-patrons.products.show.plans.show" model.product.id "new" class="btn"}} - {{i18n 'discourse_patrons.admin.plans.operations.add'}} - {{/link-to}} -
{{plan.nickname}}{{plan.interval}}{{format-date plan.createdFormatted}}{{plan.metadata.group_name}}{{plan.amount}} - {{#link-to "adminPlugins.discourse-patrons.products.show.plans.show" model.product.id plan.id class="btn no-text btn-icon"}} - {{d-icon "far-edit"}} - {{/link-to}} - {{d-button - action=(route-action "destroyPlan") - actionParam=plan - icon="trash-alt" - class="btn-danger btn no-text btn-icon"}} + + {{#unless model.plans}} +
+ {{i18n 'discourse_patrons.admin.products.product.plan_help'}} + {{/unless}}
- {{#unless model.plans}} -
- {{i18n 'discourse_patrons.admin.products.product.plan_help'}} - {{/unless}} -
- -

+
+

+{{/unless}}

diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 11802c0..9ea8861 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -73,8 +73,6 @@ en: name: Product Name statement_descriptor: Statement Descriptor statement_descriptor_help: Extra information about a product which will appear on your customer’s credit card statement. - group: User Group - group_help: This is the discourse user group the customer gets added to when the subscription is created. plan_help: Create a pricing plan to subscribe customers to this product active: Active created_at: Created @@ -83,13 +81,14 @@ en: operations: add: Add New Plan create: Create Plan - create_help: Once a pricing plan is created, only its nickname and trial period can be updated. + update: Update Plan + create_help: Once a pricing plan is created, only its nickname, trial period and user group can be updated. new: New Plan destroy: confirm: Are you sure you want to destroy this plan? plan: nickname: Plan Nickname - nickname_help: This won't be visible to customers, but will help you find this plan later. + nickname_help: This won't be visible to customers, but will help you find this plan later plan_id: Plan ID product: Product interval: Billing Interval diff --git a/spec/requests/admin/plans_controller_spec.rb b/spec/requests/admin/plans_controller_spec.rb index 0147066..394c9ab 100644 --- a/spec/requests/admin/plans_controller_spec.rb +++ b/spec/requests/admin/plans_controller_spec.rb @@ -46,9 +46,9 @@ module DiscoursePatrons end end - describe "delete" do - it "does not delete a plan" do - ::Stripe::Plan.expects(:delete).never + describe "update" do + it "does not update a plan" do + ::Stripe::Plan.expects(:update).never delete "/patrons/admin/plans/plan_12345.json" end @@ -57,6 +57,18 @@ module DiscoursePatrons expect(response.status).to eq 403 end end + + describe "delete" do + it "does not delete a plan" do + ::Stripe::Plan.expects(:delete).never + patch "/patrons/admin/plans/plan_12345.json" + end + + it "is not ok" do + patch "/patrons/admin/plans/plan_12345.json" + expect(response.status).to eq 403 + end + end end context 'authenticated' do @@ -114,6 +126,13 @@ module DiscoursePatrons end end + describe "update" do + it "updates a plan" do + ::Stripe::Plan.expects(:update) + patch "/patrons/admin/plans/plan_12345.json", params: { metadata: { group_name: 'discourse-user-group-name' } } + end + end + describe "delete" do it "deletes a plan" do ::Stripe::Plan.expects(:delete).with('plan_12345') diff --git a/spec/requests/admin/products_controller_spec.rb b/spec/requests/admin/products_controller_spec.rb index e776d4b..06ff720 100644 --- a/spec/requests/admin/products_controller_spec.rb +++ b/spec/requests/admin/products_controller_spec.rb @@ -73,6 +73,11 @@ module DiscoursePatrons ::Stripe::Product.expects(:create).with(has_entry(statement_descriptor: 'Blessed are the cheesemakers')) post "/patrons/admin/products.json", params: { statement_descriptor: 'Blessed are the cheesemakers' } end + + it 'has no statement descriptor if empty' do + ::Stripe::Product.expects(:create).with(has_key(:statement_descriptor)).never + post "/patrons/admin/products.json", params: { statement_descriptor: '' } + end end describe 'show' do