dorsale 3.14.9 → 3.17.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -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/customer_vault/events_controller.rb +0 -2
  9. data/app/controllers/dorsale/flyboy/task_comments_controller.rb +2 -2
  10. data/app/mailers/dorsale/flyboy/task_mailer.rb +2 -2
  11. data/app/models/dorsale/billing_machine/invoice.rb +2 -4
  12. data/app/models/dorsale/billing_machine/invoice_line.rb +1 -1
  13. data/app/models/dorsale/billing_machine/quotation.rb +1 -2
  14. data/app/models/dorsale/billing_machine/quotation_line.rb +1 -1
  15. data/app/models/dorsale/customer_vault/corporation.rb +11 -2
  16. data/app/models/dorsale/customer_vault/individual.rb +4 -2
  17. data/app/models/dorsale/customer_vault/person.rb +7 -7
  18. data/app/pdfs/dorsale/billing_machine/invoice_single_vat_pdf.rb +2 -2
  19. data/app/policies/dorsale/application_policy.rb +1 -0
  20. data/app/services/dorsale/billing_machine/invoice/copy.rb +1 -0
  21. data/app/services/dorsale/billing_machine/pdf_file_generator.rb +1 -7
  22. data/app/services/dorsale/billing_machine/quotation/copy.rb +1 -0
  23. data/app/services/dorsale/billing_machine/quotation/to_invoice.rb +1 -0
  24. data/app/services/dorsale/expense_gun/expense/copy.rb +1 -0
  25. data/app/services/dorsale/flyboy/task/copy.rb +1 -0
  26. data/app/services/dorsale/flyboy/task/snoozer.rb +1 -0
  27. data/app/services/dorsale/tag_list_for_model.rb +1 -0
  28. data/app/views/dorsale/billing_machine/commons/_form.html.slim +2 -1
  29. data/app/views/dorsale/billing_machine/commons/_line_fields.html.slim +4 -0
  30. data/app/views/dorsale/billing_machine/invoices/show.pdf.ruby +1 -1
  31. data/app/views/dorsale/billing_machine/quotations/show.pdf.ruby +1 -1
  32. data/app/views/dorsale/flyboy/task_mailer/new_task.html.slim +1 -1
  33. data/app/views/dorsale/flyboy/task_mailer/term_email.html.slim +1 -1
  34. data/config/locales/billing_machine.fr.yml +1 -0
  35. data/db/migrate/20210202100529_billing_machine_add_positions.rb +6 -0
  36. data/db/migrate/20210311131928_billing_machine_add_missing_unique_indexes.rb +6 -0
  37. data/features/step_definitions/billing_machine_payment_terms_steps.rb +1 -1
  38. data/features/step_definitions/billing_machine_quotations_steps.rb +1 -1
  39. data/features/step_definitions/customer_vault_activity_types_steps.rb +1 -1
  40. data/features/step_definitions/customer_vault_origins_steps.rb +1 -1
  41. data/features/step_definitions/customer_vault_people_steps.rb +1 -1
  42. data/features/step_definitions/customer_vault_search_steps.rb +10 -10
  43. data/features/step_definitions/expense_gun_categories_steps.rb +1 -1
  44. data/lib/dorsale/version.rb +1 -1
  45. data/spec/controllers/dorsale/flyboy/task_comments_controller_spec.rb +2 -2
  46. data/spec/factories/customer_vault_individuals.rb +13 -13
  47. data/spec/factories/expense_gun_categories.rb +3 -3
  48. data/spec/factories/expense_gun_expense_lines.rb +7 -7
  49. data/spec/factories/expense_gun_expenses.rb +3 -3
  50. data/spec/pdfs/dorsale/billing_machine/invoice_multiple_vat_pdf_spec.rb +1 -1
  51. data/spec/pdfs/dorsale/billing_machine/invoice_single_vat_pdf_spec.rb +1 -1
  52. data/spec/pdfs/dorsale/billing_machine/quotation_multiple_vat_pdf_spec.rb +1 -1
  53. data/spec/pdfs/dorsale/billing_machine/quotation_single_vat_pdf_spec.rb +1 -1
  54. data/spec/rails_helper.rb +0 -1
  55. metadata +5 -21
  56. data/app/assets/javascripts/url.min.js +0 -1
  57. data/app/models/dorsale/customer_vault/corporation_data.rb +0 -10
  58. data/app/models/dorsale/customer_vault/individual_data.rb +0 -3
  59. 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: c02356f6d8c0cf4484b3c5bbf8ae14b4afb5807b79a836c3ac3def7fe4f0d795
4
- data.tar.gz: 10e1416b942207884fc2a84665285e6a5ebb9d73fe5d65a69057f89d05ac75fa
3
+ metadata.gz: edb8363b4a987b737cfba9c432a65fd5c64fbb72690c51f6ea5da99c195430a6
4
+ data.tar.gz: 9b88ffbea03b8971f2a853c5dfcbe6387670ec7b69d8601d68ab295ba425364c
5
5
  SHA512:
6
- metadata.gz: ad1c5adb07688951372ec42e57c85f9487c06257827dcf0e712ab3a87794c9c9ac5e6fe6ba09115fe3813e55ceba36b56dc871729e5aead840b3815af4a8b3a8
7
- data.tar.gz: 90da6df14ad83c78ea0abe031686ea1f9cbbdb3750005c669c19f89875b7ea77a9fce70c4bfbdc9dd7f28e28f95b954ef85395c8422b86148c9bbeefffeeed1d
6
+ metadata.gz: c84800985f5243887825313437907d6a40d2ab5398e7c78de903d404a9c3d5e1d01e6bed9c7cee4fe57f15af26d0aa0c1950ede73946dd3d3f8c14a7ce20a6e1
7
+ data.tar.gz: 373d7d5e133bcb61443e8defed065177fb6e82fc56bc7424abbb110f3632d51a07a24df569f96d2b336206339a2774d26c206d5b1ff6e6862f6d5b63baa061fb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## Next version
4
4
 
5
+ ## 3.17.0
6
+ - Refactor CV models using stores
7
+ - Fix redirect after task comment create
8
+ - Add missing unique indexes on invoices and quotations
9
+
10
+ ## 3.16.0
11
+ - Allow to reorder BM lines (require Sorting.js + reimport migrations)
12
+ - Remove unused url.js
13
+
14
+ ## 3.15.0
15
+ - Fix Ruby 2.7 warnings
16
+ - Faker 2
17
+
18
+ ## 3.14.11
19
+ - Fix BM missing PDFs
20
+
21
+ ## 3.14.10
22
+ - Change BillingMachine PDF filenames
23
+ - Fix CustomerVault layout
24
+
5
25
  ## 3.14.9
6
26
  - Create corporation from individual form
7
27
  - Quotations: add draft state
@@ -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,8 +1,6 @@
1
1
  class Dorsale::CustomerVault::EventsController < ::Dorsale::CustomerVault::ApplicationController
2
2
  before_action :set_objects
3
3
 
4
- layout -> { action_name == "index" ? nil : false }
5
-
6
4
  def index
7
5
  authorize model, :list?
8
6
 
@@ -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
@@ -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
@@ -22,6 +22,8 @@ class Dorsale::BillingMachine::Invoice < ::Dorsale::ApplicationRecord
22
22
  :invoice
23
23
  end
24
24
 
25
+ after_initialize :assign_default_dates
26
+ before_save :update_totals
25
27
  before_create :assign_unique_index
26
28
  before_create :assign_tracking_id
27
29
 
@@ -43,15 +45,11 @@ class Dorsale::BillingMachine::Invoice < ::Dorsale::ApplicationRecord
43
45
  assign_default :paid, false
44
46
  end
45
47
 
46
- after_initialize :assign_default_dates
47
-
48
48
  def assign_default_dates
49
49
  assign_default :date, Date.current
50
50
  assign_default :due_date, Date.current + 30.days
51
51
  end
52
52
 
53
- before_save :update_totals
54
-
55
53
  def update_totals
56
54
  assign_default_values
57
55
  lines.each(&:update_total)
@@ -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
@@ -33,6 +33,7 @@ class Dorsale::BillingMachine::Quotation < ::Dorsale::ApplicationRecord
33
33
  :quotation
34
34
  end
35
35
 
36
+ before_save :update_totals
36
37
  before_create :assign_unique_index
37
38
  before_create :assign_tracking_id
38
39
 
@@ -55,8 +56,6 @@ class Dorsale::BillingMachine::Quotation < ::Dorsale::ApplicationRecord
55
56
  assign_default :total_excluding_taxes, 0
56
57
  end
57
58
 
58
- before_save :update_totals
59
-
60
59
  def update_totals
61
60
  assign_default_values
62
61
  lines.each(&:update_total)
@@ -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
@@ -9,8 +9,6 @@ class Dorsale::CustomerVault::Person < ::Dorsale::ApplicationRecord
9
9
  Dorsale::CustomerVault::PersonPolicy
10
10
  end
11
11
 
12
- after_initialize :verify_class
13
-
14
12
  def verify_class
15
13
  if self.class == ::Dorsale::CustomerVault::Person
16
14
  # self.abstract_class does not work with STI
@@ -30,6 +28,13 @@ class Dorsale::CustomerVault::Person < ::Dorsale::ApplicationRecord
30
28
  belongs_to :activity_type, class_name: "Dorsale::CustomerVault::ActivityType"
31
29
  belongs_to :origin, class_name: "Dorsale::CustomerVault::Origin"
32
30
 
31
+ validate :validate_taken_emails
32
+
33
+ after_initialize :verify_class
34
+ after_initialize :build_address, if: proc { new_record? && address.nil? }
35
+
36
+ before_validation :build_address, if: proc { address.nil? }
37
+
33
38
  after_destroy :destroy_links
34
39
 
35
40
  default_scope -> {
@@ -50,9 +55,6 @@ class Dorsale::CustomerVault::Person < ::Dorsale::ApplicationRecord
50
55
 
51
56
  scope :having_email, -> (email) { where("email = :e OR :e = ANY (secondary_emails)", e: email) }
52
57
 
53
- after_initialize :build_address, if: proc { new_record? && address.nil? }
54
- before_validation :build_address, if: proc { address.nil? }
55
-
56
58
  def taken_emails
57
59
  taken_emails = {}
58
60
  ([email] + secondary_emails).select(&:present?).each do |e|
@@ -62,8 +64,6 @@ class Dorsale::CustomerVault::Person < ::Dorsale::ApplicationRecord
62
64
  taken_emails
63
65
  end
64
66
 
65
- validate :validate_taken_emails
66
-
67
67
  def validate_taken_emails
68
68
  return if taken_emails.empty?
69
69
 
@@ -177,11 +177,11 @@ class Dorsale::BillingMachine::InvoiceSingleVatPdf < Dorsale::ApplicationPdf
177
177
  end
178
178
 
179
179
  def has_advance
180
- main_document.try(:advance) && main_document.advance != 0.0
180
+ main_document.try(:advance) && main_document.advance.to_d != 0.0.to_d
181
181
  end
182
182
 
183
183
  def has_discount
184
- main_document.try(:commercial_discount) && main_document.commercial_discount != 0.0
184
+ main_document.try(:commercial_discount) && main_document.commercial_discount.to_d != 0.0.to_d
185
185
  end
186
186
 
187
187
  def build_table
@@ -19,6 +19,7 @@ class Dorsale::ApplicationPolicy
19
19
  end
20
20
 
21
21
  def self.inherited(klass)
22
+ super(klass)
22
23
  klass.define_subject_accessor!
23
24
  end
24
25
 
@@ -2,6 +2,7 @@ class Dorsale::BillingMachine::Invoice::Copy < ::Dorsale::Service
2
2
  attr_accessor :invoice, :copy
3
3
 
4
4
  def initialize(invoice)
5
+ super()
5
6
  @invoice = invoice
6
7
  end
7
8
 
@@ -2,14 +2,8 @@ class Dorsale::BillingMachine::PdfFileGenerator < Dorsale::Service
2
2
  attr_reader :document
3
3
 
4
4
  def initialize(document)
5
+ super()
5
6
  @document = document
6
-
7
- # I have no idea why I need to do that,
8
- # if I don't do that, CarrierWare do not stores the file.
9
- # The reload() method don't work either.
10
- # The problem appears only on server, not in console.
11
- # I think CarrierWave do not work anymore after first save.
12
- @document = document.class.find(document.id) if document.persisted?
13
7
  end
14
8
 
15
9
  def call
@@ -2,6 +2,7 @@ class Dorsale::BillingMachine::Quotation::Copy < ::Dorsale::Service
2
2
  attr_accessor :quotation, :copy
3
3
 
4
4
  def initialize(quotation)
5
+ super()
5
6
  @quotation = quotation
6
7
  end
7
8
 
@@ -2,6 +2,7 @@ class Dorsale::BillingMachine::Quotation::ToInvoice < ::Dorsale::Service
2
2
  attr_accessor :quotation, :invoice
3
3
 
4
4
  def initialize(quotation)
5
+ super()
5
6
  @quotation = quotation
6
7
  end
7
8
 
@@ -2,6 +2,7 @@ class Dorsale::ExpenseGun::Expense::Copy < ::Dorsale::Service
2
2
  attr_accessor :expense, :copy
3
3
 
4
4
  def initialize(expense)
5
+ super()
5
6
  @expense = expense
6
7
  end
7
8
 
@@ -2,6 +2,7 @@ class Dorsale::Flyboy::Task::Copy < ::Dorsale::Service
2
2
  attr_accessor :task, :copy
3
3
 
4
4
  def initialize(task)
5
+ super()
5
6
  @task = task
6
7
  end
7
8
 
@@ -2,6 +2,7 @@ class Dorsale::Flyboy::Task::Snoozer < ::Dorsale::Service
2
2
  attr_reader :task
3
3
 
4
4
  def initialize(task)
5
+ super()
5
6
  @task = task
6
7
  end
7
8
 
@@ -2,6 +2,7 @@ class Dorsale::TagListForModel < ::Dorsale::Service
2
2
  attr_reader :model
3
3
 
4
4
  def initialize(model)
5
+ super()
5
6
  @model = model
6
7
  end
7
8
 
@@ -21,6 +21,7 @@
21
21
  table#lines-table
22
22
  thead
23
23
  tr
24
+ th.position
24
25
  th.actions
25
26
  th.line-label = Dorsale::BillingMachine::InvoiceLine.t(:label)
26
27
  th.line-quantity = Dorsale::BillingMachine::InvoiceLine.t(:quantity)
@@ -32,7 +33,7 @@
32
33
 
33
34
  tbody
34
35
  = f.simple_fields_for :lines do |lf|
35
- = render "dorsale/billing_machine/invoices/line_fields", f: lf
36
+ = render "dorsale/billing_machine/#{document.document_type}s/line_fields", f: lf
36
37
 
37
38
  .row
38
39
  .col-sm-6
@@ -1,4 +1,8 @@
1
1
  tr.line
2
+ td.position
3
+ = icon(:arrows_alt, class: "handle")
4
+ = f.hidden_field :position
5
+
2
6
  td.actions
3
7
  a.delete href="#"
4
8
  span.fa.fa-fw.fa-trash
@@ -1,7 +1,7 @@
1
1
  filename = [
2
2
  @invoice.t.capitalize,
3
3
  @invoice.tracking_id,
4
- @invoice.customer.try(:short_name),
4
+ @invoice.customer.to_s.tr(" ", "_"),
5
5
  ].join("_").concat(".pdf")
6
6
 
7
7
  response.headers["Content-Disposition"] = %(inline; filename="#{filename}")
@@ -1,7 +1,7 @@
1
1
  filename = [
2
2
  @quotation.t.capitalize,
3
3
  @quotation.tracking_id,
4
- @quotation.customer.try(:short_name),
4
+ @quotation.customer.to_s.tr(" ", "_"),
5
5
  ].join("_").concat(".pdf")
6
6
 
7
7
  response.headers["Content-Disposition"] = %(inline; filename="#{filename}")
@@ -1 +1 @@
1
- p == lf2br t("task_mailer.new_task.body", @locals)
1
+ p == lf2br t("task_mailer.new_task.body", **@locals)
@@ -1 +1 @@
1
- p == lf2br t("task_mailer.term_email.body", @locals)
1
+ p == lf2br t("task_mailer.term_email.body", **@locals)
@@ -25,6 +25,7 @@ fr:
25
25
  expires_at: "Date d'expiration"
26
26
  balance: "Reste à payer"
27
27
  pdf_file: "Fichier PDF"
28
+ position: "Position"
28
29
 
29
30
  activerecord:
30
31
  models:
@@ -0,0 +1,6 @@
1
+ class BillingMachineAddPositions < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_column :dorsale_billing_machine_invoice_lines, :position, :integer, null: false, default: 0
4
+ add_column :dorsale_billing_machine_quotation_lines, :position, :integer, null: false, default: 0
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ class BillingMachineAddMissingUniqueIndexes < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_index :dorsale_billing_machine_invoices, :unique_index, unique: true
4
+ add_index :dorsale_billing_machine_quotations, :unique_index, unique: true
5
+ end
6
+ end
@@ -28,7 +28,7 @@ When(/^the user edits the payment_term$/) do
28
28
  find(".link_update").click
29
29
  end
30
30
 
31
- Then(/^the current payment_term's label should be pre\-filled$/) do
31
+ Then(/^the current payment_term's label should be pre-filled$/) do
32
32
  expect(page).to have_field("billing_machine_payment_term_label", with: @payment_term.label)
33
33
  end
34
34
 
@@ -58,7 +58,7 @@ When(/^the quotation line shows the right date$/) do
58
58
  expect(page).to have_selector ".date", text: I18n.l(@quotation.date)
59
59
  end
60
60
 
61
- When(/^the quotation line shows the right traking\-id$/) do
61
+ When(/^the quotation line shows the right traking-id$/) do
62
62
  expect(page).to have_selector ".tracking_id", text: @quotation.tracking_id
63
63
  end
64
64
 
@@ -28,7 +28,7 @@ When(/^I edit the activity type$/) do
28
28
  find(".link_update").click
29
29
  end
30
30
 
31
- Then(/^the current activity type's name should be pre\-filled$/) do
31
+ Then(/^the current activity type's name should be pre-filled$/) do
32
32
  expect(page).to have_field("activity_type_name", with: @activity_type.name)
33
33
  end
34
34
 
@@ -28,7 +28,7 @@ When(/^I edit the origin$/) do
28
28
  find(".link_update").click
29
29
  end
30
30
 
31
- Then(/^the current origin's name should be pre\-filled$/) do
31
+ Then(/^the current origin's name should be pre-filled$/) do
32
32
  expect(page).to have_field("origin_name", with: @origin.name)
33
33
  end
34
34
 
@@ -7,7 +7,7 @@ Then(/^the file is downloaded$/) do
7
7
  end
8
8
 
9
9
  Given(/^a very long comment on this person$/) do
10
- text = Faker::Lorem.paragraph(30)
10
+ text = Faker::Lorem.paragraph(sentence_count: 30)
11
11
  @comment = create(:customer_vault_event_comment, person: @person, text: text)
12
12
  end
13
13
 
@@ -1,48 +1,48 @@
1
- Lorsqu(/^he go to the people list$/) do
1
+ When(/^he go to the people list$/) do
2
2
  visit dorsale.customer_vault_people_path
3
3
  end
4
4
 
5
- Etantdonné(/^existing individuals$/) do
5
+ Given(/^existing individuals$/) do
6
6
  @individual1 = create(:customer_vault_individual, first_name: "Jean", last_name: "DUPONT")
7
7
  @individual2 = create(:customer_vault_individual, first_name: "Laurent", last_name: "DURAND")
8
8
  end
9
9
 
10
- Etantdonné(/^existing corporations$/) do
10
+ Given(/^existing corporations$/) do
11
11
  @corporation1 = create(:customer_vault_corporation, name: "aaa", email: "contact@aaa.com")
12
12
  @corporation2 = create(:customer_vault_corporation, name: "zzz", email: "contact@zzz.com")
13
13
  end
14
14
 
15
- Lorsqu(/^he search an individual by first name$/) do
15
+ When(/^he search an individual by first name$/) do
16
16
  fill_in "q", with: "Jean"
17
17
  find(".search-submit").click
18
18
  end
19
19
 
20
- Alors(/^this individual appear in search results$/) do
20
+ Then(/^this individual appear in search results$/) do
21
21
  expect(page).to have_content "Jean"
22
22
  expect(page).to have_content "DUPONT"
23
23
  end
24
24
 
25
- Alors(/^other individuals do not appear in search results$/) do
25
+ Then(/^other individuals do not appear in search results$/) do
26
26
  expect(page).to have_no_content "Laurent"
27
27
  expect(page).to have_no_content "DURAND"
28
28
  end
29
29
 
30
- Lorsqu(/^he search an individual by last name$/) do
30
+ When(/^he search an individual by last name$/) do
31
31
  fill_in "q", with: "DUPONT"
32
32
  find(".search-submit").click
33
33
  end
34
34
 
35
- Lorsqu(/^he search a corporation by name$/) do
35
+ When(/^he search a corporation by name$/) do
36
36
  fill_in "q", with: "aaa"
37
37
  find(".search-submit").click
38
38
  end
39
39
 
40
- Alors(/^this corporation appear in search results$/) do
40
+ Then(/^this corporation appear in search results$/) do
41
41
  expect(page).to have_content "aaa"
42
42
  expect(page).to have_content "contact@aaa.com"
43
43
  end
44
44
 
45
- Alors(/^other corporations do not appear in search results$/) do
45
+ Then(/^other corporations do not appear in search results$/) do
46
46
  expect(page).to have_no_content "zzz"
47
47
  expect(page).to have_no_content "contact@zzz.com"
48
48
  end
@@ -28,7 +28,7 @@ When(/^I edit the expense category$/) do
28
28
  find(".link_update").click
29
29
  end
30
30
 
31
- Then(/^the current expense category's label should be pre\-filled$/) do
31
+ Then(/^the current expense category's label should be pre-filled$/) do
32
32
  expect(page).to have_field("category_name", with: @category.name)
33
33
  end
34
34
 
@@ -1,3 +1,3 @@
1
1
  module Dorsale
2
- VERSION = "3.14.9"
2
+ VERSION = "3.17.0"
3
3
  end
@@ -18,7 +18,7 @@ describe Dorsale::Flyboy::TaskCommentsController, type: :controller do
18
18
  expect(assigns(:task_comment).persisted?).to be true
19
19
  end
20
20
 
21
- it "should redirect to referrer if referrer is task" do
21
+ it "should redirect to referrer if referrer is task show" do
22
22
  url = flyboy_task_path(task) + "?sort=xxx"
23
23
  request.env["HTTP_REFERER"] = url
24
24
  post :create, params: valid_params
@@ -26,7 +26,7 @@ describe Dorsale::Flyboy::TaskCommentsController, type: :controller do
26
26
  end
27
27
 
28
28
  it "should redirect to task if referrer is not task" do
29
- url = "/anywhere"
29
+ url = flyboy_task_path(task) + "/some-action"
30
30
  request.env["HTTP_REFERER"] = url
31
31
  post :create, params: valid_params
32
32
  expect(response).to redirect_to flyboy_task_path(task)
@@ -1,17 +1,17 @@
1
1
  FactoryBot.define do
2
2
  factory :customer_vault_individual, class: ::Dorsale::CustomerVault::Individual do
3
- origin { create(:customer_vault_origin) }
4
- first_name { Faker::Name.first_name }
5
- last_name { Faker::Name.last_name }
6
- short_name { "SN" }
7
- email { Faker::Internet.email("#{first_name} #{last_name}") }
8
- title { "Individual-Title" }
9
- twitter { "#{first_name}#{last_name}" }
10
- www { Faker::Internet.url }
11
- context { "Individual-Context" }
12
- phone { "01 23 xx xx xx" }
13
- fax { "09 xx xx xx xx" }
14
- mobile { "06 xx xx xx xx" }
15
- address { build(:dorsale_address) }
3
+ origin { create(:customer_vault_origin) }
4
+ first_name { Faker::Name.first_name }
5
+ last_name { Faker::Name.last_name }
6
+ short_name { "SN" }
7
+ email { Faker::Internet.email(name: name) }
8
+ title { "Individual-Title" }
9
+ twitter { "#{first_name}#{last_name}" }
10
+ www { Faker::Internet.url }
11
+ context { "Individual-Context" }
12
+ phone { "01 23 xx xx xx" }
13
+ fax { "09 xx xx xx xx" }
14
+ mobile { "06 xx xx xx xx" }
15
+ address { build(:dorsale_address) }
16
16
  end
17
17
  end
@@ -1,7 +1,7 @@
1
1
  FactoryBot.define do
2
2
  factory :expense_gun_category, class: ::Dorsale::ExpenseGun::Category do
3
- name { Faker::Lorem.word }
4
- code { Faker::Number.number(4) }
5
- vat_deductible { [true, false].sample }
3
+ name { Faker::Lorem.word }
4
+ code { Faker::Number.number(digits: 4) }
5
+ vat_deductible { [true, false].sample }
6
6
  end
7
7
  end
@@ -1,11 +1,11 @@
1
1
  FactoryBot.define do
2
2
  factory :expense_gun_expense_line, class: ::Dorsale::ExpenseGun::ExpenseLine do
3
- expense { build(:expense_gun_expense) }
4
- name { Faker::Lorem.sentence(3) }
5
- category { build(:expense_gun_category) }
6
- date { Faker::Date.backward(30) }
7
- total_all_taxes { rand(100..1000) }
8
- vat { rand(1..(total_all_taxes/5)) }
9
- company_part { [25, 50, 75, 100].sample }
3
+ expense { build(:expense_gun_expense) }
4
+ name { Faker::Lorem.sentence(word_count: 3) }
5
+ category { build(:expense_gun_category) }
6
+ date { Faker::Date.backward(days: 30) }
7
+ total_all_taxes { rand(100..1000) }
8
+ vat { rand(1..(total_all_taxes/5)) }
9
+ company_part { [25, 50, 75, 100].sample }
10
10
  end
11
11
  end
@@ -1,8 +1,8 @@
1
1
  FactoryBot.define do
2
2
  factory :expense_gun_expense, class: ::Dorsale::ExpenseGun::Expense do
3
- name { Faker::Lorem.sentence(3) }
4
- date { Date.current }
5
- user { create(:user) }
3
+ name { Faker::Lorem.sentence(word_count: 3) }
4
+ date { Date.current }
5
+ user { create(:user) }
6
6
 
7
7
  after(:create) { |expense|
8
8
  rand(2..5).times {
@@ -23,7 +23,7 @@ describe ::Dorsale::BillingMachine::InvoiceMultipleVatPdf, pdfs: true do
23
23
 
24
24
  let(:content) {
25
25
  generate!
26
- Yomu.new(invoice.pdf_file.path).text
26
+ PDF::Reader.new(invoice.pdf_file.path).pages.map(&:text).join("\n")
27
27
  }
28
28
 
29
29
  it "should not display global vat rate" do
@@ -23,7 +23,7 @@ describe ::Dorsale::BillingMachine::InvoiceSingleVatPdf, pdfs: true do
23
23
 
24
24
  let(:content) {
25
25
  generate!
26
- Yomu.new(invoice.pdf_file.path).text
26
+ PDF::Reader.new(invoice.pdf_file.path).pages.map(&:text).join("\n")
27
27
  }
28
28
 
29
29
  it "should display global vat rate" do
@@ -23,7 +23,7 @@ describe ::Dorsale::BillingMachine::QuotationMultipleVatPdf, pdfs: true do
23
23
 
24
24
  let(:content) {
25
25
  generate!
26
- Yomu.new(quotation.pdf_file.path).text
26
+ PDF::Reader.new(quotation.pdf_file.path).pages.map(&:text).join("\n")
27
27
  }
28
28
 
29
29
  it "should not display global vat rate" do
@@ -23,7 +23,7 @@ describe ::Dorsale::BillingMachine::QuotationSingleVatPdf, pdfs: true do
23
23
 
24
24
  let(:content) {
25
25
  generate!
26
- Yomu.new(quotation.pdf_file.path).text
26
+ PDF::Reader.new(quotation.pdf_file.path).pages.map(&:text).join("\n")
27
27
  }
28
28
 
29
29
  it "should display global vat rate" do
data/spec/rails_helper.rb CHANGED
@@ -4,7 +4,6 @@ require 'spec_helper'
4
4
  require File.expand_path("../dummy/config/environment", __FILE__)
5
5
  require 'rspec/rails'
6
6
  require "agilibox/rspec"
7
- require "yomu"
8
7
  # Add additional requires below this line. Rails is not loaded until this point!
9
8
  # Requires supporting ruby files with custom matchers and macros, etc,
10
9
  # in spec/support/ and its subdirectories.
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.14.9
4
+ version: 3.17.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: 2020-08-12 00:00:00.000000000 Z
11
+ date: 2021-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -50,20 +50,6 @@ dependencies:
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '99'
53
- - !ruby/object:Gem::Dependency
54
- name: virtus
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "<"
58
- - !ruby/object:Gem::Version
59
- version: '99'
60
- type: :runtime
61
- prerelease: false
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - "<"
65
- - !ruby/object:Gem::Version
66
- version: '99'
67
53
  - !ruby/object:Gem::Dependency
68
54
  name: slim-rails
69
55
  requirement: !ruby/object:Gem::Requirement
@@ -468,7 +454,6 @@ files:
468
454
  - app/assets/javascripts/dorsale/engines/billing_machine.coffee.erb
469
455
  - app/assets/javascripts/dorsale/engines/customer_vault.coffee
470
456
  - app/assets/javascripts/dorsale/engines/flyboy.coffee
471
- - app/assets/javascripts/url.min.js
472
457
  - app/assets/stylesheets/dorsale/all.sass
473
458
  - app/assets/stylesheets/dorsale/common.sass
474
459
  - app/assets/stylesheets/dorsale/common/comments.sass
@@ -550,14 +535,11 @@ files:
550
535
  - app/models/dorsale/customer_vault.rb
551
536
  - app/models/dorsale/customer_vault/activity_type.rb
552
537
  - app/models/dorsale/customer_vault/corporation.rb
553
- - app/models/dorsale/customer_vault/corporation_data.rb
554
538
  - app/models/dorsale/customer_vault/event.rb
555
539
  - app/models/dorsale/customer_vault/individual.rb
556
- - app/models/dorsale/customer_vault/individual_data.rb
557
540
  - app/models/dorsale/customer_vault/link.rb
558
541
  - app/models/dorsale/customer_vault/origin.rb
559
542
  - app/models/dorsale/customer_vault/person.rb
560
- - app/models/dorsale/customer_vault/person_data.rb
561
543
  - app/models/dorsale/email.rb
562
544
  - app/models/dorsale/expense_gun.rb
563
545
  - app/models/dorsale/expense_gun/category.rb
@@ -835,6 +817,8 @@ files:
835
817
  - db/migrate/20171023133219_customer_vault_events_add_contact_type.rb
836
818
  - db/migrate/20171024075514_customer_vault_contact_type_default_value.rb
837
819
  - db/migrate/20171115171425_dorsale_customer_vault_people_add_secondary_emails.rb
820
+ - db/migrate/20210202100529_billing_machine_add_positions.rb
821
+ - db/migrate/20210311131928_billing_machine_add_missing_unique_indexes.rb
838
822
  - features/access.feature
839
823
  - features/billing_machine_invoices.feature
840
824
  - features/billing_machine_multiple_vat.feature
@@ -989,7 +973,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
989
973
  - !ruby/object:Gem::Version
990
974
  version: '0'
991
975
  requirements: []
992
- rubygems_version: 3.0.3
976
+ rubygems_version: 3.1.4
993
977
  signing_key:
994
978
  specification_version: 4
995
979
  summary: Modular ERP made with Ruby on Rails
@@ -1 +0,0 @@
1
- /*! js-url - v2.3.0 - 2016-03-10 */window.url=function(){function a(){}function b(a){return decodeURIComponent(a.replace(/\+/g," "))}function c(a,b){var c=a.charAt(0),d=b.split(c);return c===a?d:(a=parseInt(a.substring(1),10),d[0>a?d.length+a:a-1])}function d(a,c){for(var d=a.charAt(0),e=c.split("&"),f=[],g={},h=[],i=a.substring(1),j=0,k=e.length;k>j;j++)if(f=e[j].match(/(.*?)=(.*)/),f||(f=[e[j],e[j],""]),""!==f[1].replace(/\s/g,"")){if(f[2]=b(f[2]||""),i===f[1])return f[2];h=f[1].match(/(.*)\[([0-9]+)\]/),h?(g[h[1]]=g[h[1]]||[],g[h[1]][h[2]]=f[2]):g[f[1]]=f[2]}return d===a?g:g[i]}return function(b,e){var f,g={};if("tld?"===b)return a();if(e=e||window.location.toString(),!b)return e;if(b=b.toString(),f=e.match(/^mailto:([^\/].+)/))g.protocol="mailto",g.email=f[1];else{if((f=e.match(/(.*?)\/#\!(.*)/))&&(e=f[1]+f[2]),(f=e.match(/(.*?)#(.*)/))&&(g.hash=f[2],e=f[1]),g.hash&&b.match(/^#/))return d(b,g.hash);if((f=e.match(/(.*?)\?(.*)/))&&(g.query=f[2],e=f[1]),g.query&&b.match(/^\?/))return d(b,g.query);if((f=e.match(/(.*?)\:?\/\/(.*)/))&&(g.protocol=f[1].toLowerCase(),e=f[2]),(f=e.match(/(.*?)(\/.*)/))&&(g.path=f[2],e=f[1]),g.path=(g.path||"").replace(/^([^\/])/,"/$1").replace(/\/$/,""),b.match(/^[\-0-9]+$/)&&(b=b.replace(/^([^\/])/,"/$1")),b.match(/^\//))return c(b,g.path.substring(1));if(f=c("/-1",g.path.substring(1)),f&&(f=f.match(/(.*?)\.(.*)/))&&(g.file=f[0],g.filename=f[1],g.fileext=f[2]),(f=e.match(/(.*)\:([0-9]+)$/))&&(g.port=f[2],e=f[1]),(f=e.match(/(.*?)@(.*)/))&&(g.auth=f[1],e=f[2]),g.auth&&(f=g.auth.match(/(.*)\:(.*)/),g.user=f?f[1]:g.auth,g.pass=f?f[2]:void 0),g.hostname=e.toLowerCase(),"."===b.charAt(0))return c(b,g.hostname);a()&&(f=g.hostname.match(a()),f&&(g.tld=f[3],g.domain=f[2]?f[2]+"."+f[3]:void 0,g.sub=f[1]||void 0)),g.port=g.port||("https"===g.protocol?"443":"80"),g.protocol=g.protocol||("443"===g.port?"https":"http")}return b in g?g[b]:"{}"===b?g:void 0}}(),"undefined"!=typeof jQuery&&jQuery.extend({url:function(a,b){return window.url(a,b)}});
@@ -1,10 +0,0 @@
1
- class Dorsale::CustomerVault::CorporationData < Dorsale::CustomerVault::PersonData
2
- attribute :legal_form, String
3
- attribute :immatriculation_number, String
4
- attribute :naf, String
5
- attribute :european_union_vat_number, String
6
- attribute :societe_com, String
7
- attribute :capital, Integer
8
- attribute :revenue, Integer
9
- attribute :number_of_employees, Integer
10
- end
@@ -1,3 +0,0 @@
1
- class Dorsale::CustomerVault::IndividualData < Dorsale::CustomerVault::PersonData
2
- attribute :title, String
3
- end
@@ -1,17 +0,0 @@
1
- require "virtus"
2
-
3
- class Dorsale::CustomerVault::PersonData
4
- include Virtus.model
5
-
6
- def self.dump(obj)
7
- JSON.dump(obj.attributes)
8
- end
9
-
10
- def self.load(json_string)
11
- new JSON.parse(json_string.presence || "{}")
12
- end
13
-
14
- def self.methods_to_delegate
15
- instance_methods - Dorsale::CustomerVault::PersonData.instance_methods
16
- end
17
- end