dorsale 3.14.11 → 3.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/app/assets/javascripts/dorsale/dependencies.coffee +1 -1
  4. data/app/assets/javascripts/dorsale/engines/billing_machine.coffee.erb +14 -0
  5. data/app/assets/stylesheets/dorsale/engines/billing_machine.sass +4 -1
  6. data/app/controllers/dorsale/billing_machine/invoices_controller.rb +14 -9
  7. data/app/controllers/dorsale/billing_machine/quotations_controller.rb +14 -9
  8. data/app/controllers/dorsale/expense_gun/expenses_controller.rb +24 -34
  9. data/app/controllers/dorsale/flyboy/task_comments_controller.rb +2 -2
  10. data/app/filters/dorsale/expense_gun/small_data/filter_for_expenses.rb +5 -2
  11. data/app/helpers/dorsale/expense_gun/application_helper.rb +1 -1
  12. data/app/mailers/dorsale/flyboy/task_mailer.rb +2 -2
  13. data/app/models/dorsale/billing_machine/invoice.rb +2 -4
  14. data/app/models/dorsale/billing_machine/invoice_line.rb +1 -1
  15. data/app/models/dorsale/billing_machine/quotation.rb +1 -1
  16. data/app/models/dorsale/billing_machine/quotation_line.rb +1 -1
  17. data/app/models/dorsale/customer_vault/corporation.rb +11 -2
  18. data/app/models/dorsale/customer_vault/individual.rb +4 -2
  19. data/app/models/dorsale/customer_vault/person.rb +1 -1
  20. data/app/models/dorsale/expense_gun/expense.rb +7 -34
  21. data/app/policies/dorsale/expense_gun/expense_policy_helper.rb +9 -20
  22. data/app/services/dorsale/flyboy/task/snoozer.rb +1 -1
  23. data/app/sorters/dorsale/expense_gun/expenses_sorter.rb +8 -0
  24. data/app/uploaders/dorsale/image_uploader.rb +1 -1
  25. data/app/uploaders/dorsale/pdf_uploader.rb +1 -1
  26. data/app/views/dorsale/billing_machine/commons/_form.html.slim +2 -1
  27. data/app/views/dorsale/billing_machine/commons/_line_fields.html.slim +4 -0
  28. data/app/views/dorsale/expense_gun/expenses/_filters.html.slim +8 -0
  29. data/app/views/dorsale/expense_gun/expenses/_form.html.slim +3 -4
  30. data/app/views/dorsale/expense_gun/expenses/_list.html.slim +62 -20
  31. data/app/views/dorsale/expense_gun/expenses/_show_actions.html.slim +2 -12
  32. data/app/views/dorsale/expense_gun/expenses/_state_actions.html.slim +8 -0
  33. data/app/views/dorsale/expense_gun/expenses/index.html.slim +1 -1
  34. data/app/views/dorsale/flyboy/task_mailer/new_task.html.slim +1 -1
  35. data/app/views/dorsale/flyboy/task_mailer/term_email.html.slim +1 -1
  36. data/config/locales/billing_machine.fr.yml +1 -0
  37. data/config/locales/expense_gun.fr.yml +12 -10
  38. data/config/routes.rb +3 -4
  39. data/db/migrate/20210202100529_billing_machine_add_positions.rb +6 -0
  40. data/db/migrate/20210311131928_billing_machine_add_missing_unique_indexes.rb +6 -0
  41. data/db/migrate/20210506070548_expenses_change_states.rb +7 -0
  42. data/features/expense_gun_expenses.feature +0 -30
  43. data/features/step_definitions/customer_vault_people_steps.rb +1 -1
  44. data/features/step_definitions/expense_gun_expenses_steps.rb +1 -16
  45. data/lib/dorsale/engine.rb +0 -1
  46. data/lib/dorsale/version.rb +1 -1
  47. data/spec/controllers/dorsale/expense_gun/expenses_controller_spec.rb +66 -17
  48. data/spec/controllers/dorsale/flyboy/task_comments_controller_spec.rb +2 -2
  49. data/spec/factories/customer_vault_individuals.rb +13 -13
  50. data/spec/factories/expense_gun_categories.rb +3 -3
  51. data/spec/factories/expense_gun_expense_lines.rb +7 -7
  52. data/spec/factories/expense_gun_expenses.rb +3 -3
  53. data/spec/models/dorsale/expense_gun/expense_spec.rb +1 -125
  54. data/spec/pdfs/dorsale/billing_machine/invoice_multiple_vat_pdf_spec.rb +1 -1
  55. data/spec/pdfs/dorsale/billing_machine/invoice_single_vat_pdf_spec.rb +1 -1
  56. data/spec/pdfs/dorsale/billing_machine/quotation_multiple_vat_pdf_spec.rb +1 -1
  57. data/spec/pdfs/dorsale/billing_machine/quotation_single_vat_pdf_spec.rb +1 -1
  58. data/spec/rails_helper.rb +0 -1
  59. data/spec/routing/dorsale/expense_gun/expenses_routing_spec.rb +9 -14
  60. data/spec/services/dorsale/expense_gun/expense/copy_spec.rb +2 -2
  61. data/spec/sorters/dorsale/expense_gun/expenses_sorter_spec.rb +20 -0
  62. metadata +10 -35
  63. data/app/assets/javascripts/url.min.js +0 -1
  64. data/app/models/dorsale/customer_vault/corporation_data.rb +0 -10
  65. data/app/models/dorsale/customer_vault/individual_data.rb +0 -3
  66. 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: 6866c7560ef92fbd39d25e808a3839c2cd2cebc74f96032e822ec91da2d15d22
4
- data.tar.gz: 178783cfc18bcd2e657679d8aba7d03c03f5a1576d89c36811767fdf10d4d2a0
3
+ metadata.gz: 86af52038f7c9cfc24b17dbcf5229608296a7152f2e4565d3fd415d2dd88ce87
4
+ data.tar.gz: cd7c59ee287a99e1cac77068550f7a0d64451e164cb2e10855fd1dd2d9b5fb12
5
5
  SHA512:
6
- metadata.gz: 7c13fd4a88831a65793b92a20fe25008e53313d80c05e94cf10b96b12b5b15e315e679b00177f96f700028b9b7bcecbf361cb0e25d7196d2e6d6ab78e91cdaab
7
- data.tar.gz: ab777662670e599361601e3e4a052785f9208835b2170232e6da9fd72c74e7d6dbb99a2b65828d5432ff4df843370cc3ba908aee85d8f8f1c81ca0c1a4da9355
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()
@@ -103,11 +103,14 @@
103
103
 
104
104
  th.actions,
105
105
  td.actions,
106
+ th.position,
107
+ td.position,
106
108
  padding: 0
107
109
  width: 2.5em
108
110
  text-align: center
109
111
 
110
- th.actions
112
+ th.actions,
113
+ th.position,
111
114
  border: none
112
115
 
113
116
  // disabled fields
@@ -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
- :_destroy,
162
- :id,
163
- :label,
164
- :quantity,
165
- :unit,
166
- :unit_price,
167
- :vat_rate,
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
- :_destroy,
170
- :id,
171
- :label,
172
- :quantity,
173
- :unit,
174
- :unit_price,
175
- :vat_rate,
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, only: [
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
- flash[:success] = t("expense_gun.expense.messages.created")
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
- flash[:success] = t("expense_gun.expense.messages.updated")
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 submit
75
- authorize @expense, :submit?
67
+ def go_to_pending
68
+ authorize @expense, :go_to_pending?
76
69
 
77
- @expense.go_to_submitted!
78
- flash[:success] = t("expense_gun.expense.messages.submitted")
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 accept
83
- authorize @expense, :accept?
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
- def refuse
91
- authorize @expense, :refuse?
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 cancel
99
- authorize @expense, :cancel?
83
+ def go_to_canceled
84
+ authorize @expense, :go_to_canceled?
100
85
 
101
- @expense.go_to_canceled!
102
- flash[:success] = t("expense_gun.expense.messages.canceled")
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.to_s.start_with?(task_path)
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" => ::Agilibox::SmallData::FilterStrategyByKeyValue.new("state"),
4
- "expense_user_id" => ::Agilibox::SmallData::FilterStrategyByKeyValue.new("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,6 @@
1
1
  module Dorsale::ExpenseGun::ApplicationHelper
2
2
  def expense_states_for_filters_select
3
- Dorsale::ExpenseGun::Expense.aasm.states.map do |state|
3
+ Dorsale::ExpenseGun::Expense::STATES.map do |state|
4
4
  [
5
5
  Dorsale::ExpenseGun::Expense.t("state.#{state}"),
6
6
  state,
@@ -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", @locals),
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", @locals),
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.map(&:total).sum.round(2)
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
@@ -6,7 +6,7 @@ class Dorsale::BillingMachine::InvoiceLine < ::Dorsale::ApplicationRecord
6
6
  validates :invoice, presence: true
7
7
 
8
8
  default_scope -> {
9
- order(created_at: :asc)
9
+ order(position: :asc, created_at: :asc, id: :asc)
10
10
  }
11
11
 
12
12
  before_validation :update_total
@@ -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.map(&:total).sum
64
+ lines_sum = lines.sum(&:total)
65
65
 
66
66
  self.total_excluding_taxes = lines_sum - commercial_discount
67
67
 
@@ -6,7 +6,7 @@ class Dorsale::BillingMachine::QuotationLine < ::Dorsale::ApplicationRecord
6
6
  validates :quotation, presence: true
7
7
 
8
8
  default_scope -> {
9
- order(:created_at => :asc)
9
+ order(position: :asc, created_at: :asc, id: :asc)
10
10
  }
11
11
 
12
12
  before_validation :update_total
@@ -1,6 +1,15 @@
1
1
  class Dorsale::CustomerVault::Corporation < Dorsale::CustomerVault::Person
2
- serialize :data, Dorsale::CustomerVault::CorporationData
3
- def_delegators :data, *Dorsale::CustomerVault::CorporationData.methods_to_delegate
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
- serialize :data, Dorsale::CustomerVault::IndividualData
3
- def_delegators :data, *Dorsale::CustomerVault::IndividualData.methods_to_delegate
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 self.class == ::Dorsale::CustomerVault::Person
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
- include AASM
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.map(&:total_all_taxes).sum
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.map(&:employee_payback).sum
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.map(&:total_vat_deductible).sum
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