Add basic view allowing customers to authorise shop use of their credit cards

This commit is contained in:
Rob Harrington
2018-04-27 17:42:34 +10:00
parent ffa8a8c7d6
commit 6457a17fde
12 changed files with 181 additions and 4 deletions

View File

@@ -0,0 +1,3 @@
angular.module("Darkswarm").controller "AuthorisedShopsCtrl", ($scope, Customers, Shops) ->
$scope.customers = Customers.index()
$scope.shopsByID = Shops.byID

View File

@@ -0,0 +1,20 @@
angular.module("Darkswarm").factory 'Customer', ($resource, RailsFlashLoader) ->
Customer = $resource('/api/customers/:id/:action.json', {}, {
'index':
method: 'GET'
isArray: true
'update':
method: 'PUT'
params:
id: '@id'
transformRequest: (data, headersGetter) ->
angular.toJson(customer: data)
})
Customer.prototype.update = ->
@$update().then (response) =>
RailsFlashLoader.loadFlash({success: t('js.changes_saved')})
, (response) =>
RailsFlashLoader.loadFlash({error: response.data.error})
Customer

View File

@@ -0,0 +1,13 @@
angular.module("Darkswarm").factory 'Customers', (Customer) ->
new class Customers
all: []
byID: {}
index: (params={}) ->
Customer.index params, (data) => @load(data)
@all
load: (customers) ->
for customer in customers
@all.push customer
@byID[customer.id] = customer

View File

@@ -0,0 +1,13 @@
angular.module("Darkswarm").factory 'Shops', ($injector) ->
new class Shops
all: []
byID: {}
constructor: ->
if $injector.has('shops')
@load($injector.get('shops'))
load: (shops) ->
for shop in shops
@all.push shop
@byID[shop.id] = shop

View File

@@ -28,6 +28,12 @@
margin-bottom: 0px;
}
}
.authorised_shops{
table {
width: 100%;
}
}
}
.orders {

View File

@@ -0,0 +1,13 @@
%table
%tr
%th= t(:shop_title)
%th= t(:allow_charges?)
%tr.customer{ id: "customer{{ customer.id }}", ng: { repeat: "customer in customers" } }
%td.shop{ ng: { bind: 'shopsByID[customer.enterprise_id].name' } }
%td.allow_charges
%input{ type: 'checkbox',
name: 'allow_charges',
ng: { model: 'customer.allow_charges',
change: 'customer.update()',
"true-value" => "true",
"false-value" => "false" } }

View File

@@ -10,6 +10,13 @@
%button.button.primary{ ng: { click: 'showForm()', hide: 'CreditCard.visible' } }
= t(:add_a_card)
.small-12.medium-6.columns.new_card{ ng: { show: 'CreditCard.visible', class: '{visible: CreditCard.visible}' } }
%h3= t(:add_a_new_card)
= render 'new_card_form'
.small-12.medium-6.columns
.new_card{ ng: { show: 'CreditCard.visible', class: '{visible: CreditCard.visible}' } }
%h3= t(:add_a_new_card)
= render 'new_card_form'
.authorised_shops{ ng: { controller: 'AuthorisedShopsCtrl', hide: 'CreditCard.visible' } }
%h3
= t('.authorised_shops')
%button.button.secondary.tiny.help-btn.ng-scope{ :popover => t('.authorised_shops_popover'), "popover-placement" => 'right' }
%i.ofn-i_013-help
= render 'authorised_shops'

View File

@@ -2740,5 +2740,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using
saved_cards:
default?: Default?
delete?: Delete?
cards:
authorised_shops: Authorised Shops
authorised_shops_popover: This is a list of shops which are permitted to charge your default credit card for OFN services (eg. subscriptions). Your card details will be kept secure and will not be shared with shop owners.
localized_number:
invalid_format: has an invalid format. Please enter a number.

View File

@@ -4,6 +4,7 @@ feature "Credit Cards", js: true do
include AuthenticationWorkflow
describe "as a logged in user" do
let(:user) { create(:user) }
let!(:customer) { create(:customer, user: user) }
let!(:default_card) { create(:credit_card, user_id: user.id, gateway_customer_profile_id: 'cus_AZNMJ', is_default: true) }
let!(:non_default_card) { create(:credit_card, user_id: user.id, gateway_customer_profile_id: 'cus_FDTG') }
@@ -49,10 +50,10 @@ feature "Credit Cards", js: true do
expect(page).to have_content I18n.t('js.default_card_updated')
expect(default_card.reload.is_default).to be false
within(".card#card#{default_card.id}") do
expect(find_field('default_card')).to_not be_checked
end
expect(default_card.reload.is_default).to be false
expect(non_default_card.reload.is_default).to be true
# Shows the interface for adding a card
@@ -67,6 +68,14 @@ feature "Credit Cards", js: true do
expect(page).to have_content I18n.t(:card_has_been_removed, number: "x-#{default_card.last_digits}")
expect(page).to_not have_selector ".card#card#{default_card.id}"
# Allows authorisation of card use by shops
within "tr#customer#{customer.id}" do
expect(find_field('allow_charges')).to_not be_checked
find_field('allow_charges').click
end
expect(page).to have_content I18n.t('js.changes_saved')
expect(customer.reload.allow_charges).to be true
end
end
end

View File

@@ -0,0 +1,39 @@
describe 'Customer', ->
describe "update", ->
$httpBackend = null
customer = null
response = { id: 3, code: '1234' }
RailsFlashLoaderMock = jasmine.createSpyObj('RailsFlashLoader', ['loadFlash'])
beforeEach ->
module 'Darkswarm'
module ($provide) ->
$provide.value 'RailsFlashLoader', RailsFlashLoaderMock
null
inject (_$httpBackend_, Customer)->
customer = new Customer(id: 3)
$httpBackend = _$httpBackend_
it "nests the params inside 'customer'", ->
$httpBackend
.expectPUT('/api/customers/3.json', { customer: { id: 3 } })
.respond 200, response
customer.update()
$httpBackend.flush()
describe "when the request succeeds", ->
it "shows a success flash", ->
$httpBackend.expectPUT('/api/customers/3.json').respond 200, response
customer.update()
$httpBackend.flush()
expect(RailsFlashLoaderMock.loadFlash)
.toHaveBeenCalledWith({success: jasmine.any(String)})
describe "when the request fails", ->
it "shows a error flash", ->
$httpBackend.expectPUT('/api/customers/3.json').respond 400, { error: 'Some error' }
customer.update()
$httpBackend.flush()
expect(RailsFlashLoaderMock.loadFlash)
.toHaveBeenCalledWith({error: 'Some error'})

View File

@@ -0,0 +1,24 @@
describe 'Customers', ->
describe "index", ->
$httpBackend = null
Customers = null
customerList = ['somecustomer']
beforeEach ->
module 'Darkswarm'
module ($provide) ->
$provide.value 'RailsFlashLoader', null
null
inject (_$httpBackend_, _Customers_)->
Customers = _Customers_
$httpBackend = _$httpBackend_
it "asks for customers and returns @all, promises to populate via @load", ->
spyOn(Customers,'load').and.callThrough()
$httpBackend.expectGET('/api/customers.json').respond 200, customerList
result = Customers.index()
$httpBackend.flush()
expect(Customers.load).toHaveBeenCalled()
expect(result).toEqual customerList
expect(Customers.all).toEqual customerList

View File

@@ -0,0 +1,27 @@
describe 'Shops', ->
describe "initialisation", ->
Shops = null
shops = ['some shop']
beforeEach ->
module 'Darkswarm'
describe "when the injector does not have a value for 'shops'", ->
beforeEach ->
inject (_Shops_) ->
Shops = _Shops_
it "does nothing, leaves @all empty", ->
expect(Shops.all).toEqual []
describe "when the injector has a value for 'shops'", ->
beforeEach ->
module ($provide) ->
$provide.value 'shops', shops
null
inject (_Shops_) ->
Shops = _Shops_
it "loads injected shops array into @all", ->
expect(Shops.all).toEqual shops