diff --git a/app/assets/javascripts/controllers/admin/members.coffee.erb b/app/assets/javascripts/controllers/admin/members.coffee.erb index 0e8058d2c..008cc7ca8 100644 --- a/app/assets/javascripts/controllers/admin/members.coffee.erb +++ b/app/assets/javascripts/controllers/admin/members.coffee.erb @@ -260,8 +260,8 @@ Application.Controllers.controller "AdminMembersController", ["$scope", 'members ## # Controller used in the member edition page ## -Application.Controllers.controller "EditMemberController", ["$scope", "$state", "$stateParams", "Member", 'Training', 'dialogs', 'growl', 'Group', 'Subscription', 'CSRF', 'memberPromise', 'tagsPromise', '$uibModal', 'Plan', '$filter', '_t', 'walletPromise' -, ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise) -> +Application.Controllers.controller "EditMemberController", ["$scope", "$state", "$stateParams", "Member", 'Training', 'dialogs', 'growl', 'Group', 'Subscription', 'CSRF', 'memberPromise', 'tagsPromise', '$uibModal', 'Plan', '$filter', '_t', 'walletPromise', 'transactionsPromise' +, ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise, transactionsPromise) -> @@ -303,6 +303,9 @@ Application.Controllers.controller "EditMemberController", ["$scope", "$state", ## the user wallet $scope.wallet = walletPromise + ## user wallet transactions + $scope.transactions = transactionsPromise + $scope.view = 'member_edit' diff --git a/app/assets/javascripts/controllers/wallet.coffee b/app/assets/javascripts/controllers/wallet.coffee index 51764efa1..9ab033672 100644 --- a/app/assets/javascripts/controllers/wallet.coffee +++ b/app/assets/javascripts/controllers/wallet.coffee @@ -1,9 +1,12 @@ 'use strict' -Application.Controllers.controller "WalletController", ['$scope', 'walletPromise', ($scope, walletPromise)-> +Application.Controllers.controller "WalletController", ['$scope', 'walletPromise', 'transactionsPromise', ($scope, walletPromise, transactionsPromise)-> ### PUBLIC SCOPE ### ## current user wallet $scope.wallet = walletPromise + + ## current wallet transactions + $scope.transactions = transactionsPromise ] diff --git a/app/assets/javascripts/router.coffee.erb b/app/assets/javascripts/router.coffee.erb index 5c237854f..347c49b68 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -207,6 +207,9 @@ angular.module('application.router', ['ui.router']). walletPromise: ['Wallet', (Wallet)-> Wallet.my().$promise ] + transactionsPromise: ['Wallet', 'walletPromise', (Wallet, walletPromise)-> + Wallet.transactions(id: walletPromise.id).$promise + ] translations: [ 'Translations', (Translations) -> Translations.query(['app.shared.wallet']).$promise ] @@ -875,6 +878,9 @@ angular.module('application.router', ['ui.router']). walletPromise: ['Wallet', '$stateParams', (Wallet, $stateParams)-> Wallet.getWalletByUser(user_id: $stateParams.id).$promise ] + transactionsPromise: ['Wallet', 'walletPromise', (Wallet, walletPromise)-> + Wallet.transactions(id: walletPromise.id).$promise + ] tagsPromise: ['Tag', (Tag)-> Tag.query().$promise ] diff --git a/app/assets/javascripts/services/wallet.coffee b/app/assets/javascripts/services/wallet.coffee index 0e8429d15..e3d5c7380 100644 --- a/app/assets/javascripts/services/wallet.coffee +++ b/app/assets/javascripts/services/wallet.coffee @@ -11,4 +11,8 @@ Application.Services.factory 'Wallet', ["$resource", ($resource)-> method: 'GET' url: '/api/wallet/by_user/:user_id' isArray: false + transactions: + method: 'GET' + url: '/api/wallet/:id/transactions' + isArray: true ] diff --git a/app/assets/stylesheets/app.colors.scss b/app/assets/stylesheets/app.colors.scss index 0b49e3b72..e0c6d7d63 100644 --- a/app/assets/stylesheets/app.colors.scss +++ b/app/assets/stylesheets/app.colors.scss @@ -39,3 +39,4 @@ .text-purple { color: $violet !important; } .text-japonica { color: $japonica !important; } .text-beige { color: $beige !important; } +.text-green, .green { color: #79C84A !important; } diff --git a/app/assets/stylesheets/app.components.scss b/app/assets/stylesheets/app.components.scss index 317ec00fc..e668b9e51 100644 --- a/app/assets/stylesheets/app.components.scss +++ b/app/assets/stylesheets/app.components.scss @@ -514,3 +514,28 @@ padding: 10px; border-radius: 3px; } } + +.wallet-amount-container { + padding: 20px 0; + border-top: 2px dotted $border-color; + border-bottom: 2px dotted $border-color; + margin-bottom: 20px; + text-align: center; + + .wallet-amount { + font-size: rem-calc(40); + font-weight: 700; + font-style: italic; + color: #616161; + + span { + font-weight: 500; + font-size: .7em; + } + + &.cr-green { + color: $green; + } + } +} + diff --git a/app/assets/templates/admin/members/edit.html.erb b/app/assets/templates/admin/members/edit.html.erb index b9cb70da2..ed5368a2e 100644 --- a/app/assets/templates/admin/members/edit.html.erb +++ b/app/assets/templates/admin/members/edit.html.erb @@ -220,6 +220,10 @@
+ +
+ +
diff --git a/app/assets/templates/dashboard/wallet.html.erb b/app/assets/templates/dashboard/wallet.html.erb index 0fef50380..175504c64 100644 --- a/app/assets/templates/dashboard/wallet.html.erb +++ b/app/assets/templates/dashboard/wallet.html.erb @@ -12,5 +12,10 @@
+ +
+ +
+ diff --git a/app/assets/templates/wallet/transactions.html.erb b/app/assets/templates/wallet/transactions.html.erb new file mode 100644 index 000000000..17130b013 --- /dev/null +++ b/app/assets/templates/wallet/transactions.html.erb @@ -0,0 +1,27 @@ +
+ + + + + + + + + + + + + + + + + +
{{ 'date' }}{{ 'operation' }}{{ 'operator' }}{{ 'amount' }}
{{ t.created_at | amDateFormat:'L' }} + {{ 'credit' }} + {{ t.user.full_name }} + + + - + {{ t.amount | currency }} +
+

{{ 'no_transactions_for_now' }}

+
diff --git a/app/controllers/api/wallet_controller.rb b/app/controllers/api/wallet_controller.rb index 1378b3c12..697279bd8 100644 --- a/app/controllers/api/wallet_controller.rb +++ b/app/controllers/api/wallet_controller.rb @@ -11,4 +11,10 @@ class API::WalletController < API::ApiController @wallet = Wallet.find_by(user_id: params[:user_id]) render :show end + + def transactions + @wallet = Wallet.find(params[:id]) + authorize @wallet + @wallet_transactions = @wallet.wallet_transactions.includes(:transactable, user: [:profile]).order(created_at: :desc) + end end diff --git a/app/policies/wallet_policy.rb b/app/policies/wallet_policy.rb index 24d7cdd30..b3f849b11 100644 --- a/app/policies/wallet_policy.rb +++ b/app/policies/wallet_policy.rb @@ -2,4 +2,8 @@ class WalletPolicy < ApplicationPolicy def by_user? user.is_admin? end + + def transactions? + user.is_admin? or user == record.user + end end diff --git a/app/services/wallet_service.rb b/app/services/wallet_service.rb new file mode 100644 index 000000000..62e657c98 --- /dev/null +++ b/app/services/wallet_service.rb @@ -0,0 +1,13 @@ +class WalletService + def initialize(user: nil, wallet: nil) + @user = user + @wallet = wallet + end + + def credit(amount) + if @wallet.credit(amount) + WalletTransaction.create(user: @user, wallet: @wallet, transaction_type: 'credit', amount: amount) + return true + end + end +end diff --git a/app/views/api/wallet/show.json.jbuilder b/app/views/api/wallet/show.json.jbuilder index a96e1213b..ef0b12454 100644 --- a/app/views/api/wallet/show.json.jbuilder +++ b/app/views/api/wallet/show.json.jbuilder @@ -1,2 +1 @@ -json.user_id @wallet.user_id -json.amount amount_to_f(@wallet.amount) +json.extract! @wallet, :id, :user_id, :amount diff --git a/app/views/api/wallet/transactions.json.jbuilder b/app/views/api/wallet/transactions.json.jbuilder new file mode 100644 index 000000000..d588705c4 --- /dev/null +++ b/app/views/api/wallet/transactions.json.jbuilder @@ -0,0 +1,7 @@ +json.array!(@wallet_transactions) do |t| + json.extract! t, :id, :transaction_type, :created_at, :amount + json.user do + json.id t.user.id + json.full_name t.user.profile.full_name + end +end diff --git a/config/locales/app.shared.en.yml b/config/locales/app.shared.en.yml index d0b293f84..7c655ba36 100644 --- a/config/locales/app.shared.en.yml +++ b/config/locales/app.shared.en.yml @@ -300,3 +300,8 @@ en: wallet: 'Wallet' your_wallet_amount: 'Your amount available' wallet_amount: 'Amount available' + no_transactions_for_now: 'No transactions for now' + operation: 'Operation' + operator: 'Operator' + amount: 'Amount' + credit: 'Crédit' diff --git a/config/locales/app.shared.fr.yml b/config/locales/app.shared.fr.yml index d0a46fd7f..7215c8599 100644 --- a/config/locales/app.shared.fr.yml +++ b/config/locales/app.shared.fr.yml @@ -300,3 +300,8 @@ fr: wallet: 'Porte-monnaie' your_wallet_amount: 'Votre montant disponible' wallet_amount: 'Montant disponible' + no_transactions_for_now: 'Aucune transaction pour le moment' + operation: 'Opération' + operator: 'Opérateur' + amount: 'Montant' + credit: 'Crédit' diff --git a/config/routes.rb b/config/routes.rb index 94258cf40..02d730d0a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -51,6 +51,7 @@ Rails.application.routes.draw do resources :wallet do get :my, on: :collection get '/by_user/:user_id', action: 'by_user', on: :collection + get :transactions, on: :member end # for homepage diff --git a/test/fixtures/wallet_transactions.yml b/test/fixtures/wallet_transactions.yml index 8fef445f6..9edb192b1 100644 --- a/test/fixtures/wallet_transactions.yml +++ b/test/fixtures/wallet_transactions.yml @@ -1,13 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - user_id: - wallet_id: - transaction_type: MyString - amount: 1 - -two: - user_id: - wallet_id: - transaction_type: MyString - amount: 1 +transaction1: + user_id: 4 + wallet: wallet_4 + transaction_type: credit + amount: 1000 diff --git a/test/fixtures/wallets.yml b/test/fixtures/wallets.yml index a5dbec1d4..e86e3a29f 100644 --- a/test/fixtures/wallets.yml +++ b/test/fixtures/wallets.yml @@ -4,7 +4,7 @@ wallet_2: wallet_4: user_id: 4 - amount: 0 + amount: 1000 wallet_6: user_id: 6 diff --git a/test/integration/wallets_test.rb b/test/integration/wallets_test.rb index fb9ce9d25..be1035b96 100644 --- a/test/integration/wallets_test.rb +++ b/test/integration/wallets_test.rb @@ -3,8 +3,8 @@ class WalletsTest < ActionDispatch::IntegrationTest # Called before every test method runs. Can be used # to set up fixture information. def setup - @jdupond = User.find_by_username('jdupond') - login_as(@jdupond, scope: :user) + @kdumas = User.find_by(username: 'kdumas') + login_as(@kdumas, scope: :user) end # Called after every test method runs. Can be used to tear @@ -19,8 +19,8 @@ class WalletsTest < ActionDispatch::IntegrationTest assert_equal 200, response.status assert_equal Mime::JSON, response.content_type wallet = json_response(response.body) - assert_equal @jdupond.wallet.user_id, wallet[:user_id] - assert_equal @jdupond.wallet.amount, wallet[:amount] + assert_equal @kdumas.wallet.user_id, wallet[:user_id] + assert_equal @kdumas.wallet.amount, wallet[:amount] end test 'admin can get wallet by user id' do @@ -35,9 +35,25 @@ class WalletsTest < ActionDispatch::IntegrationTest assert_equal @user1.wallet.amount, wallet[:amount] end - test 'cant get wallet of user if not admin' do - @user1 = User.first - get "/api/wallet/by_user/#{@user1.id}" + test 'cant get wallet of an user if not admin' do + user5 = users(:user_5) + get "/api/wallet/by_user/#{user5.id}" + assert_equal 403, response.status + end + + test 'get all transactions of wallet' do + w = @kdumas.wallet + get "/api/wallet/#{w.id}/transactions" + assert_equal 200, response.status + assert_equal Mime::JSON, response.content_type + transactions = json_response(response.body) + assert_equal w.wallet_transactions.count, transactions.size + assert_equal wallet_transactions(:transaction1).id, transactions.first[:id] + end + + test 'only admin and wallet owner can show their transactions' do + user5 = users(:user_5) + get "/api/wallet/#{user5.wallet.id}/transactions" assert_equal 403, response.status end end diff --git a/test/models/wallet_test.rb b/test/models/wallet_test.rb index c557d58a7..537ae6bdf 100644 --- a/test/models/wallet_test.rb +++ b/test/models/wallet_test.rb @@ -21,7 +21,7 @@ class WalletTest < ActiveSupport::TestCase test 'can debit amount' do w = Wallet.first w.credit(5) - expected_amount = 0 + expected_amount = w.amount - 5 assert w.debit(5) assert_equal w.amount, expected_amount end diff --git a/test/services/wallet_service_test.rb b/test/services/wallet_service_test.rb new file mode 100644 index 000000000..46536423f --- /dev/null +++ b/test/services/wallet_service_test.rb @@ -0,0 +1,27 @@ +require 'test_helper' + +class WalletServiceTest < ActiveSupport::TestCase + setup do + @admin = User.find_by(username: 'admin') + @user = User.find_by(username: 'jdupond') + @wallet = @user.wallet + end + + test 'admin can credit a wallet' do + service = WalletService.new(user: @admin, wallet: @wallet) + expected_amount = @wallet.amount + 5 + assert service.credit(5) + assert_equal @wallet.amount, expected_amount + end + + test 'create a credit transaction after credit amount to wallet' do + service = WalletService.new(user: @admin, wallet: @wallet) + assert_equal 0, @wallet.wallet_transactions.count + assert service.credit(10) + transaction = @wallet.wallet_transactions.first + assert_equal transaction.transaction_type, 'credit' + assert_equal transaction.amount, 10 + assert_equal transaction.user, @admin + assert_equal transaction.wallet, @wallet + end +end