diff --git a/CHANGELOG.md b/CHANGELOG.md index f599ef96c..ee8415ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog Fab Manager ## next release +- Add wallet to user, client can pay total/partial reservation or subscription by wallet - Public calendar for show all trainings/machines/events - Display 'draft' badge on drafts in project galleries - Add a 'new project' button in dashboard/my projects diff --git a/app/assets/javascripts/controllers/admin/invoices.coffee.erb b/app/assets/javascripts/controllers/admin/invoices.coffee.erb index daa410c94..044e8fd05 100644 --- a/app/assets/javascripts/controllers/admin/invoices.coffee.erb +++ b/app/assets/javascripts/controllers/admin/invoices.coffee.erb @@ -133,6 +133,8 @@ Application.Controllers.controller "InvoicesController", ["$scope", "$state", 'I sample = sample.replace(/X\[([^\]]+)\]/g, (match, p1, offset, string) -> p1 ) + # information about wallet (W[text]) - does not apply here + sample = sample.replace(/W\[([^\]]+)\]/g, "") # information about refunds (R[text]) - does not apply here sample = sample.replace(/R\[([^\]]+)\]/g, "") sample @@ -494,6 +496,7 @@ Application.Controllers.controller 'AvoirModalController', ["$scope", "$uibModal {name: _t('by_cash'), value: 'cash'} {name: _t('by_cheque'), value: 'cheque'} {name: _t('by_transfer'), value: 'transfer'} + {name: _t('by_wallet'), value: 'wallet'} ] ## If a subscription was took with the current invoice, should it be canceled or not diff --git a/app/assets/javascripts/controllers/admin/members.coffee.erb b/app/assets/javascripts/controllers/admin/members.coffee.erb index 06516d796..2c243e738 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' -, ($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', 'transactionsPromise', 'Wallet' +, ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise, transactionsPromise, Wallet) -> @@ -300,6 +300,13 @@ Application.Controllers.controller "EditMemberController", ["$scope", "$state", ## Profiles types (student/standard/...) $scope.groups = [] + ## the user wallet + $scope.wallet = walletPromise + + ## user wallet transactions + $scope.transactions = transactionsPromise + + $scope.view = 'member_edit' ## @@ -396,6 +403,39 @@ Application.Controllers.controller "EditMemberController", ["$scope", "$state", $scope.subscription = subscription + $scope.createWalletCreditModal = (user, wallet)-> + modalInstance = $uibModal.open + animation: true, + templateUrl: '<%= asset_path "wallet/credit_modal.html" %>' + controller: ['$scope', '$uibModalInstance', 'Wallet', '$locale', ($scope, $uibModalInstance, Wallet, $locale) -> + + ## currency symbol for the current locale (cf. angular-i18n) + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + ## + # Modal dialog validation callback + ## + $scope.ok = -> + Wallet.credit { id: wallet.id }, { amount: $scope.amount }, (_wallet)-> + + growl.success(_t('wallet_credit_successfully')) + $uibModalInstance.close(_wallet) + , (error)-> + growl.error(_t('a_problem_occurred_for_wallet_credit')) + + ## + # Modal dialog cancellation callback + ## + $scope.cancel = -> + $uibModalInstance.dismiss('cancel') + ] + # once the form was validated succesfully ... + modalInstance.result.then (wallet) -> + $scope.wallet = wallet + Wallet.transactions {id: wallet.id}, (transactions) -> + $scope.transactions = transactions + + ### PRIVATE SCOPE ### diff --git a/app/assets/javascripts/controllers/events.coffee.erb b/app/assets/javascripts/controllers/events.coffee.erb index b3d84f317..528d94344 100644 --- a/app/assets/javascripts/controllers/events.coffee.erb +++ b/app/assets/javascripts/controllers/events.coffee.erb @@ -132,8 +132,8 @@ Application.Controllers.controller "EventsController", ["$scope", "$state", 'Eve -Application.Controllers.controller "ShowEventController", ["$scope", "$state", "$stateParams", "Event", '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'eventPromise', 'reducedAmountAlert', 'growl', '_t' -($scope, $state, $stateParams, Event, $uibModal, Member, Reservation, Price, CustomAsset, eventPromise, reducedAmountAlert, growl, _t) -> +Application.Controllers.controller "ShowEventController", ["$scope", "$state", "$stateParams", "Event", '$uibModal', 'Member', 'Reservation', 'Price', 'CustomAsset', 'eventPromise', 'reducedAmountAlert', 'growl', '_t', 'Wallet', 'helpers', +($scope, $state, $stateParams, Event, $uibModal, Member, Reservation, Price, CustomAsset, eventPromise, reducedAmountAlert, growl, _t, Wallet, helpers) -> @@ -242,11 +242,13 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", " if Object.keys($scope.ctrl.member).length > 0 reservation = mkReservation($scope.ctrl.member, $scope.reserve, $scope.event) - if $scope.currentUser.role isnt 'admin' and $scope.reserve.amountTotal > 0 - payByStripe(reservation) - else - if $scope.currentUser.role is 'admin' or $scope.reserve.amountTotal is 0 - payOnSite(reservation) + Wallet.getWalletByUser {user_id: $scope.ctrl.member.id}, (wallet) -> + amountToPay = helpers.getAmountToPay($scope.reserve.amountTotal, wallet.amount) + if $scope.currentUser.role isnt 'admin' and amountToPay > 0 + payByStripe(reservation) + else + if $scope.currentUser.role is 'admin' or amountToPay is 0 + payOnSite(reservation) else # otherwise we alert, this error musn't occur when the current user is not admin growl.error(_t('please_select_a_member_first')) @@ -461,15 +463,20 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", " reservation price: -> Price.compute({reservation: reservation}).$promise + wallet: -> + Wallet.getWalletByUser({user_id: reservation.user_id}).$promise cgv: -> CustomAsset.get({name: 'cgv-file'}).$promise objectToPay: -> eventToReserve: $scope.event reserve: $scope.reserve member: $scope.ctrl.member - controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'growl', ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, growl) -> + controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'growl', 'wallet', 'helpers', '$locale', '$filter', ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, growl, wallet, helpers, $locale, $filter) -> + # user wallet amount + $scope.walletAmount = wallet.amount + # Price - $scope.amount = price.price + $scope.amount = helpers.getAmountToPay(price.price, wallet.amount) # CGV $scope.cgv = cgv.custom_asset @@ -477,6 +484,10 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", " # Reservation $scope.reservation = reservation + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + # Callback for the stripe payment authorization $scope.payment = (status, response) -> if response.error @@ -511,18 +522,34 @@ Application.Controllers.controller "ShowEventController", ["$scope", "$state", " reservation price: -> Price.compute({reservation: reservation}).$promise - controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation) -> + wallet: -> + Wallet.getWalletByUser({user_id: reservation.user_id}).$promise + controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', 'wallet', '$locale', 'helpers', '$filter', ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation, wallet, $locale, helpers, $filter) -> + # user wallet amount + $scope.walletAmount = wallet.amount + # Price - $scope.amount = price.price + $scope.price = price.price + + # price to pay + $scope.amount = helpers.getAmountToPay(price.price, wallet.amount) # Reservation $scope.reservation = reservation + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + # Button label + confirmPaymentText = if $scope.currentUser.role == 'admin' then _t('confirm_client_payment_of_') else _t('confirm_my_payment_of_') if $scope.amount > 0 - $scope.validButtonName = _t('confirm_(payment_on_site)') + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')($scope.amount)}" else - $scope.validButtonName = _t('confirm') + if price.price > 0 and $scope.walletAmount == 0 + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')(price.price)}" + else + $scope.validButtonName = _t('confirm') # Callback to validate the payment $scope.ok = -> diff --git a/app/assets/javascripts/controllers/machines.coffee.erb b/app/assets/javascripts/controllers/machines.coffee.erb index 79f299d62..d3092b06e 100644 --- a/app/assets/javascripts/controllers/machines.coffee.erb +++ b/app/assets/javascripts/controllers/machines.coffee.erb @@ -268,8 +268,8 @@ Application.Controllers.controller "ShowMachineController", ['$scope', '$state', # This controller workflow is pretty similar to the trainings reservation controller. ## -Application.Controllers.controller "ReserveMachineController", ["$scope", "$state", '$stateParams', "$uibModal", '_t', "moment", 'Machine', 'Auth', 'dialogs', '$timeout', 'Price', 'Member', 'Availability', 'Slot', 'Setting', 'CustomAsset', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'uiCalendarConfig', 'CalendarConfig' -($scope, $state, $stateParams, $uibModal, _t, moment, Machine, Auth, dialogs, $timeout, Price, Member, Availability, Slot, Setting, CustomAsset, plansPromise, groupsPromise, growl, settingsPromise, uiCalendarConfig, CalendarConfig) -> +Application.Controllers.controller "ReserveMachineController", ["$scope", "$state", '$stateParams', "$uibModal", '_t', "moment", 'Machine', 'Auth', 'dialogs', '$timeout', 'Price', 'Member', 'Availability', 'Slot', 'Setting', 'CustomAsset', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'Wallet', 'helpers', 'uiCalendarConfig', 'CalendarConfig', +($scope, $state, $stateParams, $uibModal, _t, moment, Machine, Auth, dialogs, $timeout, Price, Member, Availability, Slot, Setting, CustomAsset, plansPromise, groupsPromise, growl, settingsPromise, Wallet, helpers, uiCalendarConfig, CalendarConfig) -> @@ -529,11 +529,13 @@ Application.Controllers.controller "ReserveMachineController", ["$scope", "$stat if Object.keys($scope.ctrl.member).length > 0 reservation = mkReservation($scope.ctrl.member, $scope.eventsReserved, $scope.selectedPlan) - if $scope.currentUser.role isnt 'admin' and $scope.amountTotal > 0 - payByStripe(reservation) - else - if $scope.currentUser.role is 'admin' or $scope.amountTotal is 0 - payOnSite(reservation) + Wallet.getWalletByUser {user_id: $scope.ctrl.member.id}, (wallet) -> + amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount) + if $scope.currentUser.role isnt 'admin' and amountToPay > 0 + payByStripe(reservation) + else + if $scope.currentUser.role is 'admin' or amountToPay is 0 + payOnSite(reservation) else # otherwise we alert, this error musn't occur when the current user is not admin growl.error(_t('please_select_a_member_first')) @@ -752,11 +754,16 @@ Application.Controllers.controller "ReserveMachineController", ["$scope", "$stat reservation price: -> Price.compute({reservation: reservation}).$promise + wallet: -> + Wallet.getWalletByUser({user_id: reservation.user_id}).$promise cgv: -> CustomAsset.get({name: 'cgv-file'}).$promise - controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation) -> + controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'wallet', 'helpers', '$locale', '$filter', ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, wallet, helpers, $locale, $filter) -> + # user wallet amount + $scope.walletAmount = wallet.amount + # Price - $scope.amount = price.price + $scope.amount = helpers.getAmountToPay(price.price, wallet.amount) # CGV $scope.cgv = cgv.custom_asset @@ -764,6 +771,10 @@ Application.Controllers.controller "ReserveMachineController", ["$scope", "$stat # Reservation $scope.reservation = reservation + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + ## # Callback to process the payment with Stripe, triggered on button click ## @@ -800,19 +811,34 @@ Application.Controllers.controller "ReserveMachineController", ["$scope", "$stat reservation price: -> Price.compute({reservation: reservation}).$promise - controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation) -> + wallet: -> + Wallet.getWalletByUser({user_id: reservation.user_id}).$promise + controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', '$locale', ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation, wallet, helpers, $filter, $locale) -> + # user wallet amount + $scope.walletAmount = wallet.amount # Price - $scope.amount = price.price + $scope.price = price.price + + # price to pay + $scope.amount = helpers.getAmountToPay(price.price, wallet.amount) # Reservation $scope.reservation = reservation + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + # Button label + confirmPaymentText = if $scope.currentUser.role == 'admin' then _t('confirm_client_payment_of_') else _t('confirm_my_payment_of_') if $scope.amount > 0 - $scope.validButtonName = _t('confirm_(payment_on_site)') + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')($scope.amount)}" else - $scope.validButtonName = _t('confirm') + if price.price > 0 and $scope.walletAmount == 0 + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')(price.price)}" + else + $scope.validButtonName = _t('confirm') ## # Callback to process the local payment, triggered on button click diff --git a/app/assets/javascripts/controllers/plans.coffee.erb b/app/assets/javascripts/controllers/plans.coffee.erb index 529f2ba25..815a8fe8a 100644 --- a/app/assets/javascripts/controllers/plans.coffee.erb +++ b/app/assets/javascripts/controllers/plans.coffee.erb @@ -1,7 +1,7 @@ 'use strict' -Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScope", "$state", '$uibModal', 'Auth', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t' -, ($scope, $rootScope, $state, $uibModal, Auth, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t) -> +Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScope", "$state", '$uibModal', 'Auth', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t', 'Wallet', 'helpers' +, ($scope, $rootScope, $state, $uibModal, Auth, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers) -> @@ -72,10 +72,13 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop # Callback to trigger the payment process of the subscription ## $scope.openSubscribePlanModal = -> - if $scope.currentUser.role isnt 'admin' - payByStripe() - else - payOnSite() + Wallet.getWalletByUser {user_id: $scope.ctrl.member.id}, (wallet) -> + amountToPay = helpers.getAmountToPay($scope.selectedPlan.amount, wallet.amount) + if $scope.currentUser.role isnt 'admin' and amountToPay > 0 + payByStripe() + else + if $scope.currentUser.role is 'admin' or amountToPay is 0 + payOnSite() @@ -162,9 +165,20 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop resolve: selectedPlan: -> $scope.selectedPlan member: -> $scope.ctrl.member - controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'Subscription', 'CustomAsset', ($scope, $uibModalInstance, $state, selectedPlan, member, Subscription, CustomAsset) -> - $scope.amount = selectedPlan.amount + wallet: -> + Wallet.getWalletByUser({user_id: $scope.ctrl.member.id}).$promise + controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'Subscription', 'CustomAsset', 'wallet', 'helpers', '$locale', '$filter', ($scope, $uibModalInstance, $state, selectedPlan, member, Subscription, CustomAsset, wallet, helpers, $locale, $filter) -> + # user wallet amount + $scope.walletAmount = wallet.amount + + $scope.amount = helpers.getAmountToPay(selectedPlan.amount, wallet.amount) + $scope.selectedPlan = selectedPlan + + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + # retrieve the CGV CustomAsset.get {name: 'cgv-file'}, (cgv) -> $scope.cgv = cgv.custom_asset @@ -203,9 +217,34 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop resolve: selectedPlan: -> $scope.selectedPlan member: -> $scope.ctrl.member - controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'Subscription', ($scope, $uibModalInstance, $state, selectedPlan, member, Subscription) -> + wallet: -> + Wallet.getWalletByUser({user_id: $scope.ctrl.member.id}).$promise + controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'Subscription', 'wallet', 'helpers', '$locale', '$filter', ($scope, $uibModalInstance, $state, selectedPlan, member, Subscription, wallet, helpers, $locale, $filter) -> + # user wallet amount + $scope.walletAmount = wallet.amount + + $scope.price = selectedPlan.amount + + # price to pay + $scope.amount = helpers.getAmountToPay($scope.price, wallet.amount) + + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + $scope.plan = selectedPlan $scope.member = member + + # Button label + confirmPaymentText = if $scope.currentUser.role == 'admin' then _t('confirm_client_payment_of_') else _t('confirm_my_payment_of_') + if $scope.amount > 0 + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')($scope.amount)}" + else + if price.price > 0 and $scope.walletAmount == 0 + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')(price.price)}" + else + $scope.validButtonName = _t('confirm') + $scope.ok = -> $scope.attempting = true Subscription.save diff --git a/app/assets/javascripts/controllers/trainings.coffee.erb b/app/assets/javascripts/controllers/trainings.coffee.erb index f7c8589fc..8fb8de80d 100644 --- a/app/assets/javascripts/controllers/trainings.coffee.erb +++ b/app/assets/javascripts/controllers/trainings.coffee.erb @@ -51,8 +51,8 @@ Application.Controllers.controller "ShowTrainingController", ['$scope', '$state' # training can be reserved during the reservation process (the shopping cart may contains only one training and a subscription). ## -Application.Controllers.controller "ReserveTrainingController", ["$scope", "$state", '$stateParams', '$filter', '$compile', "$uibModal", 'Auth', 'dialogs', '$timeout', 'Price', 'Availability', 'Slot', 'Member', 'Setting', 'CustomAsset', 'availabilityTrainingsPromise', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'trainingPromise', '_t', 'uiCalendarConfig', 'CalendarConfig' -($scope, $state, $stateParams, $filter, $compile, $uibModal, Auth, dialogs, $timeout, Price, Availability, Slot, Member, Setting, CustomAsset, availabilityTrainingsPromise, plansPromise, groupsPromise, growl, settingsPromise, trainingPromise, _t, uiCalendarConfig, CalendarConfig) -> +Application.Controllers.controller "ReserveTrainingController", ["$scope", "$state", '$stateParams', '$filter', '$compile', "$uibModal", 'Auth', 'dialogs', '$timeout', 'Price', 'Availability', 'Slot', 'Member', 'Setting', 'CustomAsset', 'availabilityTrainingsPromise', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'trainingPromise', '_t', 'Wallet', 'helpers', 'uiCalendarConfig', 'CalendarConfig' +($scope, $state, $stateParams, $filter, $compile, $uibModal, Auth, dialogs, $timeout, Price, Availability, Slot, Member, Setting, CustomAsset, availabilityTrainingsPromise, plansPromise, groupsPromise, growl, settingsPromise, trainingPromise, _t, Wallet, helpers, uiCalendarConfig, CalendarConfig) -> @@ -188,11 +188,13 @@ Application.Controllers.controller "ReserveTrainingController", ["$scope", "$sta if Object.keys($scope.ctrl.member).length > 0 reservation = mkReservation($scope.ctrl.member, $scope.selectedTraining, $scope.selectedPlan) - if $scope.currentUser.role isnt 'admin' and $scope.amountTotal > 0 - payByStripe(reservation) - else - if $scope.currentUser.role is 'admin' or $scope.amountTotal is 0 - payOnSite(reservation) + Wallet.getWalletByUser {user_id: $scope.ctrl.member.id}, (wallet) -> + amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount) + if $scope.currentUser.role isnt 'admin' and amountToPay > 0 + payByStripe(reservation) + else + if $scope.currentUser.role is 'admin' or amountToPay is 0 + payOnSite(reservation) else # otherwise we alert, this error musn't occur when the current user is not admin growl.error(_t('please_select_a_member_first')) @@ -474,11 +476,16 @@ Application.Controllers.controller "ReserveTrainingController", ["$scope", "$sta reservation price: -> Price.compute({reservation: reservation}).$promise + wallet: -> + Wallet.getWalletByUser({user_id: reservation.user_id}).$promise cgv: -> CustomAsset.get({name: 'cgv-file'}).$promise - controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation) -> + controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'wallet', 'cgv', 'Auth', 'Reservation', '$locale', 'helpers', '$filter', ($scope, $uibModalInstance, $state, reservation, price, wallet, cgv, Auth, Reservation, $locale, helpers, $filter) -> + # user wallet amount + $scope.walletAmount = wallet.amount + # Price - $scope.amount = price.price + $scope.amount = helpers.getAmountToPay(price.price, wallet.amount) # CGV $scope.cgv = cgv.custom_asset @@ -486,6 +493,10 @@ Application.Controllers.controller "ReserveTrainingController", ["$scope", "$sta # Reservation $scope.reservation = reservation + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + ## # Callback to process the payment with Stripe, triggered on button click ## @@ -525,18 +536,34 @@ Application.Controllers.controller "ReserveTrainingController", ["$scope", "$sta reservation price: -> Price.compute({reservation: reservation}).$promise - controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation) -> + wallet: -> + Wallet.getWalletByUser({user_id: reservation.user_id}).$promise + controller: ['$scope', '$uibModalInstance', '$state', '$filter', 'reservation', 'price', 'wallet', 'Auth', 'Reservation', '$locale', 'helpers', ($scope, $uibModalInstance, $state, $filter, reservation, price, wallet, Auth, Reservation, $locale, helpers) -> + # user wallet amount + $scope.walletAmount = wallet.amount + # Price - $scope.amount = price.price + $scope.price = price.price + + # price to pay + $scope.amount = helpers.getAmountToPay(price.price, wallet.amount) # Reservation $scope.reservation = reservation + $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM + + $scope.numberFilter = $filter('number') + # Button label + confirmPaymentText = if $scope.currentUser.role == 'admin' then _t('confirm_client_payment_of_') else _t('confirm_my_payment_of_') if $scope.amount > 0 - $scope.validButtonName = _t('confirm_(payment_on_site)') + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')($scope.amount)}" else - $scope.validButtonName = _t('confirm') + if price.price > 0 and $scope.walletAmount == 0 + $scope.validButtonName = "#{confirmPaymentText} #{$filter('currency')(price.price)}" + else + $scope.validButtonName = _t('confirm') ## # Callback to process the local payment, triggered on button click diff --git a/app/assets/javascripts/controllers/wallet.coffee b/app/assets/javascripts/controllers/wallet.coffee new file mode 100644 index 000000000..9ab033672 --- /dev/null +++ b/app/assets/javascripts/controllers/wallet.coffee @@ -0,0 +1,12 @@ +'use strict' + +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 2342fa126..1c1d92d42 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -197,6 +197,22 @@ 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', 'currentUser', (Wallet, currentUser)-> + Wallet.getWalletByUser(user_id: currentUser.id).$promise + ] + transactionsPromise: ['Wallet', 'walletPromise', (Wallet, walletPromise)-> + Wallet.transactions(id: walletPromise.id).$promise + ] + translations: [ 'Translations', (Translations) -> + Translations.query(['app.shared.wallet']).$promise + ] # members @@ -347,7 +363,7 @@ angular.module('application.router', ['ui.router']). ] translations: [ 'Translations', (Translations) -> Translations.query(['app.logged.machines_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select', - 'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal']).$promise + 'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal', 'app.shared.wallet']).$promise ] .state 'app.admin.machines_edit', url: '/machines/:id/edit' @@ -424,7 +440,7 @@ angular.module('application.router', ['ui.router']). ] translations: [ 'Translations', (Translations) -> Translations.query(['app.logged.trainings_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select', - 'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal']).$promise + 'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal', 'app.shared.wallet']).$promise ] # notifications .state 'app.logged.notifications', @@ -457,7 +473,7 @@ angular.module('application.router', ['ui.router']). Group.query().$promise ] translations: [ 'Translations', (Translations) -> - Translations.query(['app.public.plans', 'app.shared.member_select', 'app.shared.stripe']).$promise + Translations.query(['app.public.plans', 'app.shared.member_select', 'app.shared.stripe', 'app.shared.wallet']).$promise ] # events @@ -494,7 +510,7 @@ angular.module('application.router', ['ui.router']). Setting.get(name: 'event_reduced_amount_alert').$promise ] translations: [ 'Translations', (Translations) -> - Translations.query(['app.public.events_show', 'app.shared.member_select', 'app.shared.stripe', 'app.shared.valid_reservation_modal']).$promise + Translations.query(['app.public.events_show', 'app.shared.member_select', 'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.wallet']).$promise ] # calendar global (trainings, machines and events) @@ -859,11 +875,17 @@ 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 + ] + transactionsPromise: ['Wallet', 'walletPromise', (Wallet, walletPromise)-> + Wallet.transactions(id: walletPromise.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' diff --git a/app/assets/javascripts/services/helpers.coffee b/app/assets/javascripts/services/helpers.coffee new file mode 100644 index 000000000..488f12852 --- /dev/null +++ b/app/assets/javascripts/services/helpers.coffee @@ -0,0 +1,6 @@ +'use strict' + +Application.Services.factory 'helpers', [()-> + getAmountToPay: (price, walletAmount)-> + if walletAmount > price then 0 else price - walletAmount + ] diff --git a/app/assets/javascripts/services/wallet.coffee b/app/assets/javascripts/services/wallet.coffee new file mode 100644 index 000000000..44c414fdb --- /dev/null +++ b/app/assets/javascripts/services/wallet.coffee @@ -0,0 +1,18 @@ +'use strict' + +Application.Services.factory 'Wallet', ["$resource", ($resource)-> + $resource "/api/wallet", + {}, + getWalletByUser: + method: 'GET' + url: '/api/wallet/by_user/:user_id' + isArray: false + transactions: + method: 'GET' + url: '/api/wallet/:id/transactions' + isArray: true + credit: + method: 'PUT' + url: '/api/wallet/:id/credit' + isArray: false +] 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..babf2b8bb 100644 --- a/app/assets/stylesheets/app.components.scss +++ b/app/assets/stylesheets/app.components.scss @@ -514,3 +514,48 @@ 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; + } + } +} + +.amountGroup { + input { + display: inline-block; + width: 100px; + margin-left: 5px; + padding-right: 6px; + font-weight: bold; + color: $green; + font-size: 1.2em; + line-height: 0; + } + .afterAmount { + margin-left: -35px; + font-weight: bold; + color: $green; + font-size: 1.2em; + line-height: 0; + } +} + diff --git a/app/assets/templates/admin/invoices/index.html.erb b/app/assets/templates/admin/invoices/index.html.erb index 730c0c01d..6ba4bda8a 100644 --- a/app/assets/templates/admin/invoices/index.html.erb +++ b/app/assets/templates/admin/invoices/index.html.erb @@ -210,6 +210,7 @@
  • {{ 'day' | translate }}
  • {{ '#_of_invoice' | translate }}
  • {{ 'online_sales' | translate }}
  • +
  • {{ 'wallet' | translate }}
  • {{ 'refund' | translate }}
  • @@ -279,6 +280,12 @@ + + \ No newline at end of file + diff --git a/app/assets/templates/admin/members/edit.html.erb b/app/assets/templates/admin/members/edit.html.erb index e8b9eaf94..7b706e0ec 100644 --- a/app/assets/templates/admin/members/edit.html.erb +++ b/app/assets/templates/admin/members/edit.html.erb @@ -215,6 +215,22 @@ + + +
    + + +
    +
    + +
    + +
    + +
    + +
    +
    diff --git a/app/assets/templates/dashboard/nav.html.erb b/app/assets/templates/dashboard/nav.html.erb index 954fcd515..9d609a588 100644 --- a/app/assets/templates/dashboard/nav.html.erb +++ b/app/assets/templates/dashboard/nav.html.erb @@ -8,15 +8,16 @@
    -

    {{ 'dashboard' }}

    - +

    {{ 'dashboard' }}

    +
    diff --git a/app/assets/templates/dashboard/wallet.html.erb b/app/assets/templates/dashboard/wallet.html.erb new file mode 100644 index 000000000..175504c64 --- /dev/null +++ b/app/assets/templates/dashboard/wallet.html.erb @@ -0,0 +1,21 @@ +
    + +
    +
    + +
    + +
    + + +
    +
    + +
    + +
    + +
    +
    +
    + diff --git a/app/assets/templates/plans/payment_modal.html.erb b/app/assets/templates/plans/payment_modal.html.erb index 42b33239f..60d198d2c 100644 --- a/app/assets/templates/plans/payment_modal.html.erb +++ b/app/assets/templates/plans/payment_modal.html.erb @@ -3,10 +3,12 @@

    {{ 'subscription_confirmation' }}

    diff --git a/app/assets/templates/shared/_wallet_amount_info.html.erb b/app/assets/templates/shared/_wallet_amount_info.html.erb new file mode 100644 index 000000000..2eeb7b4e9 --- /dev/null +++ b/app/assets/templates/shared/_wallet_amount_info.html.erb @@ -0,0 +1,10 @@ +
    +

    {{ 'you_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol } }}

    +

    {{'wallet_pay_reservation' | translate}}

    +

    {{'credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol } }}

    +
    +
    +

    {{ 'client_have_amount_in_wallet' | translate:{ amount: numberFilter(walletAmount, 2), currency: currencySymbol } }}

    +

    {{'client_wallet_pay_reservation' | translate}}

    +

    {{'client_credit_amount_for_pay_reservation' | translate:{ amount: numberFilter(amount, 2), currency: currencySymbol } }}

    +
    diff --git a/app/assets/templates/shared/header.html.erb b/app/assets/templates/shared/header.html.erb index 263be0ab2..2fae7886f 100644 --- a/app/assets/templates/shared/header.html.erb +++ b/app/assets/templates/shared/header.html.erb @@ -40,6 +40,7 @@
  • {{ 'my_trainings' }}
  • {{ 'my_events' }}
  • {{ 'my_invoices' }}
  • +
  • {{ 'my_wallet' }}
  • {{ 'sign_out' | translate }}
  • diff --git a/app/assets/templates/shared/valid_reservation_modal.html.erb b/app/assets/templates/shared/valid_reservation_modal.html.erb index 1c2483cd6..89d28df19 100644 --- a/app/assets/templates/shared/valid_reservation_modal.html.erb +++ b/app/assets/templates/shared/valid_reservation_modal.html.erb @@ -3,6 +3,8 @@

    {{ 'booking_confirmation' }}