Skip to content
This repository has been archived by the owner on Apr 7, 2021. It is now read-only.

Commit

Permalink
Merge pull request #214 from thebristolcable/wpf-admin-sub-controls
Browse files Browse the repository at this point in the history
Add admin update subscription controls
  • Loading branch information
wpf500 authored Oct 23, 2020
2 parents 9065db8 + bfea94c commit d2cab81
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 58 deletions.
22 changes: 14 additions & 8 deletions apps/members/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const { hasModel, hasSchema } = require( __js + '/middleware' );
const Options = require( __js + '/options' )();
const { cleanEmailAddress, wrapAsync } = require( __js + '/utils' );

const { isValidCustomer, createMember, customerToMember, startMembership } = require( __apps + '/join/utils' );
const { isValidCustomer, createMember, customerToMember } = require( __apps + '/join/utils' );
const { calcSubscriptionMonthsLeft, canChangeSubscription, handleUpdateSubscription } = require( __apps + '/profile/apps/direct-debit/utils' );
const { syncMemberDetails } = require( __apps + '/profile/apps/account/utils' );
const exportTypes = require( __apps + '/tools/apps/exports/exports');

Expand Down Expand Up @@ -367,18 +368,23 @@ memberAdminRouter.post( '/exports', wrapAsync( async ( req, res ) => {
res.redirect( req.baseUrl + '/exports' );
} ) );

memberAdminRouter.get( '/gocardless', ( req, res ) => {
res.render( 'gocardless', { member: req.model } );
} );
memberAdminRouter.get( '/gocardless', wrapAsync( async ( req, res ) => {
res.render( 'gocardless', {
member: req.model,
canChange: await canChangeSubscription( req.model, req.model.canTakePayment ),
monthsLeft: calcSubscriptionMonthsLeft( req.model )
} );
} ) );

memberAdminRouter.post( '/gocardless', wrapAsync( async ( req, res ) => {
const member = req.model;

switch ( req.body.action ) {
case 'create-subscription':
await startMembership(member, {
case 'update-subscription':
await handleUpdateSubscription(req, member, {
amount: Number(req.body.amount),
period: req.body.period,
prorate: req.body.prorate === 'true',
payFee: req.body.payFee === 'true'
});
break;
Expand All @@ -390,12 +396,12 @@ memberAdminRouter.post( '/gocardless', wrapAsync( async ( req, res ) => {
'gocardless.subscription_id': req.body.subscription_id,
'gocardless.amount': Number(req.body.amount),
'gocardless.period': req.body.period,
'gocardless.paying_fee': req.body.paying_fee
'gocardless.paying_fee': req.body.payFee === 'true'
} });
req.flash( 'success', 'gocardless-updated' );
break;
}

req.flash( 'success', 'gocardless-updated' );
res.redirect( req.baseUrl + '/gocardless' );
} ) );

Expand Down
1 change: 1 addition & 0 deletions apps/members/views/emails.pug
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ block contents
select(name='email' id='email' required).form-control
option(value='' selected disabled) Select email
option(value='welcome') Welcome email
option(value='welcome-post-gift') Post gift welcome email
+form_button('Send email', 'primary', {left: 3})

74 changes: 46 additions & 28 deletions apps/members/views/gocardless.pug
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,63 @@ block prepend title
- title = 'GoCardless'
- page = 'gocardless'

mixin commonSubscriptionFields(idPrefix, periodReadOnly)
+input( 'number', 'Monthly amount', 'amount', {
left: 3, right: 4, before: '£',
value: member.contributionMonthlyAmount,
id: idPrefix + 'Amount'
})
if periodReadOnly
.form-group
label.col-md-3.control-label Period
.col-md-4.form-control-static= member.contributionPeriod
else
+input( 'radio', 'Period', 'period', {
left: 3, right: 4,
options: {'monthly': 'Monthly', 'annually': 'Annually'},
value: member.contributionPeriod,
id: idPrefix + 'Period'
})
+input( 'checkbox', 'Paying fee', 'payFee', {
left: 3, right: 4,
options: {'true': 'Yes'},
value: member.gocardless.paying_fee,
id: idPrefix + 'PayFee'
})

block contents
.row
.col-md-3
include partials/sidebar.pug
.col-md-9
+page_header( title )

h4 Create subscription
if member.hasActiveSubscription
p User has a subscription
else if !member.canTakePayment
p User does not have an active payment method
h4= member.hasActiveSubscription ? 'Update contribution' : 'Start contribution'
if !member.canTakePayment
.alert.alert-warning User does not have an active payment method
else if !canChange
.alert.alert-warning Can't change contribution at the moment, probably due to pending payments
else
form( method="post").form-horizontal
+csrf
input( type='hidden' name='action' value='create-subscription' )
+input( 'number', 'Monthly amount', 'amount', { left: 3, right: 4, before: '£' })
+input( 'radio', 'Period', 'period', {
left: 3, right: 4,
options: {'monthly': 'Monthly', 'annually': 'Annually'}
})
+input( 'checkbox', 'Paying fee', 'payFee', {
left: 3, right: 4,
options: {'true': 'Yes'}
})
+form_button( 'Create', 'primary', { left: 3 } )
input( type='hidden' name='action' value='update-subscription' )
+commonSubscriptionFields('update', member.hasActiveSubscription)

if monthsLeft > 0
.form-group
label(for='prorate').col-md-3.control-label Prorate
.col-md-9
.checkbox
label
input(type='checkbox' value='true')#prorate
| Yes
|
small (#{monthsLeft} months left until next payment)

+form_button( member.hasActiveSubscription ? 'Update' : 'Start', 'success', { left: 3 } )

h4 Manual update
.alert.alert-warning.
.alert.alert-danger.
If done incorrectly this could result in payments being taken but not
recorded
form( method="post" ).form-horizontal
Expand All @@ -41,15 +69,5 @@ block contents
+input( 'text', 'Customer ID', 'customer_id', { value: member.gocardless.customer_id, left: 3, right: 4 } )
+input( 'text', 'Mandate ID', 'mandate_id', { value: member.gocardless.mandate_id, left: 3, right: 4 } )
+input( 'text', 'Subscription ID', 'subscription_id', { value: member.gocardless.subscription_id, left: 3, right: 4 } )
+input( 'number', 'Monthly amount', 'amount', { value: member.gocardless.amount, left: 3, right: 4, before: '£' } )
+input( 'radio', 'Period', 'period', {
value: member.gocardless.period,
left: 3, right: 4,
options: {'monthly': 'Monthly', 'annually': 'Annually'}
})
+input( 'checkbox', 'Paying fee', 'paying_fee', {
value: member.gocardless.paying_fee,
left: 3, right: 4,
options: {'true': 'Yes'}
} )
+commonSubscriptionFields('force', false)
+form_button( 'Update', 'danger', { left: 3 } )
15 changes: 2 additions & 13 deletions apps/profile/apps/direct-debit/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const config = require( __config );
const { createJoinFlow, completeJoinFlow } = require( __apps + '/join/utils' );

const { cancelSubscriptionSchema, completeFlowSchema, updateSubscriptionSchema } = require('./schemas.json');
const { calcSubscriptionMonthsLeft, canChangeSubscription, getBankAccount, processUpdateSubscription } = require('./utils');
const { calcSubscriptionMonthsLeft, canChangeSubscription, getBankAccount, handleUpdateSubscription } = require('./utils');

const app = express();
var app_config = {};
Expand Down Expand Up @@ -57,17 +57,6 @@ app.get( '/', wrapAsync( async function ( req, res ) {
} );
} ) );

async function handleUpdateSubscription(req, user, form) {
const wasGift = user.contributionPeriod === 'gift';
await processUpdateSubscription(user, form);
if (wasGift) {
await mandrill.sendToMember('welcome-post-gift', user);
req.flash( 'success', 'contribution-gift-updated' );
} else {
req.flash( 'success', 'contribution-updated' );
}
}

app.post( '/', [
hasSchema(updateSubscriptionSchema).orFlash
], wrapAsync( async ( req, res ) => {
Expand All @@ -82,7 +71,7 @@ app.post( '/', [
updateForm
}
} );
if ( useMandate && user.canTakePayment ) {
if ( useMandate ) {
await handleUpdateSubscription(req, user, updateForm);
res.redirect( app.parent.mountpath + app.mountpath );
} else {
Expand Down
24 changes: 18 additions & 6 deletions apps/profile/apps/direct-debit/utils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const moment = require('moment');

const gocardless = require( __js + '/gocardless' );
const { Payments } = require( __js + '/database' );

const gocardless = require( __js + '/gocardless' );
const log = require( __js + '/logging' ).log;
const mandrill = require( __js + '/mandrill' );
const { getChargeableAmount } = require( __js + '/utils' );
const { createSubscription, startMembership } = require( __apps + '/join/utils' );

Expand Down Expand Up @@ -48,10 +48,10 @@ async function getBankAccount(user) {
return await gocardless.customerBankAccounts.get(mandate.links.customer_bank_account);
} catch (err) {
// 404s can happen on dev as we don't use real mandate IDs
if (!config.dev || !err.response || err.response.status !== 404) {
throw err;
if (config.dev && err.response && err.response.status === 404) {
return null;
}
return null;
throw err;
}
} else {
return null;
Expand Down Expand Up @@ -152,9 +152,21 @@ async function processUpdateSubscription(user, {amount, period, prorate, payFee}
}
}

async function handleUpdateSubscription(req, user, form) {
const wasGift = user.contributionPeriod === 'gift';
await processUpdateSubscription(user, form);
if (wasGift) {
await mandrill.sendToMember('welcome-post-gift', user);
req.flash( 'success', 'contribution-gift-updated' );
} else {
req.flash( 'success', 'contribution-updated' );
}
}

module.exports = {
calcSubscriptionMonthsLeft,
canChangeSubscription,
getBankAccount,
processUpdateSubscription
processUpdateSubscription,
handleUpdateSubscription
};
6 changes: 3 additions & 3 deletions src/views/mixins.pug
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mixin input( type, label, name, opts )
unless opts.id
- opts.id = name
.form-group
label( for=name, class=( opts.left ? 'col-md-' + opts.left : 'col-md-2' ) ).control-label #{ label }
label( for=opts.id, class=( opts.left ? 'col-md-' + opts.left : 'col-md-2' ) ).control-label #{ label }
div( class=( opts.right ? 'col-md-' + opts.right : 'col-md-3' ) )
div( class=( opts.before || opts.after ? 'input-group' : null ) )
if opts.before
Expand All @@ -29,8 +29,8 @@ mixin input( type, label, name, opts )
for text, value in opts.options
- i++
div( class=type )
label( for=name + "_" + i )
input( name=name, type=type, value=value, required=opts.required, checked=( opts.value === true || value == opts.value ), id=name + "_" + i )
label( for=opts.id + "_" + i )
input( name=name, type=type, value=value, required=opts.required, checked=( opts.value === true || value == opts.value ), id=opts.id + "_" + i )
| #{ text }
- break
if opts.after
Expand Down

0 comments on commit d2cab81

Please sign in to comment.