dorsale 3.18.0 → 3.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/app/controllers/dorsale/expense_gun/expenses_controller.rb +24 -34
- data/app/filters/dorsale/expense_gun/small_data/filter_for_expenses.rb +5 -2
- data/app/helpers/dorsale/expense_gun/application_helper.rb +1 -1
- data/app/models/dorsale/expense_gun/expense.rb +4 -31
- data/app/policies/dorsale/expense_gun/expense_policy_helper.rb +9 -20
- data/app/sorters/dorsale/expense_gun/expenses_sorter.rb +8 -0
- data/app/views/dorsale/expense_gun/expenses/_filters.html.slim +8 -0
- data/app/views/dorsale/expense_gun/expenses/_form.html.slim +3 -4
- data/app/views/dorsale/expense_gun/expenses/_list.html.slim +62 -20
- data/app/views/dorsale/expense_gun/expenses/_show_actions.html.slim +2 -12
- data/app/views/dorsale/expense_gun/expenses/_state_actions.html.slim +8 -0
- data/app/views/dorsale/expense_gun/expenses/index.html.slim +1 -1
- data/config/locales/expense_gun.fr.yml +12 -10
- data/config/routes.rb +3 -4
- data/db/migrate/20210506070548_expenses_change_states.rb +7 -0
- data/features/expense_gun_expenses.feature +0 -30
- data/features/step_definitions/expense_gun_expenses_steps.rb +1 -16
- data/lib/dorsale/engine.rb +0 -1
- data/lib/dorsale/version.rb +1 -1
- data/spec/controllers/dorsale/expense_gun/expenses_controller_spec.rb +66 -17
- data/spec/models/dorsale/expense_gun/expense_spec.rb +1 -125
- data/spec/routing/dorsale/expense_gun/expenses_routing_spec.rb +9 -14
- data/spec/services/dorsale/expense_gun/expense/copy_spec.rb +2 -2
- data/spec/sorters/dorsale/expense_gun/expenses_sorter_spec.rb +20 -0
- metadata +7 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86af52038f7c9cfc24b17dbcf5229608296a7152f2e4565d3fd415d2dd88ce87
|
4
|
+
data.tar.gz: cd7c59ee287a99e1cac77068550f7a0d64451e164cb2e10855fd1dd2d9b5fb12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20bc75f4aa3210835d0b8ce2c6e7bb0b43ab7b2a496555df02fc1b6ef9983af553ad586170a5d67c729630905706d6ecea52340811781707520f71a47211e73a
|
7
|
+
data.tar.gz: 33809971e1f21d88f6a6d6d110a062cb94b18391dee6c667afa28adc9c7d9690d99806b783f02c8a0f427771e7d9f473b7a693cbba069f339005f5631426fa6d
|
data/CHANGELOG.md
CHANGED
@@ -1,15 +1,5 @@
|
|
1
1
|
class Dorsale::ExpenseGun::ExpensesController < Dorsale::ExpenseGun::ApplicationController
|
2
|
-
before_action :set_expense
|
3
|
-
:show,
|
4
|
-
:edit,
|
5
|
-
:update,
|
6
|
-
:copy,
|
7
|
-
:submit,
|
8
|
-
:accept,
|
9
|
-
:refuse,
|
10
|
-
:cancel,
|
11
|
-
]
|
12
|
-
|
2
|
+
before_action :set_expense
|
13
3
|
before_action :set_filters_variables, only: [:index]
|
14
4
|
|
15
5
|
def index
|
@@ -18,7 +8,10 @@ class Dorsale::ExpenseGun::ExpensesController < Dorsale::ExpenseGun::Application
|
|
18
8
|
@expenses ||= scope.all.preload(:user, :expense_lines)
|
19
9
|
@filters ||= Dorsale::ExpenseGun::SmallData::FilterForExpenses.new(filters_jar)
|
20
10
|
@expenses = @filters.apply(@expenses)
|
11
|
+
@expenses = Dorsale::ExpenseGun::ExpensesSorter.call(@expenses, params[:sort] ||= "-created_at")
|
21
12
|
@expenses = @expenses.page(params[:page]).per(25)
|
13
|
+
|
14
|
+
@total_payback = @expenses.limit(nil).to_a.sum(&:total_employee_payback)
|
22
15
|
end
|
23
16
|
|
24
17
|
def new
|
@@ -34,7 +27,7 @@ class Dorsale::ExpenseGun::ExpensesController < Dorsale::ExpenseGun::Application
|
|
34
27
|
@expense ||= scope.new(expense_params_for_create)
|
35
28
|
|
36
29
|
if @expense.save
|
37
|
-
|
30
|
+
set_succress_flash
|
38
31
|
redirect_to dorsale.expense_gun_expense_path(@expense)
|
39
32
|
else
|
40
33
|
render :new
|
@@ -55,7 +48,7 @@ class Dorsale::ExpenseGun::ExpensesController < Dorsale::ExpenseGun::Application
|
|
55
48
|
authorize @expense, :update?
|
56
49
|
|
57
50
|
if @expense.update(expense_params_for_update)
|
58
|
-
|
51
|
+
set_succress_flash
|
59
52
|
redirect_to dorsale.expense_gun_expense_path(@expense)
|
60
53
|
else
|
61
54
|
render :edit
|
@@ -71,50 +64,47 @@ class Dorsale::ExpenseGun::ExpensesController < Dorsale::ExpenseGun::Application
|
|
71
64
|
render :new
|
72
65
|
end
|
73
66
|
|
74
|
-
def
|
75
|
-
authorize @expense, :
|
67
|
+
def go_to_pending
|
68
|
+
authorize @expense, :go_to_pending?
|
76
69
|
|
77
|
-
@expense.
|
78
|
-
|
70
|
+
@expense.update!(state: "pending")
|
71
|
+
set_succress_flash
|
79
72
|
redirect_to dorsale.expense_gun_expenses_path
|
80
73
|
end
|
81
74
|
|
82
|
-
def
|
83
|
-
authorize @expense, :
|
84
|
-
|
85
|
-
@expense.go_to_accepted!
|
86
|
-
flash[:success] = t("expense_gun.expense.messages.accepted")
|
87
|
-
redirect_to dorsale.expense_gun_expense_path(@expense)
|
88
|
-
end
|
75
|
+
def go_to_paid
|
76
|
+
authorize @expense, :go_to_paid?
|
89
77
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
@expense.go_to_refused!
|
94
|
-
flash[:success] = t("expense_gun.expense.messages.refused")
|
78
|
+
@expense.update!(state: "paid")
|
79
|
+
set_succress_flash
|
95
80
|
redirect_to dorsale.expense_gun_expenses_path
|
96
81
|
end
|
97
82
|
|
98
|
-
def
|
99
|
-
authorize @expense, :
|
83
|
+
def go_to_canceled
|
84
|
+
authorize @expense, :go_to_canceled?
|
100
85
|
|
101
|
-
@expense.
|
102
|
-
|
86
|
+
@expense.update!(state: "canceled")
|
87
|
+
set_succress_flash
|
103
88
|
redirect_to dorsale.expense_gun_expenses_path
|
104
89
|
end
|
105
90
|
|
106
91
|
private
|
107
92
|
|
93
|
+
def set_succress_flash
|
94
|
+
flash.notice = t("expense_gun.expense.messages.#{action_name}_ok")
|
95
|
+
end
|
96
|
+
|
108
97
|
def model
|
109
98
|
::Dorsale::ExpenseGun::Expense
|
110
99
|
end
|
111
100
|
|
112
101
|
def set_expense
|
113
|
-
@expense = scope.find(params[:id])
|
102
|
+
@expense = scope.find(params[:id]) if params.key?(:id)
|
114
103
|
end
|
115
104
|
|
116
105
|
def permitted_params
|
117
106
|
[
|
107
|
+
:state,
|
118
108
|
:name,
|
119
109
|
:date,
|
120
110
|
:expense_lines_attributes => [
|
@@ -1,6 +1,9 @@
|
|
1
1
|
class Dorsale::ExpenseGun::SmallData::FilterForExpenses < ::Agilibox::SmallData::Filter
|
2
2
|
STRATEGIES = {
|
3
|
-
"expense_state"
|
4
|
-
"expense_user_id"
|
3
|
+
"expense_state" => ::Agilibox::SmallData::FilterStrategyByKeyValue.new("state"),
|
4
|
+
"expense_user_id" => ::Agilibox::SmallData::FilterStrategyByKeyValue.new("user_id"),
|
5
|
+
"expense_time_period" => ::Agilibox::SmallData::FilterStrategyByDatePeriod.new(:date),
|
6
|
+
"expense_date_begin" => ::Agilibox::SmallData::FilterStrategyByDateBegin.new(:date),
|
7
|
+
"expense_date_end" => ::Agilibox::SmallData::FilterStrategyByDateEnd.new(:date),
|
5
8
|
}
|
6
9
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
class Dorsale::ExpenseGun::Expense < ::Dorsale::ApplicationRecord
|
2
2
|
self.table_name = "dorsale_expense_gun_expenses"
|
3
|
-
|
3
|
+
|
4
|
+
STATES = %w(draft pending paid canceled)
|
4
5
|
|
5
6
|
has_many :expense_lines, inverse_of: :expense, dependent: :destroy, class_name: "Dorsale::ExpenseGun::ExpenseLine"
|
6
7
|
|
@@ -12,6 +13,7 @@ class Dorsale::ExpenseGun::Expense < ::Dorsale::ApplicationRecord
|
|
12
13
|
belongs_to :user
|
13
14
|
validates :user, presence: true
|
14
15
|
|
16
|
+
validates :state, presence: true, inclusion: {in: STATES}
|
15
17
|
validates :name, presence: true
|
16
18
|
validates :date, presence: true
|
17
19
|
|
@@ -24,6 +26,7 @@ class Dorsale::ExpenseGun::Expense < ::Dorsale::ApplicationRecord
|
|
24
26
|
}
|
25
27
|
|
26
28
|
def assign_default_values
|
29
|
+
assign_default :state, STATES.first
|
27
30
|
assign_default :date, Date.current
|
28
31
|
end
|
29
32
|
|
@@ -41,34 +44,4 @@ class Dorsale::ExpenseGun::Expense < ::Dorsale::ApplicationRecord
|
|
41
44
|
def total_vat_deductible
|
42
45
|
expense_lines.sum(&:total_vat_deductible)
|
43
46
|
end
|
44
|
-
|
45
|
-
delegate :current_state, to: :aasm
|
46
|
-
|
47
|
-
aasm(column: :state, whiny_transitions: false) do
|
48
|
-
state :draft, initial: true
|
49
|
-
state :submitted
|
50
|
-
state :accepted
|
51
|
-
state :refused
|
52
|
-
state :canceled
|
53
|
-
|
54
|
-
event :go_to_submitted do
|
55
|
-
transitions from: :draft, to: :submitted
|
56
|
-
end
|
57
|
-
|
58
|
-
event :go_to_accepted do
|
59
|
-
transitions from: :submitted, to: :accepted
|
60
|
-
end
|
61
|
-
|
62
|
-
event :go_to_refused do
|
63
|
-
transitions from: :submitted, to: :refused
|
64
|
-
end
|
65
|
-
|
66
|
-
event :go_to_canceled do
|
67
|
-
transitions from: [:draft, :submitted, :accepted], to: :canceled
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def may_edit?
|
72
|
-
current_state == :draft
|
73
|
-
end
|
74
47
|
end
|
@@ -5,34 +5,23 @@ module Dorsale::ExpenseGun::ExpensePolicyHelper
|
|
5
5
|
:read?,
|
6
6
|
:update?,
|
7
7
|
:copy?,
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:cancel?,
|
8
|
+
:go_to_pending?,
|
9
|
+
:go_to_paid?,
|
10
|
+
:go_to_canceled?,
|
12
11
|
]
|
13
12
|
|
14
|
-
def
|
15
|
-
return false unless expense.
|
13
|
+
def go_to_pending?
|
14
|
+
return false unless expense.state == "draft"
|
16
15
|
super
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
20
|
-
return false unless expense.
|
18
|
+
def go_to_paid?
|
19
|
+
return false unless expense.state == "pending"
|
21
20
|
super
|
22
21
|
end
|
23
22
|
|
24
|
-
def
|
25
|
-
return false unless expense.
|
26
|
-
super
|
27
|
-
end
|
28
|
-
|
29
|
-
def refuse?
|
30
|
-
return false unless expense.may_go_to_refused?
|
31
|
-
super
|
32
|
-
end
|
33
|
-
|
34
|
-
def cancel?
|
35
|
-
return false unless expense.may_go_to_canceled?
|
23
|
+
def go_to_canceled?
|
24
|
+
return false unless expense.state == "draft"
|
36
25
|
super
|
37
26
|
end
|
38
27
|
end
|
@@ -1,3 +1,11 @@
|
|
1
1
|
= filters_form do |f|
|
2
2
|
= f.input :expense_state, collection: expense_states_for_filters_select, include_blank: t("expense_gun.filters.all_states")
|
3
3
|
= f.input :expense_user_id, collection: @users, include_blank: t("expense_gun.filters.all_users")
|
4
|
+
|
5
|
+
= f.input(:expense_time_period,
|
6
|
+
:collection => agilibox_time_periods_for_select,
|
7
|
+
:include_blank => false,
|
8
|
+
)
|
9
|
+
|
10
|
+
= f.input :expense_date_begin, input_html: {placeholder: t("filters.date_begin")}
|
11
|
+
= f.input :expense_date_end, input_html: {placeholder: t("filters.date_end")}
|
@@ -8,10 +8,9 @@
|
|
8
8
|
|
9
9
|
.panel-body
|
10
10
|
.row
|
11
|
-
.col-md-
|
12
|
-
|
13
|
-
.col-md-
|
14
|
-
= f.input :date, as: :string, input_html: {type: :date}
|
11
|
+
.col-md-4 = f.input :name
|
12
|
+
.col-md-4 = f.input :date, as: :string, input_html: {type: :date}
|
13
|
+
.col-md-4 = f.input :state, collection: expense_states_for_filters_select, include_blank: false
|
15
14
|
|
16
15
|
#expense-lines
|
17
16
|
= f.simple_fields_for :expense_lines do |line_form|
|
@@ -1,20 +1,62 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
.
|
5
|
-
=
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
.
|
11
|
-
|
12
|
-
|
13
|
-
.
|
14
|
-
.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
table.default
|
2
|
+
thead
|
3
|
+
tr
|
4
|
+
th.expense-created_at
|
5
|
+
= sortable_column Dorsale::ExpenseGun::Expense.t(:created_at), :created_at
|
6
|
+
|
7
|
+
th.expense-date
|
8
|
+
= sortable_column Dorsale::ExpenseGun::Expense.t(:date), :date
|
9
|
+
|
10
|
+
th.expense-name
|
11
|
+
= Dorsale::ExpenseGun::Expense.t(:name)
|
12
|
+
|
13
|
+
th.expense-user
|
14
|
+
= Dorsale::ExpenseGun::Expense.t(:user)
|
15
|
+
|
16
|
+
th.expense-total_employee_payback
|
17
|
+
= Dorsale::ExpenseGun::Expense.t(:total_employee_payback)
|
18
|
+
|
19
|
+
th.expense-total_all_taxes
|
20
|
+
= Dorsale::ExpenseGun::Expense.t(:total_all_taxes)
|
21
|
+
|
22
|
+
th.expense-state
|
23
|
+
= Dorsale::ExpenseGun::Expense.t(:state)
|
24
|
+
|
25
|
+
th.expense-actions.actions
|
26
|
+
= ta(:actions)
|
27
|
+
|
28
|
+
|
29
|
+
tbody
|
30
|
+
- @expenses.each do |expense|
|
31
|
+
tr.expense
|
32
|
+
td.expense-created_at
|
33
|
+
= date expense.created_at.to_date
|
34
|
+
|
35
|
+
td.expense-date
|
36
|
+
= date expense.date
|
37
|
+
|
38
|
+
td.expense-name
|
39
|
+
= expense.name
|
40
|
+
|
41
|
+
td.expense-user
|
42
|
+
= expense.user
|
43
|
+
|
44
|
+
td.expense-total_employee_payback
|
45
|
+
= euros expense.total_employee_payback
|
46
|
+
|
47
|
+
td.expense-total_all_taxes
|
48
|
+
= euros expense.total_all_taxes
|
49
|
+
|
50
|
+
td.expense-state
|
51
|
+
= expense.tv(:state)
|
52
|
+
|
53
|
+
td.expense-actions.actions
|
54
|
+
= read_button dorsale.expense_gun_expense_path(expense)
|
55
|
+
= render "state_actions", expense: expense
|
56
|
+
|
57
|
+
tfoot
|
58
|
+
tr
|
59
|
+
td.text-right colspan=99
|
60
|
+
strong
|
61
|
+
= "Total remboursements : "
|
62
|
+
= euros @total_payback
|
@@ -1,21 +1,11 @@
|
|
1
|
+
= render "state_actions", expense: @expense
|
2
|
+
|
1
3
|
- if policy(@expense).update?
|
2
4
|
= update_button dorsale.edit_expense_gun_expense_path(@expense)
|
3
5
|
|
4
6
|
- if policy(@expense).copy?
|
5
7
|
= copy_button dorsale.copy_expense_gun_expense_path(@expense)
|
6
8
|
|
7
|
-
- if policy(@expense).submit?
|
8
|
-
= bs_button dorsale.submit_expense_gun_expense_path(@expense), action: :submit, method: "patch", confirm: true, icon: :check, class: "btn btn-xs btn-primary"
|
9
|
-
|
10
|
-
- if policy(@expense).accept?
|
11
|
-
= bs_button dorsale.accept_expense_gun_expense_path(@expense), action: :accept, method: "patch", confirm: true, icon: :check, class: "btn btn-xs btn-success"
|
12
|
-
|
13
|
-
- if policy(@expense).refuse?
|
14
|
-
= bs_button dorsale.refuse_expense_gun_expense_path(@expense), action: :refuse, method: "patch", confirm: true, icon: :ban, class: "btn btn-xs btn-danger"
|
15
|
-
|
16
|
-
- if policy(@expense).cancel?
|
17
|
-
= bs_button dorsale.cancel_expense_gun_expense_path(@expense), action: :cancel, method: "patch", confirm: true, icon: :times, class: "btn btn-xs btn-warning"
|
18
|
-
|
19
9
|
= download_button url_for(format: :pdf)
|
20
10
|
|
21
11
|
= print_button
|
@@ -0,0 +1,8 @@
|
|
1
|
+
- if policy(expense).go_to_pending?
|
2
|
+
= bs_button dorsale.go_to_pending_expense_gun_expense_path(expense), text: t("expense_gun.actions.go_to_pending"), method: "post", confirm: true, icon: :check, class: "btn btn-xs btn-success"
|
3
|
+
|
4
|
+
- if policy(expense).go_to_paid?
|
5
|
+
= bs_button dorsale.go_to_paid_expense_gun_expense_path(expense), text: t("expense_gun.actions.go_to_paid"), method: "post", confirm: true, icon: :check, class: "btn btn-xs btn-success"
|
6
|
+
|
7
|
+
- if policy(expense).go_to_canceled?
|
8
|
+
= bs_button dorsale.go_to_canceled_expense_gun_expense_path(expense), text: t("expense_gun.actions.go_to_canceled"), method: "post", confirm: true, icon: :times, class: "btn btn-xs btn-warning"
|
@@ -2,12 +2,11 @@ fr:
|
|
2
2
|
expense_gun:
|
3
3
|
expense:
|
4
4
|
messages:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
canceled : "La note de frais a été annulée."
|
5
|
+
create_ok: "La note de frais a été créée."
|
6
|
+
update_ok: "La note de frais a été mise à jour."
|
7
|
+
go_to_pending_ok: "La note de frais a été marquée comme à payer."
|
8
|
+
go_to_paid_ok: "La note de frais a été marquée comme payée."
|
9
|
+
go_to_canceled_ok: "La note de frais a été marquée comme annulée."
|
11
10
|
|
12
11
|
actions:
|
13
12
|
create : "Nouvelle note de frais"
|
@@ -25,6 +24,10 @@ fr:
|
|
25
24
|
all_states: "Tous les états"
|
26
25
|
all_users: "Tous les utilisateurs"
|
27
26
|
|
27
|
+
actions:
|
28
|
+
go_to_pending: "Marquer à payer"
|
29
|
+
go_to_paid: "Marquer payée"
|
30
|
+
go_to_canceled: "Marquer annulée"
|
28
31
|
|
29
32
|
activerecord:
|
30
33
|
models:
|
@@ -43,7 +46,7 @@ fr:
|
|
43
46
|
attributes:
|
44
47
|
dorsale/expense_gun/expense:
|
45
48
|
user : "Employé"
|
46
|
-
total_employee_payback : "Total remboursement
|
49
|
+
total_employee_payback : "Total remboursement"
|
47
50
|
vat_deductible : "TVA déductible"
|
48
51
|
total_vat_deductible : "Total TVA déductible"
|
49
52
|
total_all_taxes : "Total TTC"
|
@@ -63,7 +66,6 @@ fr:
|
|
63
66
|
dorsale/expense_gun/expense/state:
|
64
67
|
all : "Toutes"
|
65
68
|
draft : "Brouillon"
|
66
|
-
|
67
|
-
|
68
|
-
refused : "Refusée"
|
69
|
+
pending : "À payer"
|
70
|
+
paid : "Payé"
|
69
71
|
canceled : "Annulée"
|
data/config/routes.rb
CHANGED
@@ -96,10 +96,9 @@ Dorsale::Engine.routes.draw do
|
|
96
96
|
resources :expenses, except: [:destroy] do
|
97
97
|
member do
|
98
98
|
get :copy
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
patch :cancel
|
99
|
+
post :go_to_pending
|
100
|
+
post :go_to_paid
|
101
|
+
post :go_to_canceled
|
103
102
|
end
|
104
103
|
end
|
105
104
|
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class ExpensesChangeStates < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
Dorsale::ExpenseGun::Expense.where(state: "submitted").update_all(state: "pending")
|
4
|
+
Dorsale::ExpenseGun::Expense.where(state: "accepted").update_all(state: "paid")
|
5
|
+
Dorsale::ExpenseGun::Expense.where(state: "refused").update_all(state: "canceled")
|
6
|
+
end
|
7
|
+
end
|
@@ -28,33 +28,3 @@ Feature: Expenses
|
|
28
28
|
When I copy the expense
|
29
29
|
Then an expense copy is created
|
30
30
|
And I am redirected on the expense page
|
31
|
-
|
32
|
-
Scenario: Submit expense
|
33
|
-
Given an existing expense
|
34
|
-
When I go on the expense page
|
35
|
-
And I submit the expense
|
36
|
-
Then I am redirect to the expenses page
|
37
|
-
And the expense state is "submitted"
|
38
|
-
|
39
|
-
Scenario: Cancel expense
|
40
|
-
Given an existing expense
|
41
|
-
When I go on the expense page
|
42
|
-
And I cancel the expense
|
43
|
-
Then I am redirect to the expenses page
|
44
|
-
And the expense state is "canceled"
|
45
|
-
|
46
|
-
Scenario: Accept expense
|
47
|
-
Given an existing expense
|
48
|
-
And the expense is submitted
|
49
|
-
When I go on the expense page
|
50
|
-
And I accept the expense
|
51
|
-
Then I am redirect to the expense page
|
52
|
-
And the expense state is "accepted"
|
53
|
-
|
54
|
-
Scenario: Refuse expense
|
55
|
-
Given an existing expense
|
56
|
-
And the expense is submitted
|
57
|
-
When I go on the expense page
|
58
|
-
And I refuse the expense
|
59
|
-
Then I am redirect to the expenses page
|
60
|
-
And the expense state is "refused"
|
@@ -61,6 +61,7 @@ When(/^I update the expense$/) do
|
|
61
61
|
@expenses_count = Dorsale::ExpenseGun::Expense.count
|
62
62
|
@expense_lines_count = Dorsale::ExpenseGun::ExpenseLine.count
|
63
63
|
|
64
|
+
find(".link_read").click
|
64
65
|
find("#main [href$=edit]").click
|
65
66
|
|
66
67
|
fill_in :expense_name, with: "NewExpenseName"
|
@@ -78,10 +79,6 @@ Then(/^the expense is update$/) do
|
|
78
79
|
expect(@expense.name).to eq "NewExpenseName"
|
79
80
|
end
|
80
81
|
|
81
|
-
When(/^I submit the expense$/) do
|
82
|
-
find("[href$='/submit']").click
|
83
|
-
end
|
84
|
-
|
85
82
|
Then(/^I am redirect to the expenses page$/) do
|
86
83
|
wait_for { current_path }.to eq dorsale.expense_gun_expenses_path
|
87
84
|
end
|
@@ -94,18 +91,6 @@ Given(/^the expense is submitted$/) do
|
|
94
91
|
@expense.update_columns(state: "submitted")
|
95
92
|
end
|
96
93
|
|
97
|
-
When(/^I cancel the expense$/) do
|
98
|
-
find("[href$='/cancel']").click
|
99
|
-
end
|
100
|
-
|
101
|
-
When(/^I accept the expense$/) do
|
102
|
-
find("[href$='/accept']").click
|
103
|
-
end
|
104
|
-
|
105
|
-
When(/^I refuse the expense$/) do
|
106
|
-
find("[href$='/refuse']").click
|
107
|
-
end
|
108
|
-
|
109
94
|
Then(/^I am redirect to the expense page$/) do
|
110
95
|
wait_for { current_path }.to include dorsale.expense_gun_expense_path(@expense)
|
111
96
|
end
|
data/lib/dorsale/engine.rb
CHANGED
data/lib/dorsale/version.rb
CHANGED
@@ -9,38 +9,57 @@ RSpec.describe ::Dorsale::ExpenseGun::ExpensesController, type: :controller do
|
|
9
9
|
describe "filters" do
|
10
10
|
render_views
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
let!(:user1) { create(:user) }
|
13
|
+
let!(:user2) { create(:user) }
|
14
|
+
let!(:expense1) {
|
15
|
+
create(:expense_gun_expense, state: "pending", user: user1, date: "2021-05-10")
|
16
|
+
}
|
17
|
+
let!(:expense2) {
|
18
|
+
create(:expense_gun_expense, state: "canceled", user: user2, date: "2021-05-20")
|
19
|
+
}
|
15
20
|
|
16
|
-
|
21
|
+
def filter_by(**filters)
|
22
|
+
cookies[:filters] = filters.to_json
|
17
23
|
get :index
|
24
|
+
assigns :expenses
|
25
|
+
end
|
18
26
|
|
19
|
-
|
27
|
+
it "should filter by state" do
|
28
|
+
expect(filter_by expense_state: "pending").to eq [expense1]
|
20
29
|
end
|
21
30
|
|
22
31
|
it "should filter by user" do
|
23
|
-
|
24
|
-
|
25
|
-
expense1 = create(:expense_gun_expense, user: user1)
|
26
|
-
expense2 = create(:expense_gun_expense, user: user2)
|
32
|
+
expect(filter_by expense_user_id: user1.id).to eq [expense1]
|
33
|
+
end
|
27
34
|
|
28
|
-
|
29
|
-
|
35
|
+
it "should filter by date period" do
|
36
|
+
Timecop.freeze "2021-05-20"
|
37
|
+
expect(filter_by expense_time_period: "this_week").to eq [expense2]
|
38
|
+
end
|
30
39
|
|
31
|
-
|
40
|
+
it "should filter by date begin" do
|
41
|
+
expect(filter_by expense_date_begin: "2021-05-15").to eq [expense2]
|
32
42
|
end
|
33
43
|
|
34
|
-
it "should
|
35
|
-
|
36
|
-
|
37
|
-
expense2 = create(:expense_gun_expense, user: user2)
|
44
|
+
it "should filter by date begin" do
|
45
|
+
expect(filter_by expense_date_end: "2021-05-15").to eq [expense1]
|
46
|
+
end
|
38
47
|
|
48
|
+
it "should assigns only users having expenses" do
|
49
|
+
expense1.destroy!
|
39
50
|
get :index
|
40
|
-
|
41
51
|
expect(assigns :users).to eq [user2]
|
42
52
|
end
|
43
53
|
end # describe "filters"
|
54
|
+
|
55
|
+
it "should set total_payback" do
|
56
|
+
create(:expense_gun_expense_line, total_all_taxes: 200, company_part: 50)
|
57
|
+
.expense.update!(state: "pending")
|
58
|
+
create(:expense_gun_expense_line, total_all_taxes: 50, company_part: 100)
|
59
|
+
.expense.update!(state: "paid")
|
60
|
+
get :index
|
61
|
+
expect(assigns :total_payback).to eq 150
|
62
|
+
end
|
44
63
|
end # describe "#index"
|
45
64
|
|
46
65
|
describe "#show" do
|
@@ -52,4 +71,34 @@ RSpec.describe ::Dorsale::ExpenseGun::ExpensesController, type: :controller do
|
|
52
71
|
expect(response).to be_ok
|
53
72
|
end
|
54
73
|
end # describe "#show"
|
74
|
+
|
75
|
+
describe "#go_to_pending" do
|
76
|
+
it "should go to pending and redirect" do
|
77
|
+
expense = create(:expense_gun_expense, user: user, state: "draft")
|
78
|
+
post :go_to_pending, params: {id: expense}
|
79
|
+
expect(response).to be_redirect
|
80
|
+
expect(flash.notice).to be_present
|
81
|
+
expect(expense.reload.state).to eq "pending"
|
82
|
+
end
|
83
|
+
end # describe "#go_to_pending"
|
84
|
+
|
85
|
+
describe "#go_to_paid" do
|
86
|
+
it "should go to paid and redirect" do
|
87
|
+
expense = create(:expense_gun_expense, user: user, state: "pending")
|
88
|
+
post :go_to_paid, params: {id: expense}
|
89
|
+
expect(response).to be_redirect
|
90
|
+
expect(flash.notice).to be_present
|
91
|
+
expect(expense.reload.state).to eq "paid"
|
92
|
+
end
|
93
|
+
end # describe "#go_to_pending"
|
94
|
+
|
95
|
+
describe "#go_to_canceled" do
|
96
|
+
it "should go to canceled and redirect" do
|
97
|
+
expense = create(:expense_gun_expense, user: user, state: "draft")
|
98
|
+
post :go_to_canceled, params: {id: expense}
|
99
|
+
expect(response).to be_redirect
|
100
|
+
expect(flash.notice).to be_present
|
101
|
+
expect(expense.reload.state).to eq "canceled"
|
102
|
+
end
|
103
|
+
end # describe "#go_to_pending"
|
55
104
|
end
|
@@ -14,123 +14,7 @@ RSpec.describe Dorsale::ExpenseGun::Expense, type: :model do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "new expense should have new state" do
|
17
|
-
expect(described_class.new.
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "new state" do
|
21
|
-
before :each do
|
22
|
-
@expense = build(:expense_gun_expense)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "new expense can be submitted" do
|
26
|
-
expect(@expense.go_to_submitted).to be true
|
27
|
-
expect(@expense.current_state).to be :submitted
|
28
|
-
end
|
29
|
-
|
30
|
-
it "new expense can't be accepted" do
|
31
|
-
expect(@expense.go_to_accepted).to be false
|
32
|
-
expect(@expense.current_state).to be :draft
|
33
|
-
end
|
34
|
-
|
35
|
-
it "new expense can't be refused" do
|
36
|
-
expect(@expense.go_to_refused).to be false
|
37
|
-
expect(@expense.current_state).to be :draft
|
38
|
-
end
|
39
|
-
|
40
|
-
it "new expense can be canceled" do
|
41
|
-
expect(@expense.go_to_canceled).to be true
|
42
|
-
expect(@expense.current_state).to be :canceled
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe "submitted state" do
|
47
|
-
before :each do
|
48
|
-
@expense = build(:expense_gun_expense)
|
49
|
-
@expense.go_to_submitted
|
50
|
-
end
|
51
|
-
|
52
|
-
it "submitted expense can be accepted" do
|
53
|
-
expect(@expense.go_to_accepted).to be true
|
54
|
-
expect(@expense.current_state).to be :accepted
|
55
|
-
end
|
56
|
-
|
57
|
-
it "submitted expense can be refused" do
|
58
|
-
expect(@expense.go_to_refused).to be true
|
59
|
-
expect(@expense.current_state).to be :refused
|
60
|
-
end
|
61
|
-
|
62
|
-
it "submitted expense can be canceled" do
|
63
|
-
expect(@expense.go_to_canceled).to be true
|
64
|
-
expect(@expense.current_state).to be :canceled
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "acceped state" do
|
69
|
-
before :each do
|
70
|
-
@expense = build(:expense_gun_expense)
|
71
|
-
@expense.go_to_submitted
|
72
|
-
@expense.go_to_accepted
|
73
|
-
end
|
74
|
-
|
75
|
-
it "acceped expense can't be submitted" do
|
76
|
-
expect(@expense.go_to_submitted).to be false
|
77
|
-
expect(@expense.current_state).to be :accepted
|
78
|
-
end
|
79
|
-
|
80
|
-
it "acceped expense can't be refused" do
|
81
|
-
expect(@expense.go_to_refused).to be false
|
82
|
-
expect(@expense.current_state).to be :accepted
|
83
|
-
end
|
84
|
-
|
85
|
-
it "acceped expense can be canceled" do
|
86
|
-
expect(@expense.go_to_canceled).to be true
|
87
|
-
expect(@expense.current_state).to be :canceled
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
describe "refused state" do
|
92
|
-
before :each do
|
93
|
-
@expense = build(:expense_gun_expense)
|
94
|
-
@expense.go_to_submitted
|
95
|
-
@expense.go_to_refused
|
96
|
-
end
|
97
|
-
|
98
|
-
it "refused expense can't be submitted" do
|
99
|
-
expect(@expense.go_to_submitted).to be false
|
100
|
-
expect(@expense.current_state).to be :refused
|
101
|
-
end
|
102
|
-
|
103
|
-
it "refused expense can't be acceped" do
|
104
|
-
expect(@expense.go_to_accepted).to be false
|
105
|
-
expect(@expense.current_state).to be :refused
|
106
|
-
end
|
107
|
-
|
108
|
-
it "refused expense can't be canceled" do
|
109
|
-
expect(@expense.go_to_canceled).to be false
|
110
|
-
expect(@expense.current_state).to be :refused
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe "canceled state" do
|
115
|
-
before :each do
|
116
|
-
@expense = build(:expense_gun_expense)
|
117
|
-
@expense.go_to_canceled
|
118
|
-
end
|
119
|
-
|
120
|
-
it "canceled expense can't be submitted" do
|
121
|
-
expect(@expense.go_to_submitted).to be false
|
122
|
-
expect(@expense.current_state).to be :canceled
|
123
|
-
end
|
124
|
-
|
125
|
-
it "canceled expense can't be acceped" do
|
126
|
-
expect(@expense.go_to_accepted).to be false
|
127
|
-
expect(@expense.current_state).to be :canceled
|
128
|
-
end
|
129
|
-
|
130
|
-
it "canceled expense can't be refused" do
|
131
|
-
expect(@expense.go_to_refused).to be false
|
132
|
-
expect(@expense.current_state).to be :canceled
|
133
|
-
end
|
17
|
+
expect(described_class.new.state).to eq "draft"
|
134
18
|
end
|
135
19
|
|
136
20
|
it "#total_all_taxes should return sum of lines" do
|
@@ -165,12 +49,4 @@ RSpec.describe Dorsale::ExpenseGun::Expense, type: :model do
|
|
165
49
|
|
166
50
|
expect(expense.total_vat_deductible).to eq 5.0
|
167
51
|
end
|
168
|
-
|
169
|
-
it "#may_edit? should return false unless expense is not submitted" do
|
170
|
-
expect(described_class.new(state: :draft).may_edit?).to be true
|
171
|
-
expect(described_class.new(state: :submitted).may_edit?).to be false
|
172
|
-
expect(described_class.new(state: :acceped).may_edit?).to be false
|
173
|
-
expect(described_class.new(state: :refused).may_edit?).to be false
|
174
|
-
expect(described_class.new(state: :canceled).may_edit?).to be false
|
175
|
-
end
|
176
52
|
end
|
@@ -34,24 +34,19 @@ describe ::Dorsale::ExpenseGun::ExpensesController, type: :routing do
|
|
34
34
|
route_to("dorsale/expense_gun/expenses#update", id: "1")
|
35
35
|
end
|
36
36
|
|
37
|
-
it "#
|
38
|
-
expect(
|
39
|
-
route_to("dorsale/expense_gun/expenses#
|
37
|
+
it "#go_to_pending" do
|
38
|
+
expect(post "/expense_gun/expenses/1/go_to_pending").to \
|
39
|
+
route_to("dorsale/expense_gun/expenses#go_to_pending", id: "1")
|
40
40
|
end
|
41
41
|
|
42
|
-
it "#
|
43
|
-
expect(
|
44
|
-
route_to("dorsale/expense_gun/expenses#
|
42
|
+
it "#go_to_paid" do
|
43
|
+
expect(post "/expense_gun/expenses/1/go_to_paid").to \
|
44
|
+
route_to("dorsale/expense_gun/expenses#go_to_paid", id: "1")
|
45
45
|
end
|
46
46
|
|
47
|
-
it "#
|
48
|
-
expect(
|
49
|
-
route_to("dorsale/expense_gun/expenses#
|
50
|
-
end
|
51
|
-
|
52
|
-
it "#cancel" do
|
53
|
-
expect(patch "/expense_gun/expenses/1/cancel").to \
|
54
|
-
route_to("dorsale/expense_gun/expenses#cancel", id: "1")
|
47
|
+
it "#go_to_canceled" do
|
48
|
+
expect(post "/expense_gun/expenses/1/go_to_canceled").to \
|
49
|
+
route_to("dorsale/expense_gun/expenses#go_to_canceled", id: "1")
|
55
50
|
end
|
56
51
|
|
57
52
|
it "#copy" do
|
@@ -6,7 +6,7 @@ RSpec.describe ::Dorsale::ExpenseGun::Expense::Copy do
|
|
6
6
|
:user => create(:user),
|
7
7
|
:name => "ExpenseName",
|
8
8
|
:date => Date.current,
|
9
|
-
:state => "
|
9
|
+
:state => "paid",
|
10
10
|
)
|
11
11
|
|
12
12
|
line = create(:expense_gun_expense_line,
|
@@ -56,7 +56,7 @@ RSpec.describe ::Dorsale::ExpenseGun::Expense::Copy do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should reset expense state" do
|
59
|
-
expect(expense.state).to eq "
|
59
|
+
expect(expense.state).to eq "paid"
|
60
60
|
expect(copy.state).to eq "draft"
|
61
61
|
end
|
62
62
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "rails_helper"
|
2
|
+
|
3
|
+
describe Dorsale::ExpenseGun::ExpensesSorter do
|
4
|
+
let!(:expense1) { create(:expense_gun_expense, date: "2021-05-10") }
|
5
|
+
let!(:expense2) { create(:expense_gun_expense, date: "2021-05-20") }
|
6
|
+
|
7
|
+
def sort_by(column)
|
8
|
+
described_class.call(Dorsale::ExpenseGun::Expense.all, column)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.it_should_sort_by(column)
|
12
|
+
it "should sort by #{column}" do
|
13
|
+
expect(sort_by column.to_s).to eq [expense1, expense2]
|
14
|
+
expect(sort_by "-#{column}").to eq [expense2, expense1]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it_should_sort_by :created_at
|
19
|
+
it_should_sort_by :date
|
20
|
+
end # describe "sorting"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dorsale
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- agilidée
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -218,20 +218,6 @@ dependencies:
|
|
218
218
|
- - "<"
|
219
219
|
- !ruby/object:Gem::Version
|
220
220
|
version: '99'
|
221
|
-
- !ruby/object:Gem::Dependency
|
222
|
-
name: aasm
|
223
|
-
requirement: !ruby/object:Gem::Requirement
|
224
|
-
requirements:
|
225
|
-
- - "<"
|
226
|
-
- !ruby/object:Gem::Version
|
227
|
-
version: '99'
|
228
|
-
type: :runtime
|
229
|
-
prerelease: false
|
230
|
-
version_requirements: !ruby/object:Gem::Requirement
|
231
|
-
requirements:
|
232
|
-
- - "<"
|
233
|
-
- !ruby/object:Gem::Version
|
234
|
-
version: '99'
|
235
221
|
- !ruby/object:Gem::Dependency
|
236
222
|
name: pdf-reader
|
237
223
|
requirement: !ruby/object:Gem::Requirement
|
@@ -589,6 +575,7 @@ files:
|
|
589
575
|
- app/services/dorsale/service.rb
|
590
576
|
- app/services/dorsale/tag_list_for_model.rb
|
591
577
|
- app/sorters/dorsale/alexandrie/attachments_sorter.rb
|
578
|
+
- app/sorters/dorsale/expense_gun/expenses_sorter.rb
|
592
579
|
- app/sorters/dorsale/flyboy/task_comments_sorter.rb
|
593
580
|
- app/sorters/dorsale/flyboy/tasks_sorter.rb
|
594
581
|
- app/uploaders/dorsale/alexandrie/file_uploader.rb
|
@@ -716,6 +703,7 @@ files:
|
|
716
703
|
- app/views/dorsale/expense_gun/expenses/_index_actions.html.slim
|
717
704
|
- app/views/dorsale/expense_gun/expenses/_list.html.slim
|
718
705
|
- app/views/dorsale/expense_gun/expenses/_show_actions.html.slim
|
706
|
+
- app/views/dorsale/expense_gun/expenses/_state_actions.html.slim
|
719
707
|
- app/views/dorsale/expense_gun/expenses/edit.html.slim
|
720
708
|
- app/views/dorsale/expense_gun/expenses/index.html.slim
|
721
709
|
- app/views/dorsale/expense_gun/expenses/new.html.slim
|
@@ -819,6 +807,7 @@ files:
|
|
819
807
|
- db/migrate/20171115171425_dorsale_customer_vault_people_add_secondary_emails.rb
|
820
808
|
- db/migrate/20210202100529_billing_machine_add_positions.rb
|
821
809
|
- db/migrate/20210311131928_billing_machine_add_missing_unique_indexes.rb
|
810
|
+
- db/migrate/20210506070548_expenses_change_states.rb
|
822
811
|
- features/access.feature
|
823
812
|
- features/billing_machine_invoices.feature
|
824
813
|
- features/billing_machine_multiple_vat.feature
|
@@ -951,6 +940,7 @@ files:
|
|
951
940
|
- spec/services/dorsale/expense_gun/expense/copy_spec.rb
|
952
941
|
- spec/services/dorsale/flyboy/task/copy_spec.rb
|
953
942
|
- spec/services/dorsale/flyboy/task/snoozer_spec.rb
|
943
|
+
- spec/sorters/dorsale/expense_gun/expenses_sorter_spec.rb
|
954
944
|
- spec/spec_helper.rb
|
955
945
|
- spec/support/devise.rb
|
956
946
|
- spec/support/message_delivery.rb
|
@@ -1004,6 +994,7 @@ test_files:
|
|
1004
994
|
- spec/models/dorsale/flyboy/task_spec.rb
|
1005
995
|
- spec/models/dorsale/flyboy/task_comment_spec.rb
|
1006
996
|
- spec/models/dorsale/address_spec.rb
|
997
|
+
- spec/sorters/dorsale/expense_gun/expenses_sorter_spec.rb
|
1007
998
|
- spec/support/devise.rb
|
1008
999
|
- spec/support/message_delivery.rb
|
1009
1000
|
- spec/factories/expense_gun_categories.rb
|