mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
Merge branch 'dev'
This commit is contained in:
commit
ef9907aa3c
@ -1,5 +1,11 @@
|
|||||||
# Changelog Fab Manager
|
# Changelog Fab Manager
|
||||||
|
|
||||||
|
## v2.2.1 2016 June 22
|
||||||
|
- Fix a bug: field User.merged_at should not be allowed to be mapped in SSO
|
||||||
|
- Fix a bug: integration test "user reservation without plan"
|
||||||
|
- Fix a bug: can't click for some seconds in Chrome 51
|
||||||
|
- Admin: statistics tables were paginated and optimized to improve load times.
|
||||||
|
|
||||||
## v2.2.0 2016 June 16
|
## v2.2.0 2016 June 16
|
||||||
- Built-in support for extensions plug-ins
|
- Built-in support for extensions plug-ins
|
||||||
- User profile form: social networks links, personal website link, job and change profile visibility (public / private)
|
- User profile form: social networks links, personal website link, job and change profile visibility (public / private)
|
||||||
|
@ -14,7 +14,7 @@ Application.Filters = angular.module('application.filters', []);
|
|||||||
Application.Directives = angular.module('application.directives', []);
|
Application.Directives = angular.module('application.directives', []);
|
||||||
|
|
||||||
|
|
||||||
angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ngAnimate', 'ngCookies', 'ui.router', 'ui.bootstrap',
|
angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ngCookies', 'ui.router', 'ui.bootstrap',
|
||||||
'ngUpload', 'duScroll', 'application.filters','application.services', 'application.directives',
|
'ngUpload', 'duScroll', 'application.filters','application.services', 'application.directives',
|
||||||
'frapontillo.bootstrap-switch', 'application.constants', 'application.controllers', 'application.router',
|
'frapontillo.bootstrap-switch', 'application.constants', 'application.controllers', 'application.router',
|
||||||
'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'DeviseModal', 'angular-growl', 'xeditable',
|
'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'DeviseModal', 'angular-growl', 'xeditable',
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
//= require angular-cookies
|
//= require angular-cookies
|
||||||
//= require angular-resource
|
//= require angular-resource
|
||||||
//= require angular-sanitize
|
//= require angular-sanitize
|
||||||
//= require angular-animate
|
|
||||||
//= require angular-cookies
|
//= require angular-cookies
|
||||||
//= require angular-touch
|
//= require angular-touch
|
||||||
//= require angular-ui-router/release/angular-ui-router
|
//= require angular-ui-router/release/angular-ui-router
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
Application.Controllers.controller "StatisticsController", ["$scope", "$state", "$rootScope", "Statistics", "es", "Member", '_t'
|
Application.Controllers.controller "StatisticsController", ["$scope", "$state", "$rootScope", "Statistics", "es", "Member", '_t', 'membersPromise', 'statisticsPromise'
|
||||||
, ($scope, $state, $rootScope, Statistics, es, Member, _t) ->
|
, ($scope, $state, $rootScope, Statistics, es, Member, _t, membersPromise, statisticsPromise) ->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### PRIVATE STATIC CONSTANTS ###
|
||||||
|
|
||||||
|
## search window size
|
||||||
|
RESULTS_PER_PAGE = 20
|
||||||
|
|
||||||
|
## keep search context for (delay in minutes) ...
|
||||||
|
ES_SCROLL_TIME = 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -11,14 +21,23 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
$scope.preventRefresh = false
|
$scope.preventRefresh = false
|
||||||
|
|
||||||
## statistics structure in elasticSearch
|
## statistics structure in elasticSearch
|
||||||
$scope.statistics = []
|
$scope.statistics = statisticsPromise
|
||||||
|
|
||||||
## fablab users list
|
## fablab users list
|
||||||
$scope.members = []
|
$scope.members = membersPromise
|
||||||
|
|
||||||
## statistics data recovered from elasticSearch
|
## statistics data recovered from elasticSearch
|
||||||
$scope.data = null
|
$scope.data = null
|
||||||
|
|
||||||
|
## when did the search was triggered
|
||||||
|
$scope.searchDate = null
|
||||||
|
|
||||||
|
## id of the elastic search context
|
||||||
|
$scope.scrollId = null
|
||||||
|
|
||||||
|
## total number of results for the current query
|
||||||
|
$scope.totalHits = null
|
||||||
|
|
||||||
## configuration of the widget allowing to pick the ages range
|
## configuration of the widget allowing to pick the ages range
|
||||||
$scope.agePicker =
|
$scope.agePicker =
|
||||||
show: false
|
show: false
|
||||||
@ -222,13 +241,33 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
# @param id {number} user ID
|
# @param id {number} user ID
|
||||||
##
|
##
|
||||||
$scope.getUserNameFromId = (id) ->
|
$scope.getUserNameFromId = (id) ->
|
||||||
if $scope.members.length == 0
|
name = $scope.members[id]
|
||||||
return "ID "+id
|
return (if name then name else "ID "+id)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# Run a scroll query to elasticsearch to append the next packet of results to those displayed.
|
||||||
|
# If the ES search context has expired when the user ask for more results, we re-run the whole query.
|
||||||
|
##
|
||||||
|
$scope.showMoreResults = ->
|
||||||
|
# if all results were retrieved, do nothing
|
||||||
|
if $scope.data.length >= $scope.totalHits
|
||||||
|
return
|
||||||
|
|
||||||
|
if moment($scope.searchDate).add(ES_SCROLL_TIME, 'minutes').isBefore(moment())
|
||||||
|
# elastic search context has expired, so we run again the whole query
|
||||||
|
refreshStats()
|
||||||
else
|
else
|
||||||
for member in $scope.members
|
es.scroll
|
||||||
if member.id == id
|
"scroll": ES_SCROLL_TIME+'m'
|
||||||
return member.name
|
"body": {scrollId: $scope.scrollId}
|
||||||
return "ID "+id
|
, (error, response) ->
|
||||||
|
if (error)
|
||||||
|
console.error "Error: something unexpected occurred during elasticSearch scroll query: "+error
|
||||||
|
else
|
||||||
|
$scope.scrollId = response._scroll_id
|
||||||
|
$scope.data = $scope.data.concat(response.hits.hits)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -238,12 +277,6 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
# Kind of constructor: these actions will be realized first when the controller is loaded
|
# Kind of constructor: these actions will be realized first when the controller is loaded
|
||||||
##
|
##
|
||||||
initialize = ->
|
initialize = ->
|
||||||
Statistics.query (stats) ->
|
|
||||||
$scope.statistics = stats
|
|
||||||
|
|
||||||
Member.query (members) ->
|
|
||||||
$scope.members = members
|
|
||||||
|
|
||||||
# workaround for angular-bootstrap::tabs behavior: on tab deletion, another tab will be selected
|
# workaround for angular-bootstrap::tabs behavior: on tab deletion, another tab will be selected
|
||||||
# which will cause every tabs to reload, one by one, when the view is closed
|
# which will cause every tabs to reload, one by one, when the view is closed
|
||||||
$rootScope.$on '$stateChangeStart', (event, toState, toParams, fromState, fromParams) ->
|
$rootScope.$on '$stateChangeStart', (event, toState, toParams, fromState, fromParams) ->
|
||||||
@ -273,6 +306,8 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
$scope.sumCA = 0
|
$scope.sumCA = 0
|
||||||
$scope.averageAge = 0
|
$scope.averageAge = 0
|
||||||
$scope.sumStat = 0
|
$scope.sumStat = 0
|
||||||
|
$scope.totalHits = null
|
||||||
|
$scope.searchDate = new Date()
|
||||||
custom = null
|
custom = null
|
||||||
if $scope.customFilter.criterion and $scope.customFilter.criterion.key and $scope.customFilter.value
|
if $scope.customFilter.criterion and $scope.customFilter.criterion.key and $scope.customFilter.value
|
||||||
custom = {}
|
custom = {}
|
||||||
@ -283,22 +318,12 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
if (err)
|
if (err)
|
||||||
console.error("[statisticsController::refreshStats] Unable to refresh due to "+err)
|
console.error("[statisticsController::refreshStats] Unable to refresh due to "+err)
|
||||||
else
|
else
|
||||||
$scope.data = res.hits
|
$scope.data = res.hits.hits
|
||||||
sumCA = 0
|
$scope.totalHits = res.hits.total
|
||||||
sumAge = 0
|
$scope.sumCA = res.aggregations.total_ca.value
|
||||||
sumStat = 0
|
$scope.averageAge = Math.round(res.aggregations.average_age.value * 100) / 100
|
||||||
if $scope.data.length > 0
|
$scope.sumStat = res.aggregations.total_stat.value
|
||||||
angular.forEach $scope.data, (datum) ->
|
$scope.scrollId = res._scroll_id
|
||||||
if datum._source.ca
|
|
||||||
sumCA += parseInt(datum._source.ca)
|
|
||||||
if datum._source.age
|
|
||||||
sumAge += parseInt(datum._source.age)
|
|
||||||
if datum._source.stat
|
|
||||||
sumStat += parseInt(datum._source.stat)
|
|
||||||
sumAge /= $scope.data.length
|
|
||||||
$scope.sumCA = sumCA
|
|
||||||
$scope.averageAge = Math.round(sumAge*100)/100
|
|
||||||
$scope.sumStat = sumStat
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -308,7 +333,7 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
# @param type {String} statistics type (month|year|booking|hour|user|project)
|
# @param type {String} statistics type (month|year|booking|hour|user|project)
|
||||||
# @param custom {{key:{string}, value:{string}}|null} custom filter property or null to disable this filter
|
# @param custom {{key:{string}, value:{string}}|null} custom filter property or null to disable this filter
|
||||||
# @param callback {function} function be to run after results were retrieved, it will receive
|
# @param callback {function} function be to run after results were retrieved, it will receive
|
||||||
# two parameters : results {Array}, error {String} (if any)
|
# two parameters : results {Object}, error {String} (if any)
|
||||||
##
|
##
|
||||||
queryElasticStats = (index, type, custom, callback) ->
|
queryElasticStats = (index, type, custom, callback) ->
|
||||||
# handle invalid callback
|
# handle invalid callback
|
||||||
@ -320,13 +345,14 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
es.search
|
es.search
|
||||||
"index": "stats"
|
"index": "stats"
|
||||||
"type": index
|
"type": index
|
||||||
"size": 1000000000
|
"size": RESULTS_PER_PAGE
|
||||||
|
"scroll": ES_SCROLL_TIME+'m'
|
||||||
"body": buildElasticDataQuery(type, custom, $scope.agePicker.start, $scope.agePicker.end, moment($scope.datePickerStart.selected), moment($scope.datePickerEnd.selected), $scope.sorting)
|
"body": buildElasticDataQuery(type, custom, $scope.agePicker.start, $scope.agePicker.end, moment($scope.datePickerStart.selected), moment($scope.datePickerEnd.selected), $scope.sorting)
|
||||||
, (error, response) ->
|
, (error, response) ->
|
||||||
if (error)
|
if (error)
|
||||||
callback([], "Error: something unexpected occurred during elasticSearch query: "+error)
|
callback({}, "Error: something unexpected occurred during elasticSearch query: "+error)
|
||||||
else
|
else
|
||||||
callback(response.hits)
|
callback(response)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -392,6 +418,19 @@ Application.Controllers.controller "StatisticsController", ["$scope", "$state",
|
|||||||
|
|
||||||
if sortings
|
if sortings
|
||||||
q["sort"] = buildElasticSortCriteria(sortings)
|
q["sort"] = buildElasticSortCriteria(sortings)
|
||||||
|
|
||||||
|
# aggregations (avg age & CA sum)
|
||||||
|
q["aggs"] = {
|
||||||
|
"total_ca":
|
||||||
|
"sum":
|
||||||
|
"field": "ca"
|
||||||
|
"average_age":
|
||||||
|
"avg":
|
||||||
|
"field": "age"
|
||||||
|
"total_stat":
|
||||||
|
"sum":
|
||||||
|
"field": "sta"
|
||||||
|
}
|
||||||
q
|
q
|
||||||
|
|
||||||
|
|
||||||
|
@ -808,6 +808,12 @@ angular.module('application.router', ['ui.router']).
|
|||||||
templateUrl: '<%= asset_path "admin/statistics/index.html" %>'
|
templateUrl: '<%= asset_path "admin/statistics/index.html" %>'
|
||||||
controller: 'StatisticsController'
|
controller: 'StatisticsController'
|
||||||
resolve:
|
resolve:
|
||||||
|
membersPromise: ['Member', (Member) ->
|
||||||
|
Member.mapping().$promise
|
||||||
|
]
|
||||||
|
statisticsPromise: ['Statistics', (Statistics)->
|
||||||
|
Statistics.query().$promise
|
||||||
|
]
|
||||||
translations: [ 'Translations', (Translations) ->
|
translations: [ 'Translations', (Translations) ->
|
||||||
Translations.query('app.admin.statistics').$promise
|
Translations.query('app.admin.statistics').$promise
|
||||||
]
|
]
|
||||||
|
@ -22,4 +22,7 @@ Application.Services.factory 'Member', ["$resource", ($resource)->
|
|||||||
url: '/api/members/search/:query'
|
url: '/api/members/search/:query'
|
||||||
params: {query: "@query"}
|
params: {query: "@query"}
|
||||||
isArray: true
|
isArray: true
|
||||||
|
mapping:
|
||||||
|
method: 'GET'
|
||||||
|
url: '/api/members/mapping'
|
||||||
]
|
]
|
||||||
|
@ -229,7 +229,7 @@
|
|||||||
|
|
||||||
<div id="totaux">
|
<div id="totaux">
|
||||||
<ul>
|
<ul>
|
||||||
<li>{{ 'entries' | translate }} {{data.length}}</li>
|
<li>{{ 'entries' | translate }} {{totalHits}}</li>
|
||||||
<li ng-show="selectedIndex.ca">{{ 'revenue_' | translate }} {{sumCA | currency}}</li>
|
<li ng-show="selectedIndex.ca">{{ 'revenue_' | translate }} {{sumCA | currency}}</li>
|
||||||
<li>{{ 'average_age' | translate }} {{averageAge}} {{ 'years_old' | translate }}</li>
|
<li>{{ 'average_age' | translate }} {{averageAge}} {{ 'years_old' | translate }}</li>
|
||||||
<li ng-if="!type.active.simple">{{ 'total' | translate }} {{type.active.label}} : {{sumStat}}</li>
|
<li ng-if="!type.active.simple">{{ 'total' | translate }} {{type.active.label}} : {{sumStat}}</li>
|
||||||
@ -260,7 +260,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="datum in data">
|
<tr ng-repeat="datum in data">
|
||||||
<td>{{formatDate(datum._source.date)}}</td>
|
<td>{{formatDate(datum._source.date)}}</td>
|
||||||
<td><a href="" ui-sref="app.logged.members_show({id:datum._source.userId})">{{getUserNameFromId(datum._source.userId)}}</a></td>
|
<td><a href="" ui-sref="app.admin.members_edit({id:datum._source.userId})">{{getUserNameFromId(datum._source.userId)}}</a></td>
|
||||||
<td>{{formatSex(datum._source.gender)}}</td>
|
<td>{{formatSex(datum._source.gender)}}</td>
|
||||||
<td><span ng-if="datum._source.age">{{datum._source.age}} {{ 'years_old' | translate }}</span><span ng-if="!datum._source.age" translate>{{ 'unknown' }}</span></td>
|
<td><span ng-if="datum._source.age">{{datum._source.age}} {{ 'years_old' | translate }}</span><span ng-if="!datum._source.age" translate>{{ 'unknown' }}</span></td>
|
||||||
<td>{{formatSubtype(datum._source.subType)}}</td>
|
<td>{{formatSubtype(datum._source.subType)}}</td>
|
||||||
@ -278,6 +278,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<div class="text-center">
|
||||||
|
<button class="btn btn-warning" ng-click="showMoreResults()" ng-hide="data && data.length >= totalHits"><i class="fa fa-search-plus" aria-hidden="true"></i> {{ 'display_more_results' | translate }}</button>
|
||||||
|
</div>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
</uib-tabset>
|
</uib-tabset>
|
||||||
</div>
|
</div>
|
||||||
|
@ -204,6 +204,12 @@ class API::MembersController < API::ApiController
|
|||||||
@members
|
@members
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mapping
|
||||||
|
authorize User
|
||||||
|
|
||||||
|
@members = User.includes(:profile)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def set_member
|
def set_member
|
||||||
@member = User.find(params[:id])
|
@member = User.find(params[:id])
|
||||||
|
@ -16,4 +16,12 @@ class API::StatisticsController < API::ApiController
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def scroll
|
||||||
|
authorize :statistic, :scroll?
|
||||||
|
|
||||||
|
results = Elasticsearch::Client.new.scroll scroll: params[:scroll], scroll_id: params[:scrollId]
|
||||||
|
render json: results
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
class StatisticPolicy < ApplicationPolicy
|
class StatisticPolicy < ApplicationPolicy
|
||||||
['index', 'account', 'event', 'machine', 'project', 'subscription', 'training', 'user'].each do |action|
|
%w(index account event machine project subscription training user scroll).each do |action|
|
||||||
define_method "#{action}?" do
|
define_method "#{action}?" do
|
||||||
user.is_admin?
|
user.is_admin?
|
||||||
end
|
end
|
||||||
|
@ -13,10 +13,6 @@ class UserPolicy < ApplicationPolicy
|
|||||||
user.is_admin? or (record.is_allow_contact and record.is_member?) or (user.id == record.id)
|
user.is_admin? or (record.is_allow_contact and record.is_member?) or (user.id == record.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
|
||||||
user.is_admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
user.is_admin? or (user.id == record.id)
|
user.is_admin? or (user.id == record.id)
|
||||||
end
|
end
|
||||||
@ -29,8 +25,9 @@ class UserPolicy < ApplicationPolicy
|
|||||||
user.id == record.id
|
user.id == record.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def list?
|
%w(list create mapping).each do |action|
|
||||||
|
define_method "#{action}?" do
|
||||||
user.is_admin?
|
user.is_admin?
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
json.user User.column_names - %w(id encrypted_password reset_password_token reset_password_sent_at remember_created_at
|
json.user User.column_names - %w(id encrypted_password reset_password_token reset_password_sent_at remember_created_at
|
||||||
sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip confirmation_token confirmed_at
|
sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip confirmation_token confirmed_at
|
||||||
confirmation_sent_at unconfirmed_email failed_attempts unlock_token locked_at created_at updated_at stp_customer_id slug
|
confirmation_sent_at unconfirmed_email failed_attempts unlock_token locked_at created_at updated_at stp_customer_id slug
|
||||||
provider auth_token)
|
provider auth_token merged_at)
|
||||||
|
|
||||||
json.profile Profile.column_names - %w(id user_id created_at updated_at) + %w(avatar)
|
json.profile Profile.column_names - %w(id user_id created_at updated_at) + %w(avatar)
|
3
app/views/api/members/mapping.json.jbuilder
Normal file
3
app/views/api/members/mapping.json.jbuilder
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@members.each do |member|
|
||||||
|
json.set! member.id, member.profile.full_name
|
||||||
|
end
|
@ -388,6 +388,7 @@ en:
|
|||||||
revenue: "Revenue"
|
revenue: "Revenue"
|
||||||
unknown: "Unknown"
|
unknown: "Unknown"
|
||||||
user_id: "User ID"
|
user_id: "User ID"
|
||||||
|
display_more_results: "Display more results"
|
||||||
|
|
||||||
|
|
||||||
stats_graphs:
|
stats_graphs:
|
||||||
|
@ -388,6 +388,7 @@ fr:
|
|||||||
revenue: "Chiffre d'affaires"
|
revenue: "Chiffre d'affaires"
|
||||||
unknown: "Inconnu"
|
unknown: "Inconnu"
|
||||||
user_id: "ID Utilisateur"
|
user_id: "ID Utilisateur"
|
||||||
|
display_more_results: "Afficher plus de résultats"
|
||||||
|
|
||||||
|
|
||||||
stats_graphs:
|
stats_graphs:
|
||||||
|
@ -42,6 +42,7 @@ Rails.application.routes.draw do
|
|||||||
put ':id/merge', action: 'merge', on: :collection
|
put ':id/merge', action: 'merge', on: :collection
|
||||||
post 'list', action: 'list', on: :collection
|
post 'list', action: 'list', on: :collection
|
||||||
get 'search/:query', action: 'search', on: :collection
|
get 'search/:query', action: 'search', on: :collection
|
||||||
|
get 'mapping', action: 'mapping', on: :collection
|
||||||
end
|
end
|
||||||
resources :reservations, only: [:show, :create, :index, :update]
|
resources :reservations, only: [:show, :create, :index, :update]
|
||||||
resources :notifications, only: [:index, :show, :update] do
|
resources :notifications, only: [:index, :show, :update] do
|
||||||
@ -104,6 +105,7 @@ Rails.application.routes.draw do
|
|||||||
%w(account event machine project subscription training user).each do |path|
|
%w(account event machine project subscription training user).each do |path|
|
||||||
post "/stats/#{path}/_search", to: "api/statistics##{path}"
|
post "/stats/#{path}/_search", to: "api/statistics##{path}"
|
||||||
end
|
end
|
||||||
|
post '_search/scroll', to: "api/statistics#scroll"
|
||||||
|
|
||||||
match '/project_collaborator/:valid_token', to: 'api/projects#collaborator_valid', via: :get
|
match '/project_collaborator/:valid_token', to: 'api/projects#collaborator_valid', via: :get
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ module Reservations
|
|||||||
invoice_item = InvoiceItem.last
|
invoice_item = InvoiceItem.last
|
||||||
|
|
||||||
refute invoice_item.stp_invoice_item_id
|
refute invoice_item.stp_invoice_item_id
|
||||||
assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id).amount
|
assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id, plan_id: nil).amount
|
||||||
|
|
||||||
# invoice assertions
|
# invoice assertions
|
||||||
invoice = Invoice.find_by(invoiced: reservation)
|
invoice = Invoice.find_by(invoiced: reservation)
|
||||||
|
@ -55,7 +55,7 @@ module Reservations
|
|||||||
invoice_item = InvoiceItem.last
|
invoice_item = InvoiceItem.last
|
||||||
|
|
||||||
assert invoice_item.stp_invoice_item_id
|
assert invoice_item.stp_invoice_item_id
|
||||||
assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id).amount
|
assert_equal invoice_item.amount, machine.prices.find_by(group_id: @user_without_subscription.group_id, plan_id: nil).amount
|
||||||
|
|
||||||
# invoice assertions
|
# invoice assertions
|
||||||
invoice = Invoice.find_by(invoiced: reservation)
|
invoice = Invoice.find_by(invoiced: reservation)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user