1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-19 13:54:25 +01:00

application can show user wallet

This commit is contained in:
Peng DU 2016-07-18 18:16:54 +02:00
parent 83ed46a4d8
commit db8a6e8a32
26 changed files with 258 additions and 12 deletions

View File

@ -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'
, ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t) ->
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) ->
@ -300,6 +300,10 @@ Application.Controllers.controller "EditMemberController", ["$scope", "$state",
## Profiles types (student/standard/...)
$scope.groups = []
## the user wallet
$scope.wallet = walletPromise
$scope.view = 'member_edit'
##

View File

@ -0,0 +1,9 @@
'use strict'
Application.Controllers.controller "WalletController", ['$scope', 'walletPromise', ($scope, walletPromise)->
### PUBLIC SCOPE ###
## current user wallet
$scope.wallet = walletPromise
]

View File

@ -197,6 +197,19 @@ angular.module('application.router', ['ui.router']).
translations: [ 'Translations', (Translations) ->
Translations.query('app.logged.dashboard.invoices').$promise
]
.state 'app.logged.dashboard.wallet',
url: '/wallet'
views:
'main@':
templateUrl: '<%= asset_path "dashboard/wallet.html" %>'
controller: 'WalletController'
resolve:
walletPromise: ['Wallet', (Wallet)->
Wallet.my().$promise
]
translations: [ 'Translations', (Translations) ->
Translations.query(['app.shared.wallet']).$promise
]
# members
@ -859,11 +872,14 @@ angular.module('application.router', ['ui.router']).
memberPromise: ['Member', '$stateParams', (Member, $stateParams)->
Member.get(id: $stateParams.id).$promise
]
walletPromise: ['Wallet', '$stateParams', (Wallet, $stateParams)->
Wallet.getWalletByUser(user_id: $stateParams.id).$promise
]
tagsPromise: ['Tag', (Tag)->
Tag.query().$promise
]
translations: [ 'Translations', (Translations) ->
Translations.query(['app.admin.members_edit', 'app.shared.user', 'app.shared.user_admin']).$promise
Translations.query(['app.admin.members_edit', 'app.shared.user', 'app.shared.user_admin', 'app.shared.wallet']).$promise
]
.state 'app.admin.admins_new',
url: '/admin/admins/new'

View File

@ -0,0 +1,14 @@
'use strict'
Application.Services.factory 'Wallet', ["$resource", ($resource)->
$resource "/api/wallet",
{},
my:
method: 'GET'
url: '/api/wallet/my'
isArray: false
getWalletByUser:
method: 'GET'
url: '/api/wallet/by_user/:user_id'
isArray: false
]

View File

@ -215,6 +215,12 @@
</div>
</uib-tab>
<uib-tab heading="{{ 'wallet' | translate }}">
<div class="col-md-12 m m-t-lg">
<ng-include src="'<%= asset_path 'wallet/show.html' %>'"></ng-include>
</div>
</uib-tab>
</uib-tabset>
</div>

View File

@ -8,15 +8,16 @@
</div>
<div class="col-xs-10 col-sm-10 col-md-10 b-l">
<section class="heading-title m-l">
<h4 class="m-l text-sm" translate>{{ 'dashboard' }}</h4>
<ul class="nav-page nav nav-pills text-u-c text-sm">
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.profile" translate>{{ 'my_profile' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.settings" translate>{{ 'my_settings' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.projects" translate>{{ 'my_projects' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.trainings" translate>{{ 'my_trainings' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'my_events' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.invoices" translate>{{ 'my_invoices' }}</a></li>
</ul>
<h4 class="m-l text-sm" translate>{{ 'dashboard' }}</h4>
<ul class="nav-page nav nav-pills text-u-c text-sm">
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.profile" translate>{{ 'my_profile' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.settings" translate>{{ 'my_settings' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.projects" translate>{{ 'my_projects' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.trainings" translate>{{ 'my_trainings' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'my_courses_and_workshops' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.invoices" translate>{{ 'my_invoices' }}</a></li>
<li ui-sref-active="active"><a class="text-black" href="#" ui-sref="app.logged.dashboard.wallet" translate>{{ 'my_wallet' }}</a></li>
</ul>
</section>
</div>
</div>

View File

@ -0,0 +1,16 @@
<div>
<section class="heading">
<div class="row no-gutter">
<ng-include src="'<%= asset_path 'dashboard/nav.html' %>'"></ng-include>
</div>
</section>
<div class="row no-gutter">
<div class="col-md-12 m m-t-lg">
<ng-include src="'<%= asset_path 'wallet/show.html' %>'"></ng-include>
</div>
</div>
</div>

View File

@ -40,6 +40,7 @@
<li><a href="#" ui-sref="app.logged.dashboard.trainings" translate>{{ 'my_trainings' }}</a></li>
<li><a href="#" ui-sref="app.logged.dashboard.events" translate>{{ 'my_events' }}</a></li>
<li><a href="#" ui-sref="app.logged.dashboard.invoices" translate>{{ 'my_invoices' }}</a></li>
<li><a href="#" ui-sref="app.logged.dashboard.wallet" translate>{{ 'my_wallet' }}</a></li>
<li class="divider"></li>
<li><a href="#" class="text-black" ng-click="logout($event)"><i class="fa fa-power-off"></i> {{ 'sign_out' | translate }}</a></li>

View File

@ -0,0 +1,7 @@
<div class="col-sm-4 text-center">
<h4 translate ng-if="view !== 'member_edit'">{{'your_wallet_amount'}}</h4>
<h4 translate ng-if="view === 'member_edit'">{{'wallet_amount'}}</h4>
<div class="wallet-amount-container">
<div class="wallet-amount">{{wallet.amount | currency}}</div>
</div>
</div>

View File

@ -0,0 +1,14 @@
class API::WalletController < API::ApiController
before_action :authenticate_user!
def my
@wallet = current_user.wallet
render :show
end
def by_user
authorize Wallet
@wallet = Wallet.find_by(user_id: params[:user_id])
render :show
end
end

View File

@ -52,6 +52,10 @@ module ApplicationHelper
if (bool) then return :true else return :false end
end
def amount_to_f(amount)
amount / 100.00
end
private
## inspired by gems/actionview-4.2.5/lib/action_view/helpers/translation_helper.rb

View File

@ -45,12 +45,15 @@ class User < ActiveRecord::Base
has_many :tags, through: :user_tags
accepts_nested_attributes_for :tags, allow_destroy: true
has_one :wallet, dependent: :destroy
# fix for create admin user
before_save do
self.email.downcase! if self.email
end
before_create :assign_default_role
after_create :create_a_wallet
after_commit :create_stripe_customer, on: [:create]
after_commit :notify_admin_when_user_is_created, on: :create
after_update :notify_admin_invoicing_changed, if: :invoicing_disabled_changed?
@ -333,6 +336,10 @@ class User < ActiveRecord::Base
StripeWorker.perform_async(:create_stripe_customer, id)
end
def create_a_wallet
self.create_wallet
end
def notify_admin_when_user_is_created
if need_completion? and not provider.nil?
NotificationCenter.call type: 'notify_admin_when_user_is_imported',

4
app/models/wallet.rb Normal file
View File

@ -0,0 +1,4 @@
class Wallet < ActiveRecord::Base
belongs_to :user
validates :user, presence: true
end

View File

@ -0,0 +1,5 @@
class WalletPolicy < ApplicationPolicy
def by_user?
user.is_admin?
end
end

View File

@ -0,0 +1,2 @@
json.user_id @wallet.user_id
json.amount amount_to_f(@wallet.amount)

View File

@ -14,6 +14,7 @@ en:
my_trainings: "My Trainings"
my_events: "My Events"
my_invoices: "My Invoices"
my_wallet: "My Wallet"
# login/logout
sign_out: "Sign Out"

View File

@ -14,6 +14,7 @@ fr:
my_trainings: "Mes formations"
my_events: "Mes évènements"
my_invoices: "Mes factures"
my_wallet: "Mon porte-monnaie"
# connexion / déconnexion
sign_out: "Se déconnecter"

View File

@ -295,3 +295,8 @@ en:
author: "Author"
collaborator: "Collaborator"
private_profile: "Private profile"
wallet:
wallet: 'Wallet'
your_wallet_amount: 'Your amount available'
wallet_amount: 'Amount available'

View File

@ -295,3 +295,8 @@ fr:
author: "Auteur"
collaborator: "Collaborateur"
private_profile: "Profil privé"
wallet:
wallet: 'Porte-monnaie'
your_wallet_amount: 'Votre montant disponible'
wallet_amount: 'Montant disponible'

View File

@ -48,6 +48,10 @@ Rails.application.routes.draw do
resources :notifications, only: [:index, :show, :update] do
match :update_all, path: '/', via: [:put, :patch], on: :collection
end
resources :wallet do
get :my, on: :collection
get '/by_user/:user_id', action: 'by_user', on: :collection
end
# for homepage
get '/last_subscribed/:last' => "members#last_subscribed"

View File

@ -0,0 +1,18 @@
class CreateWallets < ActiveRecord::Migration
def up
create_table :wallets do |t|
t.belongs_to :user, index: true, foreign_key: true
t.integer :amount, default: 0
t.timestamps null: false
end
User.all.each do |u|
Wallet.create(user: u)
end
end
def down
drop_table :wallets
end
end

View File

@ -708,6 +708,15 @@ ActiveRecord::Schema.define(version: 20160714095018) do
add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id", using: :btree
create_table "wallets", force: :cascade do |t|
t.integer "user_id"
t.integer "amount", default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "wallets", ["user_id"], name: "index_wallets_on_user_id", using: :btree
add_foreign_key "availability_tags", "availabilities"
add_foreign_key "availability_tags", "tags"
add_foreign_key "events_event_themes", "event_themes"
@ -718,4 +727,5 @@ ActiveRecord::Schema.define(version: 20160714095018) do
add_foreign_key "prices", "plans"
add_foreign_key "user_tags", "tags"
add_foreign_key "user_tags", "users"
add_foreign_key "wallets", "users"
end

27
test/fixtures/wallets.yml vendored Normal file
View File

@ -0,0 +1,27 @@
wallet_2:
user_id: 2
amount: 0
wallet_4:
user_id: 4
amount: 0
wallet_6:
user_id: 6
amount: 0
wallet_5:
user_id: 5
amount: 0
wallet_3:
user_id: 3
amount: 0
wallet_1:
user_id: 1
amount: 0
wallet_7:
user_id: 7
amount: 0

View File

@ -0,0 +1,43 @@
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)
end
# Called after every test method runs. Can be used to tear
# down fixture information.
def teardown
# Do nothing
end
test 'get my wallet' do
get '/api/wallet/my'
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]
end
test 'admin can get wallet by user id' do
@admin = User.find_by_username('admin')
login_as(@admin, scope: :user)
@user1 = User.first
get "/api/wallet/by_user/#{@user1.id}"
assert_equal 200, response.status
assert_equal Mime::JSON, response.content_type
wallet = json_response(response.body)
assert_equal @user1.wallet.user_id, wallet[:user_id]
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}"
assert_equal 403, response.status
end
end

9
test/models/user_test.rb Normal file
View File

@ -0,0 +1,9 @@
require 'test_helper'
class UserTest < ActiveSupport::TestCase
test "must create a wallet after create user" do
u = User.create(username: 'user', email: 'userwallet@fabmanager.com', password: 'testpassword', password_confirmation: 'testpassword',
profile_attributes: {first_name: 'user', last_name: 'wallet', gender: true, birthday: 18.years.ago, phone: '0123456789'} )
assert u.wallet.present?
end
end

View File

@ -0,0 +1,13 @@
require 'test_helper'
class WalletTest < ActiveSupport::TestCase
test "default amount must be zero" do
w = Wallet.new
assert w.amount == 0
end
test 'should user present' do
w = Wallet.create
assert w.errors[:user].present?
end
end