dorsale 3.14.11 → 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 +21 -0
- data/app/assets/javascripts/dorsale/dependencies.coffee +1 -1
- data/app/assets/javascripts/dorsale/engines/billing_machine.coffee.erb +14 -0
- data/app/assets/stylesheets/dorsale/engines/billing_machine.sass +4 -1
- data/app/controllers/dorsale/billing_machine/invoices_controller.rb +14 -9
- data/app/controllers/dorsale/billing_machine/quotations_controller.rb +14 -9
- data/app/controllers/dorsale/expense_gun/expenses_controller.rb +24 -34
- data/app/controllers/dorsale/flyboy/task_comments_controller.rb +2 -2
- 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/mailers/dorsale/flyboy/task_mailer.rb +2 -2
- data/app/models/dorsale/billing_machine/invoice.rb +2 -4
- data/app/models/dorsale/billing_machine/invoice_line.rb +1 -1
- data/app/models/dorsale/billing_machine/quotation.rb +1 -1
- data/app/models/dorsale/billing_machine/quotation_line.rb +1 -1
- data/app/models/dorsale/customer_vault/corporation.rb +11 -2
- data/app/models/dorsale/customer_vault/individual.rb +4 -2
- data/app/models/dorsale/customer_vault/person.rb +1 -1
- data/app/models/dorsale/expense_gun/expense.rb +7 -34
- data/app/policies/dorsale/expense_gun/expense_policy_helper.rb +9 -20
- data/app/services/dorsale/flyboy/task/snoozer.rb +1 -1
- data/app/sorters/dorsale/expense_gun/expenses_sorter.rb +8 -0
- data/app/uploaders/dorsale/image_uploader.rb +1 -1
- data/app/uploaders/dorsale/pdf_uploader.rb +1 -1
- data/app/views/dorsale/billing_machine/commons/_form.html.slim +2 -1
- data/app/views/dorsale/billing_machine/commons/_line_fields.html.slim +4 -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/app/views/dorsale/flyboy/task_mailer/new_task.html.slim +1 -1
- data/app/views/dorsale/flyboy/task_mailer/term_email.html.slim +1 -1
- data/config/locales/billing_machine.fr.yml +1 -0
- data/config/locales/expense_gun.fr.yml +12 -10
- data/config/routes.rb +3 -4
- data/db/migrate/20210202100529_billing_machine_add_positions.rb +6 -0
- data/db/migrate/20210311131928_billing_machine_add_missing_unique_indexes.rb +6 -0
- data/db/migrate/20210506070548_expenses_change_states.rb +7 -0
- data/features/expense_gun_expenses.feature +0 -30
- data/features/step_definitions/customer_vault_people_steps.rb +1 -1
- 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/controllers/dorsale/flyboy/task_comments_controller_spec.rb +2 -2
- data/spec/factories/customer_vault_individuals.rb +13 -13
- data/spec/factories/expense_gun_categories.rb +3 -3
- data/spec/factories/expense_gun_expense_lines.rb +7 -7
- data/spec/factories/expense_gun_expenses.rb +3 -3
- data/spec/models/dorsale/expense_gun/expense_spec.rb +1 -125
- data/spec/pdfs/dorsale/billing_machine/invoice_multiple_vat_pdf_spec.rb +1 -1
- data/spec/pdfs/dorsale/billing_machine/invoice_single_vat_pdf_spec.rb +1 -1
- data/spec/pdfs/dorsale/billing_machine/quotation_multiple_vat_pdf_spec.rb +1 -1
- data/spec/pdfs/dorsale/billing_machine/quotation_single_vat_pdf_spec.rb +1 -1
- data/spec/rails_helper.rb +0 -1
- 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 +10 -35
- data/app/assets/javascripts/url.min.js +0 -1
- data/app/models/dorsale/customer_vault/corporation_data.rb +0 -10
- data/app/models/dorsale/customer_vault/individual_data.rb +0 -3
- data/app/models/dorsale/customer_vault/person_data.rb +0 -17
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
@@ -2,6 +2,27 @@
|
|
2
2
|
|
3
3
|
## Next version
|
4
4
|
|
5
|
+
# 3.19.0
|
6
|
+
- Change expenses state machine
|
7
|
+
- Change expenses list view
|
8
|
+
|
9
|
+
# 3.18.0
|
10
|
+
- Change uploaders `extension_whitelist` to `extension_allowlist`
|
11
|
+
- Rails 6.1 compatibility
|
12
|
+
|
13
|
+
## 3.17.0
|
14
|
+
- Refactor CV models using stores
|
15
|
+
- Fix redirect after task comment create
|
16
|
+
- Add missing unique indexes on invoices and quotations
|
17
|
+
|
18
|
+
## 3.16.0
|
19
|
+
- Allow to reorder BM lines (require Sorting.js + reimport migrations)
|
20
|
+
- Remove unused url.js
|
21
|
+
|
22
|
+
## 3.15.0
|
23
|
+
- Fix Ruby 2.7 warnings
|
24
|
+
- Faker 2
|
25
|
+
|
5
26
|
## 3.14.11
|
6
27
|
- Fix BM missing PDFs
|
7
28
|
|
@@ -4,11 +4,11 @@
|
|
4
4
|
//= require bootstrap
|
5
5
|
//= require cocoon
|
6
6
|
//= require accounting
|
7
|
-
//= require url.min
|
8
7
|
//= require select2
|
9
8
|
//= require select2_locale_fr
|
10
9
|
//= require bootstrap-datepicker/core
|
11
10
|
//= require bootstrap-datepicker/locales/bootstrap-datepicker.fr
|
12
11
|
//= require Chart.bundle
|
13
12
|
//= require chartkick
|
13
|
+
//= require Sortable
|
14
14
|
//= require agilibox/all
|
@@ -77,6 +77,10 @@ BillingMachine.formatInputs = ->
|
|
77
77
|
formatted_number = BillingMachine.num2str BillingMachine.str2num $(this).val()
|
78
78
|
$(this).val formatted_number
|
79
79
|
|
80
|
+
BillingMachine.updatePositions = ->
|
81
|
+
i = 0
|
82
|
+
$("#billing_machine-form input[name*=position]").map -> this.value = (i = i + 1)
|
83
|
+
|
80
84
|
# Empty number inputs on focus if value is 0
|
81
85
|
$(document).on "focus", "#billing_machine-form input.number", ->
|
82
86
|
$(this).val("") if BillingMachine.str2num($(this).val()) == 0
|
@@ -96,6 +100,7 @@ $(document).on "click", "#billing_machine-form a.delete", (e) ->
|
|
96
100
|
$(document).on "turbolinks:load cocoon:after-insert", ->
|
97
101
|
BillingMachine.formatInputs()
|
98
102
|
BillingMachine.updateTotals()
|
103
|
+
BillingMachine.updatePositions()
|
99
104
|
|
100
105
|
# Fix Cocoon bug
|
101
106
|
$("#billing_machine-form .line textarea").map ->
|
@@ -106,3 +111,12 @@ $(document).on "keyup", "#billing_machine-form input.number", ->
|
|
106
111
|
|
107
112
|
$(document).on "blur", "#billing_machine-form input.number", ->
|
108
113
|
BillingMachine.formatInputs()
|
114
|
+
|
115
|
+
$(document).on "turbolinks:load", ->
|
116
|
+
$("#billing_machine-form tbody").map ->
|
117
|
+
container = this
|
118
|
+
|
119
|
+
new Sortable container,
|
120
|
+
handle: ".handle"
|
121
|
+
animation: 150
|
122
|
+
onSort: -> BillingMachine.updatePositions()
|
@@ -157,15 +157,20 @@ class Dorsale::BillingMachine::InvoicesController < ::Dorsale::BillingMachine::A
|
|
157
157
|
:advance,
|
158
158
|
:due_date,
|
159
159
|
:comments,
|
160
|
-
:lines_attributes =>
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
160
|
+
:lines_attributes => line_permitted_params,
|
161
|
+
]
|
162
|
+
end
|
163
|
+
|
164
|
+
def line_permitted_params
|
165
|
+
[
|
166
|
+
:_destroy,
|
167
|
+
:id,
|
168
|
+
:label,
|
169
|
+
:quantity,
|
170
|
+
:unit,
|
171
|
+
:unit_price,
|
172
|
+
:vat_rate,
|
173
|
+
:position,
|
169
174
|
]
|
170
175
|
end
|
171
176
|
|
@@ -165,15 +165,20 @@ class Dorsale::BillingMachine::QuotationsController < ::Dorsale::BillingMachine:
|
|
165
165
|
:comments,
|
166
166
|
:vat_rate,
|
167
167
|
:commercial_discount,
|
168
|
-
:lines_attributes =>
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
168
|
+
:lines_attributes => line_permitted_params,
|
169
|
+
]
|
170
|
+
end
|
171
|
+
|
172
|
+
def line_permitted_params
|
173
|
+
[
|
174
|
+
:_destroy,
|
175
|
+
:id,
|
176
|
+
:label,
|
177
|
+
:quantity,
|
178
|
+
:unit,
|
179
|
+
:unit_price,
|
180
|
+
:vat_rate,
|
181
|
+
:position,
|
177
182
|
]
|
178
183
|
end
|
179
184
|
|
@@ -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 => [
|
@@ -19,9 +19,9 @@ class Dorsale::Flyboy::TaskCommentsController < ::Dorsale::Flyboy::ApplicationCo
|
|
19
19
|
|
20
20
|
def back_url
|
21
21
|
task_path = flyboy_task_path(@task)
|
22
|
-
back_url = super
|
22
|
+
back_url = super.to_s
|
23
23
|
|
24
|
-
if back_url.
|
24
|
+
if back_url == task_path || back_url.start_with?(task_path + "?")
|
25
25
|
back_url
|
26
26
|
else
|
27
27
|
task_path
|
@@ -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
|
@@ -11,7 +11,7 @@ class Dorsale::Flyboy::TaskMailer < ::Dorsale::ApplicationMailer
|
|
11
11
|
|
12
12
|
mail(
|
13
13
|
:to => task.owner.email,
|
14
|
-
:subject => t("task_mailer.new_task.subject",
|
14
|
+
:subject => t("task_mailer.new_task.subject", **@locals),
|
15
15
|
)
|
16
16
|
end
|
17
17
|
|
@@ -26,7 +26,7 @@ class Dorsale::Flyboy::TaskMailer < ::Dorsale::ApplicationMailer
|
|
26
26
|
|
27
27
|
mail(
|
28
28
|
:to => task.owner.email,
|
29
|
-
:subject => t("task_mailer.term_email.subject",
|
29
|
+
:subject => t("task_mailer.term_email.subject", **@locals),
|
30
30
|
)
|
31
31
|
end
|
32
32
|
end
|
@@ -55,7 +55,7 @@ class Dorsale::BillingMachine::Invoice < ::Dorsale::ApplicationRecord
|
|
55
55
|
lines.each(&:update_total)
|
56
56
|
apply_vat_rate_to_lines
|
57
57
|
|
58
|
-
lines_sum = lines.
|
58
|
+
lines_sum = lines.sum(&:total).round(2)
|
59
59
|
|
60
60
|
self.total_excluding_taxes = lines_sum - commercial_discount
|
61
61
|
|
@@ -109,9 +109,7 @@ class Dorsale::BillingMachine::Invoice < ::Dorsale::ApplicationRecord
|
|
109
109
|
def payment_status
|
110
110
|
if paid?
|
111
111
|
:paid
|
112
|
-
elsif due_date.nil?
|
113
|
-
:on_alert
|
114
|
-
elsif Date.current >= due_date + 15
|
112
|
+
elsif due_date.nil? || Date.current >= due_date + 15
|
115
113
|
:on_alert
|
116
114
|
elsif Date.current > due_date
|
117
115
|
:late
|
@@ -61,7 +61,7 @@ class Dorsale::BillingMachine::Quotation < ::Dorsale::ApplicationRecord
|
|
61
61
|
lines.each(&:update_total)
|
62
62
|
apply_vat_rate_to_lines
|
63
63
|
|
64
|
-
lines_sum = lines.
|
64
|
+
lines_sum = lines.sum(&:total)
|
65
65
|
|
66
66
|
self.total_excluding_taxes = lines_sum - commercial_discount
|
67
67
|
|
@@ -1,6 +1,15 @@
|
|
1
1
|
class Dorsale::CustomerVault::Corporation < Dorsale::CustomerVault::Person
|
2
|
-
|
3
|
-
|
2
|
+
data_attributes = %i(
|
3
|
+
legal_form
|
4
|
+
immatriculation_number
|
5
|
+
naf
|
6
|
+
european_union_vat_number
|
7
|
+
societe_com
|
8
|
+
capital
|
9
|
+
revenue
|
10
|
+
number_of_employees
|
11
|
+
)
|
12
|
+
store :data, accessors: data_attributes, coder: JSON
|
4
13
|
|
5
14
|
validates :corporation_name, presence: true
|
6
15
|
has_many :individuals, dependent: :nullify
|
@@ -1,6 +1,8 @@
|
|
1
1
|
class Dorsale::CustomerVault::Individual < Dorsale::CustomerVault::Person
|
2
|
-
|
3
|
-
|
2
|
+
data_attributes = %i(
|
3
|
+
title
|
4
|
+
)
|
5
|
+
store :data, accessors: data_attributes, coder: JSON
|
4
6
|
|
5
7
|
validates :first_name, presence: true
|
6
8
|
validates :last_name, presence: true
|
@@ -10,7 +10,7 @@ class Dorsale::CustomerVault::Person < ::Dorsale::ApplicationRecord
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def verify_class
|
13
|
-
if
|
13
|
+
if instance_of?(Dorsale::CustomerVault::Person)
|
14
14
|
# self.abstract_class does not work with STI
|
15
15
|
raise "Cannot directly instantiate Person class"
|
16
16
|
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,51 +26,22 @@ 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
|
|
30
33
|
# Sum of line amounts
|
31
34
|
def total_all_taxes
|
32
|
-
expense_lines.
|
35
|
+
expense_lines.sum(&:total_all_taxes)
|
33
36
|
end
|
34
37
|
|
35
38
|
# Sum of line emplee payback
|
36
39
|
def total_employee_payback
|
37
|
-
expense_lines.
|
40
|
+
expense_lines.sum(&:employee_payback)
|
38
41
|
end
|
39
42
|
|
40
43
|
# Sum of deductible deductible vat
|
41
44
|
def total_vat_deductible
|
42
|
-
expense_lines.
|
43
|
-
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
|
45
|
+
expense_lines.sum(&:total_vat_deductible)
|
73
46
|
end
|
74
47
|
end
|