mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-01 02:03:22 +00:00
Add basic view allowing customers to authorise shop use of their credit cards
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
angular.module("Darkswarm").controller "AuthorisedShopsCtrl", ($scope, Customers, Shops) ->
|
||||
$scope.customers = Customers.index()
|
||||
$scope.shopsByID = Shops.byID
|
||||
20
app/assets/javascripts/darkswarm/services/customer.js.coffee
Normal file
20
app/assets/javascripts/darkswarm/services/customer.js.coffee
Normal 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
|
||||
@@ -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
|
||||
13
app/assets/javascripts/darkswarm/services/shops.js.coffee
Normal file
13
app/assets/javascripts/darkswarm/services/shops.js.coffee
Normal 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
|
||||
@@ -28,6 +28,12 @@
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.authorised_shops{
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.orders {
|
||||
|
||||
13
app/views/spree/users/_authorised_shops.html.haml
Normal file
13
app/views/spree/users/_authorised_shops.html.haml
Normal 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" } }
|
||||
@@ -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'
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'})
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user