diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1a63ee7..f7e066533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog Fab-manager +## v5.9.1 2023 March 22 + +- Fix a bug: logical sequence of invoices references has duplicates +- Fix a bug: in some cases, unable to export to excel files +- Fix a security issue: updated rack to 2.2.6.4 to fix [CVE-2023-27539](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-27539) + ## v5.9.0 2023 March 20 - Ability to restrict machine reservations per plan diff --git a/Gemfile.lock b/Gemfile.lock index e15107497..43a951841 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -299,7 +299,7 @@ GEM activesupport (>= 3.0.0) raabro (1.4.0) racc (1.6.1) - rack (2.2.6.3) + rack (2.2.6.4) rack-oauth2 (1.19.0) activesupport attr_required diff --git a/app/frontend/src/javascript/controllers/trainings.js.erb b/app/frontend/src/javascript/controllers/trainings.js.erb index 79979fdd6..929e56148 100644 --- a/app/frontend/src/javascript/controllers/trainings.js.erb +++ b/app/frontend/src/javascript/controllers/trainings.js.erb @@ -135,13 +135,13 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$tra // the moment when the slot selection changed for the last time, used to trigger changes in the cart $scope.selectionTime = null; - // the last clicked event in the calender + // the last clicked event in the calendar $scope.selectedEvent = null; // indicates the state of the current view : calendar or plans information $scope.plansAreShown = false; - // will store the user's plan if he choosed to buy one + // will store the user's plan if he chose to buy one $scope.selectedPlan = null; // the moment when the plan selection changed for the last time, used to trigger changes in the cart diff --git a/app/models/availability.rb b/app/models/availability.rb index 99073d410..e81f9c41e 100644 --- a/app/models/availability.rb +++ b/app/models/availability.rb @@ -41,6 +41,9 @@ class Availability < ApplicationRecord validate :length_must_be_slot_multiple, unless: proc { end_at.blank? or start_at.blank? } validate :should_be_associated + # cache + after_update :refresh_places_cache + ## elastic callbacks after_save { AvailabilityIndexerWorker.perform_async(:index, id) } after_destroy { AvailabilityIndexerWorker.perform_async(:delete, id) } @@ -128,7 +131,7 @@ class Availability < ApplicationRecord slots.map(&:reserved_users).flatten end - # @param user [User] + # @param user_id [Integer] # @return [Boolean] def reserved_by?(user_id) reserved_users.include?(user_id) @@ -195,4 +198,10 @@ class Availability < ApplicationRecord errors.add(:machine_ids, I18n.t('availabilities.must_be_associated_with_at_least_1_machine')) end + + def refresh_places_cache + slots.each do |slot| + Slots::PlacesCacheService.refresh(slot) + end + end end diff --git a/app/models/avoir.rb b/app/models/avoir.rb index 7a505aaea..7c731e69f 100644 --- a/app/models/avoir.rb +++ b/app/models/avoir.rb @@ -14,10 +14,6 @@ class Avoir < Invoice delegate :order_number, to: :invoice - def generate_reference - super(created_at) - end - def expire_subscription user.subscription.expire end diff --git a/app/models/footprintable.rb b/app/models/footprintable.rb index 7f6060fda..e5b09a3be 100644 --- a/app/models/footprintable.rb +++ b/app/models/footprintable.rb @@ -34,8 +34,6 @@ class Footprintable < ApplicationRecord FootprintService.debug_footprint(self.class, self) end - #protected - def compute_footprint FootprintService.compute_footprint(self.class, self) end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index a8a54844f..75e7ad3f8 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -50,11 +50,9 @@ class Invoice < PaymentDocument end def order_number - return order.reference unless order.nil? + return order.reference unless order.nil? || order.reference.nil? - if !payment_schedule_item.nil? && !payment_schedule_item.first? - return payment_schedule_item.payment_schedule.ordered_items.first.invoice.order_number - end + return payment_schedule_item.payment_schedule.order_number if !payment_schedule_item.nil? && !payment_schedule_item.first? PaymentDocumentService.generate_order_number(self) end diff --git a/app/models/order.rb b/app/models/order.rb index 037e69a70..a2000fdc1 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -20,6 +20,8 @@ class Order < PaymentDocument delegate :user, to: :statistic_profile + alias_attribute :order_number, :reference + def generate_reference(_date = Time.current) self.reference = PaymentDocumentService.generate_order_number(self) end diff --git a/app/models/payment_document.rb b/app/models/payment_document.rb index 66ce36af6..56016867e 100644 --- a/app/models/payment_document.rb +++ b/app/models/payment_document.rb @@ -4,7 +4,7 @@ class PaymentDocument < Footprintable self.abstract_class = true - def generate_reference(date = Time.current) + def generate_reference(date = created_at) self.reference = PaymentDocumentService.generate_reference(self, date: date) end diff --git a/app/models/payment_schedule.rb b/app/models/payment_schedule.rb index 43e36596c..b6096fa80 100644 --- a/app/models/payment_schedule.rb +++ b/app/models/payment_schedule.rb @@ -38,6 +38,10 @@ class PaymentSchedule < PaymentDocument "#{prefix}-#{id}_#{created_at.strftime('%d%m%Y')}.pdf" end + def order_number + ordered_items.first&.invoice&.order_number || PaymentDocumentService.generate_order_number(self) + end + ## # This is useful to check the first item because its amount may be different from the others ## diff --git a/app/models/statistic_type.rb b/app/models/statistic_type.rb index 58a016ae8..d0b44526d 100644 --- a/app/models/statistic_type.rb +++ b/app/models/statistic_type.rb @@ -1,6 +1,10 @@ +# frozen_string_literal: true + +# Allows splinting a StatisticIndex into multiple types. +# e.g. The StatisticIndex "subscriptions" may have types like "1 month", "1 year", etc. class StatisticType < ApplicationRecord - has_one :statistic_index - has_many :statistic_type_sub_types + belongs_to :statistic_index + has_many :statistic_type_sub_types, dependent: :destroy has_many :statistic_sub_types, through: :statistic_type_sub_types - has_many :statistic_custom_aggregations + has_many :statistic_custom_aggregations, dependent: :destroy end diff --git a/app/services/excel_service.rb b/app/services/excel_service.rb new file mode 100644 index 000000000..067640489 --- /dev/null +++ b/app/services/excel_service.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# Provides methods around Excel files specification +class ExcelService + class << self + # remove all unauthorized characters from the given Excel's worksheet name + # @param name [String] + # @param replace [String] + # @return [String] + def name_safe(name, replace = '-') + name.gsub(%r{[*|\\:"<>?/]}, replace).truncate(31) + end + + # Generate a name for the current type, compatible with Excel worksheet names + # @param type [StatisticType] + # @param workbook [Axlsx::Workbook] + # @return [String] + def statistic_type_sheet_name(type, workbook) + # see https://msdn.microsoft.com/fr-fr/library/c6bdca6y(v=vs.90).aspx for unauthorized character list + name = "#{type.statistic_index.label} - #{type.label}".gsub(%r{[*|\\:"<>?/]}, '') + # sheet name is limited to 31 characters + if name.length > 31 + name = "#{type.statistic_index.label.truncate(4, omission: '.')} - #{type.label}".gsub(%r{[*|\\:"<>?/]}, '').truncate(31) + end + # we cannot have two sheets with the same name + name = name[0..30] + String((rand * 10).to_i) until workbook.sheet_by_name(name).nil? + name + end + end +end diff --git a/app/services/invoices/number_service.rb b/app/services/invoices/number_service.rb new file mode 100644 index 000000000..63875cb1a --- /dev/null +++ b/app/services/invoices/number_service.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +# module definition +module Invoices; end + +# The invoice number is based on the previous invoice +class Invoices::NumberService + class << self + # Get the order number or reference number for the given invoice (not the whole identifier). + # The date part, online payment part, etc. will be excluded and only the number part will be returned. + # @param document [PaymentDocument,NilClass] + # @param setting [String] 'invoice_reference' | 'invoice_order-nb' + # @return [Integer,NilClass] + def number(document, setting = 'invoice_reference') + raise TypeError, "invalid setting #{setting}" unless %w[invoice_order-nb invoice_reference].include?(setting) + return nil if document.nil? + + saved_number = setting == 'invoice_reference' ? document.reference : document.order_number + return nil if saved_number.nil? + + pattern = pattern(document, setting) + pattern = PaymentDocumentService.send(:replace_document_type_pattern, document, pattern) + start_idx = pattern.index(/n+|y+|m+|d+/) + end_idx = pattern.rindex(/n+|y+|m+|d+/) + + saved_number[start_idx..end_idx]&.to_i + end + + # @param document [PaymentDocument,NilClass] + # @param setting [String] 'invoice_reference' | 'invoice_order-nb' + # @return [String,NilClass] 'global' | 'year' | 'month' | 'day' + def number_periodicity(document, setting = 'invoice_reference') + raise TypeError, "invalid setting #{setting}" unless %w[invoice_order-nb invoice_reference].include?(setting) + return nil if document.nil? + + pattern = pattern(document, setting) + pattern = PaymentDocumentService.send(:replace_document_type_pattern, document, pattern) + + return 'global' if pattern.match?(/n+/) + return 'year' if pattern.match?(/y+/) + return 'month' if pattern.match?(/m+/) + return 'day' if pattern.match?(/d+/) + + nil + end + + # Get the pattern applicable to generate the number of the given invoice. + # @param document [PaymentDocument] + # @param setting [String] 'invoice_reference' | 'invoice_order-nb' + # @return [String] + def pattern(document, setting = 'invoice_reference') + raise TypeError, "invalid setting #{setting}" unless %w[invoice_order-nb invoice_reference].include?(setting) + + value = Setting.find_by(name: setting).value_at(document.created_at) + value || if document.created_at < Setting.find_by(name: setting).first_update + Setting.find_by(name: setting).first_value + else + Setting.get(setting) + end + end + end +end diff --git a/app/services/payment_document_service.rb b/app/services/payment_document_service.rb index e5436099b..5209f0b3d 100644 --- a/app/services/payment_document_service.rb +++ b/app/services/payment_document_service.rb @@ -7,56 +7,23 @@ class PaymentDocumentService # @param document [PaymentDocument] # @param date [Time] def generate_reference(document, date: Time.current) - pattern = Setting.get('invoice_reference').to_s + pattern = Invoices::NumberService.pattern(document, 'invoice_reference') - reference = replace_document_number_pattern(pattern, document, document.created_at) + reference = replace_document_number_pattern(pattern, document) reference = replace_date_pattern(reference, date) - - case document - when Avoir - # information about refund/avoir (R[text]) - reference.gsub!(/R\[([^\]]+)\]/, '\1') - - # remove information about online selling (X[text]) - reference.gsub!(/X\[([^\]]+)\]/, ''.to_s) - # remove information about payment schedule (S[text]) - reference.gsub!(/S\[([^\]]+)\]/, ''.to_s) - when PaymentSchedule - # information about payment schedule - reference.gsub!(/S\[([^\]]+)\]/, '\1') - # remove information about online selling (X[text]) - reference.gsub!(/X\[([^\]]+)\]/, ''.to_s) - # remove information about refunds (R[text]) - reference.gsub!(/R\[([^\]]+)\]/, ''.to_s) - when Invoice - # information about online selling (X[text]) - if document.paid_by_card? - reference.gsub!(/X\[([^\]]+)\]/, '\1') - else - reference.gsub!(/X\[([^\]]+)\]/, ''.to_s) - end - - # remove information about refunds (R[text]) - reference.gsub!(/R\[([^\]]+)\]/, ''.to_s) - # remove information about payment schedule (S[text]) - reference.gsub!(/S\[([^\]]+)\]/, ''.to_s) - else - raise TypeError - end - - reference + replace_document_type_pattern(document, reference) end # @param document [PaymentDocument] def generate_order_number(document) - pattern = Setting.get('invoice_order-nb') + pattern = Invoices::NumberService.pattern(document, 'invoice_order-nb') # global document number (nn..nn) reference = pattern.gsub(/n+(?![^\[]*\])/) do |match| - pad_and_truncate(number_of_order('global', document, document.created_at), match.to_s.length) + pad_and_truncate(order_number(document, 'global'), match.to_s.length) end - reference = replace_document_number_pattern(reference, document, document.created_at, :number_of_order) + reference = replace_document_number_pattern(reference, document, :order_number) replace_date_pattern(reference, document.created_at) end @@ -70,58 +37,65 @@ class PaymentDocumentService value.to_s.rjust(length, '0').gsub(/^.*(.{#{length},}?)$/m, '\1') end - # Returns the number of current invoices in the given range around the current date. - # If range is invalid or not specified, the total number of invoices is returned. - # @param range [String] 'day', 'month', 'year' # @param document [PaymentDocument] - # @param date [Time] the ending date - # @return [Integer] - def number_of_documents(range, document, date = Time.current) - start = case range.to_s - when 'day' - date.beginning_of_day - when 'month' - date.beginning_of_month - when 'year' - date.beginning_of_year - else - nil - end - ending = date + # @param periodicity [String] 'day' | 'month' | 'year' | 'global' + # @return [PaymentDocument,NilClass] + def previous_document(document, periodicity) + previous = document.class.base_class.where('created_at < ?', db_time(document.created_at)) + .order(created_at: :desc) + .limit(1) + if %w[day month year].include?(periodicity) + previous = previous.where('date_trunc(:periodicity, created_at) = :date', + periodicity: periodicity, + date: document.created_at.utc.send("beginning_of_#{periodicity}").to_date) + end - documents = document.class.base_class - .where('created_at <= :end_date', end_date: db_time(ending)) - - documents = documents.where('created_at >= :start_date', start_date: db_time(start)) unless start.nil? - - documents.count + previous.first end - def number_of_order(range, _document, date = Time.current) - start = case range.to_s - when 'day' - date.beginning_of_day - when 'month' - date.beginning_of_month - when 'year' - date.beginning_of_year - else - nil - end - ending = date - orders = Order.where('created_at <= :end_date', end_date: db_time(ending)) - orders = orders.where('created_at >= :start_date', start_date: db_time(start)) unless start.nil? - - schedules = PaymentSchedule.where('created_at <= :end_date', end_date: db_time(ending)) - schedules = schedules.where('created_at >= :start_date', start_date: db_time(start)) unless start.nil? + # @param document [PaymentDocument] + # @param periodicity [String] 'day' | 'month' | 'year' | 'global' + def previous_order(document, periodicity) + start = periodicity == 'global' ? nil : document.created_at.send("beginning_of_#{periodicity}") + ending = document.created_at + orders = orders_in_range(document, start, ending) + schedules = schedules_in_range(document, start, ending) invoices = Invoice.where(type: nil) .where.not(id: orders.map(&:invoice_id)) .where.not(id: schedules.map(&:payment_schedule_items).flatten.map(&:invoice_id).filter(&:present?)) - .where('created_at <= :end_date', end_date: db_time(ending)) + .where('created_at < :end_date', end_date: db_time(ending)) invoices = invoices.where('created_at >= :start_date', start_date: db_time(start)) unless start.nil? - orders.count + schedules.count + invoices.count + [ + orders.order(created_at: :desc).limit(1).first, + schedules.order(created_at: :desc).limit(1).first, + invoices.order(created_at: :desc).limit(1).first + ].filter(&:present?).max_by { |item| item&.created_at } + end + + # @param document [PaymentDocument] invoice to exclude + # @param start [Time,NilClass] + # @param ending [Time] + # @return [ActiveRecord::Relation,ActiveRecord::QueryMethods::WhereChain] + def orders_in_range(document, start, ending) + orders = Order.where('created_at < :end_date', end_date: db_time(ending)) + orders = orders.where('created_at >= :start_date', start_date: db_time(start)) unless start.nil? + orders = orders.where.not(id: document.order.id) if document.is_a?(Invoice) && document.order.present? + orders + end + + # @param document [PaymentDocument] invoice to exclude + # @param start [Time,NilClass] + # @param ending [Time] + # @return [ActiveRecord::Relation,ActiveRecord::QueryMethods::WhereChain] + def schedules_in_range(document, start, ending) + schedules = PaymentSchedule.where('created_at < :end_date', end_date: db_time(ending)) + schedules = schedules.where('created_at >= :start_date', start_date: db_time(start)) unless start.nil? + if document.is_a?(Invoice) && document.payment_schedule_item.present? + schedules = schedules.where.not(id: document.payment_schedule_item.payment_schedule.id) + end + schedules end # Replace the date elements in the provided pattern with the date values, from the provided date @@ -155,25 +129,92 @@ class PaymentDocumentService copy end + # @param document [PaymentDocument] + # @param periodicity [String] 'day' | 'month' | 'year' | 'global' + # @return [Integer] + def document_number(document, periodicity) + previous = previous_document(document, periodicity) + number = Invoices::NumberService.number(previous) if Invoices::NumberService.number_periodicity(previous) == periodicity + number ||= 0 + + number + 1 + end + + # @param document [PaymentDocument] + # @param periodicity [String] 'day' | 'month' | 'year' | 'global' + # @return [Integer] + def order_number(document, periodicity) + previous = previous_order(document, periodicity) + if Invoices::NumberService.number_periodicity(previous, 'invoice_order-nb') == periodicity + number = Invoices::NumberService.number(previous, 'invoice_order-nb') + end + number ||= 0 + + number + 1 + end + # Replace the document number elements in the provided pattern with counts from the database # @param reference [String] # @param document [PaymentDocument] - # @param date [Time] - # @param count_method [Symbol] :number_of_documents OR :number_of_order - def replace_document_number_pattern(reference, document, date, count_method = :number_of_documents) + # @param numeration_method [Symbol] :document_number OR :order_number + def replace_document_number_pattern(reference, document, numeration_method = :document_number) copy = reference.dup # document number per year (yy..yy) copy.gsub!(/y+(?![^\[]*\])/) do |match| - pad_and_truncate(send(count_method, 'year', document, date), match.to_s.length) + pad_and_truncate(send(numeration_method, document, 'year'), match.to_s.length) end # document number per month (mm..mm) copy.gsub!(/m+(?![^\[]*\])/) do |match| - pad_and_truncate(send(count_method, 'month', document, date), match.to_s.length) + pad_and_truncate(send(numeration_method, document, 'month'), match.to_s.length) end # document number per day (dd..dd) copy.gsub!(/d+(?![^\[]*\])/) do |match| - pad_and_truncate(send(count_method, 'day', document, date), match.to_s.length) + pad_and_truncate(send(numeration_method, document, 'day'), match.to_s.length) + end + + copy + end + + # @param document [PaymentDocument] + # @param pattern [String] + # @return [String] + def replace_document_type_pattern(document, pattern) + copy = pattern.dup + case document + when Avoir + # information about refund/avoir (R[text]) + copy.gsub!(/R\[([^\]]+)\]/, '\1') + + # remove information about online selling (X[text]) + copy.gsub!(/X\[([^\]]+)\]/, ''.to_s) + # remove information about payment schedule (S[text]) + copy.gsub!(/S\[([^\]]+)\]/, ''.to_s) + when PaymentSchedule + # information about payment schedule + copy.gsub!(/S\[([^\]]+)\]/, '\1') + # remove information about online selling (X[text]) + copy.gsub!(/X\[([^\]]+)\]/, ''.to_s) + # remove information about refunds (R[text]) + copy.gsub!(/R\[([^\]]+)\]/, ''.to_s) + when Invoice + # information about online selling (X[text]) + if document.paid_by_card? + copy.gsub!(/X\[([^\]]+)\]/, '\1') + else + copy.gsub!(/X\[([^\]]+)\]/, ''.to_s) + end + + # remove information about refunds (R[text]) + copy.gsub!(/R\[([^\]]+)\]/, ''.to_s) + # remove information about payment schedule (S[text]) + copy.gsub!(/S\[([^\]]+)\]/, ''.to_s) + else + # maybe an Order or anything else, + # remove all informations + copy.gsub!(/S\[([^\]]+)\]/, ''.to_s) + copy.gsub!(/X\[([^\]]+)\]/, ''.to_s) + copy.gsub!(/R\[([^\]]+)\]/, ''.to_s) end copy diff --git a/app/views/exports/availabilities_index.xlsx.axlsx b/app/views/exports/availabilities_index.xlsx.axlsx index 58748e4c4..7952956df 100644 --- a/app/views/exports/availabilities_index.xlsx.axlsx +++ b/app/views/exports/availabilities_index.xlsx.axlsx @@ -6,7 +6,7 @@ header = wb.styles.add_style b: true, bg_color: Stylesheet.primary.upcase.gsub(' date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_format ## Machines slots -wb.add_worksheet(name: t('export_availabilities.machines')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.machines'))) do |sheet| ## data table # heading labels @@ -45,7 +45,7 @@ end ## Trainings availabilities -wb.add_worksheet(name: t('export_availabilities.trainings')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.trainings'))) do |sheet| ## data table # heading labels @@ -73,7 +73,7 @@ end ## Spaces slots if Setting.get('spaces_module') - wb.add_worksheet(name: t('export_availabilities.spaces')) do |sheet| + wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.spaces'))) do |sheet| ## data table # heading labels @@ -109,7 +109,7 @@ end ## Events availabilities -wb.add_worksheet(name: t('export_availabilities.events')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_availabilities.events'))) do |sheet| ## data table # heading labels diff --git a/app/views/exports/statistics_current.xlsx.axlsx b/app/views/exports/statistics_current.xlsx.axlsx index e4b8062c4..f009cab19 100644 --- a/app/views/exports/statistics_current.xlsx.axlsx +++ b/app/views/exports/statistics_current.xlsx.axlsx @@ -6,12 +6,10 @@ bold = wb.styles.add_style b: true header = wb.styles.add_style b: true, bg_color: Stylesheet.primary.upcase.gsub('#', 'FF'), fg_color: 'FFFFFFFF' date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_format -wb.add_worksheet(name: @index.label) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(@index.label)) do |sheet| ## heading stats for the current page sheet.add_row [t('export.entries'), @results['hits']['total']], style: [bold, nil], types: %i[string integer] - if @index.ca - sheet.add_row [t('export.revenue'), @results['aggregations']['total_ca']['value']], style: [bold, nil], types: %i[string float] - end + sheet.add_row [t('export.revenue'), @results['aggregations']['total_ca']['value']], style: [bold, nil], types: %i[string float] if @index.ca sheet.add_row [t('export.average_age'), @results['aggregations']['average_age']['value']], style: [bold, nil], types: %i[string float] unless @type.simple sheet.add_row ["#{t('export.total')} #{@type.label}", @results['aggregations']['total_stat']['value']], diff --git a/app/views/exports/statistics_global.xlsx.axlsx b/app/views/exports/statistics_global.xlsx.axlsx index 2b9a723d5..b2ffc108c 100644 --- a/app/views/exports/statistics_global.xlsx.axlsx +++ b/app/views/exports/statistics_global.xlsx.axlsx @@ -9,9 +9,7 @@ date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_for next unless index.table index.statistic_types.each do |type| - # see https://msdn.microsoft.com/fr-fr/library/c6bdca6y(v=vs.90).aspx for unauthorized character list - sheet_name = "#{index.label} - #{type.label}".gsub(%r{[*|\\:"<>?/]}, '').truncate(31) - wb.add_worksheet(name: sheet_name) do |sheet| + wb.add_worksheet(name: ExcelService.statistic_type_sheet_name(type, wb)) do |sheet| ## data table # heading labels columns = [t('export.date'), t('export.user'), t('export.email'), t('export.phone'), t('export.gender'), t('export.age'), diff --git a/app/views/exports/users_members.xlsx.axlsx b/app/views/exports/users_members.xlsx.axlsx index be786b317..877a8bf0b 100644 --- a/app/views/exports/users_members.xlsx.axlsx +++ b/app/views/exports/users_members.xlsx.axlsx @@ -5,7 +5,7 @@ wb = xlsx_package.workbook header = wb.styles.add_style b: true, bg_color: Stylesheet.primary.upcase.gsub('#', 'FF'), fg_color: 'FFFFFFFF' date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_format -wb.add_worksheet(name: t('export_members.members')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_members.members'))) do |sheet| ## data table # heading labels columns = [t('export_members.id'), diff --git a/app/views/exports/users_reservations.xlsx.axlsx b/app/views/exports/users_reservations.xlsx.axlsx index 6322d5194..ca2a11b07 100644 --- a/app/views/exports/users_reservations.xlsx.axlsx +++ b/app/views/exports/users_reservations.xlsx.axlsx @@ -5,7 +5,7 @@ wb = xlsx_package.workbook header = wb.styles.add_style b: true, bg_color: Stylesheet.primary.upcase.gsub('#', 'FF'), fg_color: 'FFFFFFFF' date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_format -wb.add_worksheet(name: t('export_reservations.reservations')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_reservations.reservations'))) do |sheet| ## data table # heading labels diff --git a/app/views/exports/users_subscriptions.xlsx.axlsx b/app/views/exports/users_subscriptions.xlsx.axlsx index 05af09724..b8e43ac26 100644 --- a/app/views/exports/users_subscriptions.xlsx.axlsx +++ b/app/views/exports/users_subscriptions.xlsx.axlsx @@ -5,7 +5,7 @@ wb = xlsx_package.workbook header = wb.styles.add_style b: true, bg_color: Stylesheet.primary.upcase.gsub('#', 'FF'), fg_color: 'FFFFFFFF' date = wb.styles.add_style format_code: Rails.application.secrets.excel_date_format -wb.add_worksheet(name: t('export_subscriptions.subscriptions')) do |sheet| +wb.add_worksheet(name: ExcelService.name_safe(t('export_subscriptions.subscriptions'))) do |sheet| ## data table # heading labels diff --git a/package.json b/package.json index bc199b30f..368690a3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fab-manager", - "version": "5.9.0", + "version": "5.9.1", "description": "Fab-manager is the FabLab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.", "keywords": [ "fablab", diff --git a/test/fixtures/availabilities.yml b/test/fixtures/availabilities.yml index 655ae9fcb..d0158a750 100644 --- a/test/fixtures/availabilities.yml +++ b/test/fixtures/availabilities.yml @@ -219,3 +219,13 @@ availability_22: updated_at: 2023-01-24 13:34:43.841240000 Z nb_total_places: 5 destroying: false + +availbility_23: + id: 23 + start_at: 2022-01-01 10:00:00.00000000 Z + end_at: 2022-01-01 11:00:00.00000000 Z + available_type: machines + created_at: 2021-12-24 13:34:43.841240000 Z + updated_at: 2021-12-24 13:34:43.841240000 Z + nb_total_places: + destroying: false diff --git a/test/fixtures/machines_availabilities.yml b/test/fixtures/machines_availabilities.yml index 1400c16a5..a4a5cf772 100644 --- a/test/fixtures/machines_availabilities.yml +++ b/test/fixtures/machines_availabilities.yml @@ -108,3 +108,8 @@ machines_availability_22: id: 22 machine_id: 1 availability_id: 19 + +machines_availability_23: + id: 23 + machine_id: 1 + availability_id: 23 diff --git a/test/fixtures/payment_schedules.yml b/test/fixtures/payment_schedules.yml index ba981efbf..7e7495b65 100644 --- a/test/fixtures/payment_schedules.yml +++ b/test/fixtures/payment_schedules.yml @@ -1,7 +1,7 @@ payment_schedule_12: id: 12 total: 180000 - reference: 210600309/E + reference: 2106309/E payment_method: card wallet_amount: wallet_transaction_id: @@ -17,7 +17,7 @@ payment_schedule_12: payment_schedule_13: id: 13 total: 180000 - reference: <%= 9.months.ago.utc.strftime('%y%m00310/E') %> + reference: <%= 9.months.ago.utc.strftime('%y%m310/E') %> payment_method: card wallet_amount: wallet_transaction_id: diff --git a/test/fixtures/slots.yml b/test/fixtures/slots.yml index f47bf70cc..63bb121ed 100644 --- a/test/fixtures/slots.yml +++ b/test/fixtures/slots.yml @@ -655,3 +655,12 @@ slot_134: updated_at: 2023-01-24 13:34:43.841240000 Z availability_id: 22 places: [{"user_ids": [], "reservable_id": 4, "reservable_type": "Training", "reserved_places": 0}] + +slot_135: + id: 135 + start_at: 2022-01-01 10:00:00.00000000 Z + end_at: 2022-01-01 11:00:00.00000000 Z + created_at: 2021-12-24 13:34:43.841240000 Z + updated_at: 2021-12-24 13:34:43.841240000 Z + availability_id: 23 + places: [{"user_ids": [], "reservable_id": 1, "reservable_type": "Machine", "reserved_places": 0}] diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index c937d613c..b9ffa3410 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -1,5 +1,5 @@ # admin without subscription -user_1: +user1: id: 1 username: admin email: admin@fab-manager.com @@ -32,7 +32,7 @@ user_1: is_allow_newsletter: true # member without subscription -user_2: +user2: id: 2 username: jdupond email: jean.dupond@gmail.com @@ -65,7 +65,7 @@ user_2: is_allow_newsletter: true # member with 1 month subscription (plan 2/standard) -user_3: +user3: id: 3 username: pdurand email: paulette.durand@hotmail.fr @@ -98,7 +98,7 @@ user_3: is_allow_newsletter: false # member with 1 month subscription (plan 3/students) -user_4: +user4: id: 4 username: kdumas email: kevin.dumas@orange.fr @@ -131,7 +131,7 @@ user_4: is_allow_newsletter: false # member with 10€ on wallet -user_5: +user5: id: 5 username: vlonchamp email: vanessa.lonchamp@sfr.fr @@ -164,7 +164,7 @@ user_5: is_allow_newsletter: true # partner of plan 2 -user_6: +user6: id: 6 username: GilbertPartenaire email: gilbert.partenaire@nicolas.com @@ -197,7 +197,7 @@ user_6: is_allow_newsletter: true # member with 255€ on wallet -user_7: +user7: id: 7 username: lseguin email: lucile.seguin@live.fr @@ -229,7 +229,7 @@ user_7: merged_at: is_allow_newsletter: false -user_8: +user8: id: 8 username: atiermoulin email: a.tiermoulin@mail.fr @@ -261,7 +261,7 @@ user_8: merged_at: is_allow_newsletter: false -user_9: +user9: id: 9 username: pjproudhon email: pj.proudhon@la-propriete.org @@ -294,7 +294,7 @@ user_9: is_allow_newsletter: true # member with 1 year subscription -user_10: +user10: id: 10 username: acamus email: albert.camus@letranger.org diff --git a/test/helpers/invoice_helper.rb b/test/helpers/invoice_helper.rb index 2f2cf27ef..d63ed0f9b 100644 --- a/test/helpers/invoice_helper.rb +++ b/test/helpers/invoice_helper.rb @@ -60,7 +60,7 @@ module InvoiceHelper gateway_object_type: 'Stripe::PaymentIntent' ) end - invoice.save + invoice.save! invoice end diff --git a/test/helpers/payment_schedule_helper.rb b/test/helpers/payment_schedule_helper.rb index 90ba5702b..97cc24e8a 100644 --- a/test/helpers/payment_schedule_helper.rb +++ b/test/helpers/payment_schedule_helper.rb @@ -27,10 +27,10 @@ module PaymentScheduleHelper options = { payment_method: 'card', payment_id: 'pi_3LpALs2sOmf47Nz91QyFI7nP', payment_type: 'Stripe::PaymentIntent' } end schedule = PaymentScheduleService.new.create([subscription], 113_600, customer, operator: operator, **options) - schedule.save + schedule.save! first_item = schedule.ordered_items.first PaymentScheduleService.new.generate_invoice(first_item, **options) - first_item.update(state: 'paid', payment_method: operator.privileged? ? 'check' : 'card') + first_item.update!(state: 'paid', payment_method: operator.privileged? ? 'check' : 'card') schedule end diff --git a/test/integration/exports/statistics_export_test.rb b/test/integration/exports/statistics_export_test.rb index 222fee336..00a5cd4cd 100644 --- a/test/integration/exports/statistics_export_test.rb +++ b/test/integration/exports/statistics_export_test.rb @@ -104,11 +104,7 @@ class Exports::StatisticsExportTest < ActionDispatch::IntegrationTest workbook = RubyXL::Parser.parse(e.file) # test worksheets - StatisticIndex.where(table: true).includes(:statistic_fields, statistic_types: [:statistic_sub_types]).each do |index| - index.statistic_types.each do |type| - sheet_name = "#{index.label} - #{type.label}".gsub(%r{[*|\\:"<>?/]}, '').truncate(31) - assert_not_nil workbook[sheet_name], "#{sheet_name} not found" - end - end + assert_equal StatisticIndex.where(table: true).includes(:statistic_types).map(&:statistic_types).flatten.count, + workbook.worksheets.length end end diff --git a/test/integration/order/create_cart_item_test.rb b/test/integration/order/create_cart_item_test.rb index 7fba81874..11a712ee9 100644 --- a/test/integration/order/create_cart_item_test.rb +++ b/test/integration/order/create_cart_item_test.rb @@ -31,6 +31,8 @@ class CreateCartItemTest < ActionDispatch::IntegrationTest test 'create a machine reservation' do machine = Machine.first + slots = Availabilities::AvailabilitiesService.new(@user) + .machines([machine], @user, { start: Time.current, end: 10.days.from_now }) post '/api/cart/create_item', params: { order_token: @order.token, @@ -38,7 +40,7 @@ class CreateCartItemTest < ActionDispatch::IntegrationTest reservable_id: machine.id, reservable_type: 'Machine', slots_reservations_attributes: [ - { slot_id: machine.availabilities.last&.slots&.last&.id } + { slot_id: slots&.last&.id } ] } } diff --git a/test/integration/reservations/pay_with_wallet_test.rb b/test/integration/reservations/pay_with_wallet_test.rb index ec84b8129..9c531017d 100644 --- a/test/integration/reservations/pay_with_wallet_test.rb +++ b/test/integration/reservations/pay_with_wallet_test.rb @@ -188,7 +188,8 @@ class Reservations::PayWithWalletTest < ActionDispatch::IntegrationTest wallet_transactions_count = WalletTransaction.count machine = Machine.find(1) - availability = machine.availabilities.last + slots = Availabilities::AvailabilitiesService.new(user) + .machines([machine], user, { start: Time.current, end: 1.day.from_now }) plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Abonnement mensualisable') VCR.use_cassette('reservations_machine_subscription_with_payment_schedule_coupon_wallet') do @@ -203,7 +204,7 @@ class Reservations::PayWithWalletTest < ActionDispatch::IntegrationTest reservable_type: machine.class.name, slots_reservations_attributes: [ { - slot_id: availability.slots.first.id + slot_id: slots.first.id } ] } diff --git a/test/integration/wallets_test.rb b/test/integration/wallets_test.rb index bbe5de66a..1e050cf08 100644 --- a/test/integration/wallets_test.rb +++ b/test/integration/wallets_test.rb @@ -39,7 +39,7 @@ class WalletsTest < ActionDispatch::IntegrationTest end test 'cant get wallet of an user if not admin' do - user5 = users(:user_4) + user5 = users(:user4) get "/api/wallet/by_user/#{user5.id}" assert_equal 403, response.status end @@ -55,13 +55,13 @@ class WalletsTest < ActionDispatch::IntegrationTest end test 'only admin and wallet owner can show their transactions' do - user5 = users(:user_4) + user5 = users(:user4) get "/api/wallet/#{user5.wallet.id}/transactions" assert_equal 403, response.status end test 'admin can credit amount to a wallet' do - admin = users(:user_1) + admin = users(:user1) login_as(admin, scope: :user) w = @vlonchamp.wallet amount = 10.5 @@ -81,7 +81,7 @@ class WalletsTest < ActionDispatch::IntegrationTest end test 'admin credit wallet with refund invoice generation' do - admin = users(:user_1) + admin = users(:user1) login_as(admin, scope: :user) w = @vlonchamp.wallet amount = 10 diff --git a/test/services/invoices/number_service_test.rb b/test/services/invoices/number_service_test.rb new file mode 100644 index 000000000..caf538ee4 --- /dev/null +++ b/test/services/invoices/number_service_test.rb @@ -0,0 +1,143 @@ +# frozen_string_literal: true + +require 'test_helper' + +class Invoices::NumberServiceTest < ActiveSupport::TestCase + test 'invoice 1 numbers' do + invoice = Invoice.find(1) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 1, reference + assert_equal 1, order_number + periodicity = Invoices::NumberService.number_periodicity(invoice) + assert_equal 'month', periodicity + end + + test 'invoice 2 numbers' do + invoice = Invoice.find(2) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 2, reference + assert_equal 2, order_number + periodicity = Invoices::NumberService.number_periodicity(invoice, 'invoice_order-nb') + assert_equal 'global', periodicity + end + + test 'invoice 3 numbers' do + invoice = Invoice.find(3) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 1, reference + assert_equal 3, order_number + end + + test 'invoice 4 numbers' do + invoice = Invoice.find(4) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 2, reference + assert_equal 4, order_number + end + + test 'invoice 5 numbers' do + invoice = Invoice.find(5) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 31, reference + assert_equal 5, order_number + end + + test 'invoice 6 numbers' do + invoice = Invoice.find(6) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 41, reference + assert_equal 6, order_number + end + + test 'payment schedule 12 numbers' do + schedule = PaymentSchedule.find(12) + reference = Invoices::NumberService.number(schedule) + order_number = Invoices::NumberService.number(schedule, 'invoice_order-nb') + assert_equal 309, reference + assert_equal 7, order_number + end + + test 'payment schedule 13 numbers' do + schedule = PaymentSchedule.find(13) + reference = Invoices::NumberService.number(schedule) + order_number = Invoices::NumberService.number(schedule, 'invoice_order-nb') + assert_equal 310, reference + assert_equal 8, order_number + end + + test 'invoice 5811 numbers' do + invoice = Invoice.find(5811) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 2, reference + assert_equal 9, order_number + end + + test 'invoice 5812 numbers' do + invoice = Invoice.find(5812) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 4, reference + assert_equal 5877, order_number + end + + test 'invoice 5816 numbers' do + invoice = Invoice.find(5816) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 2, reference + assert_equal 5888, order_number + end + + test 'invoice 5817 numbers' do + invoice = Invoice.find(5817) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 4, reference + assert_equal 5890, order_number + end + + test 'invoice 5818 numbers' do + invoice = Invoice.find(5818) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 6, reference + assert_equal 5892, order_number + end + + test 'invoice 5819 numbers' do + invoice = Invoice.find(5819) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 8, reference + assert_equal 5894, order_number + end + + test 'invoice 5820 numbers' do + invoice = Invoice.find(5820) + reference = Invoices::NumberService.number(invoice) + order_number = Invoices::NumberService.number(invoice, 'invoice_order-nb') + assert_equal 10, reference + assert_equal 5882, order_number + end + + test 'daily periodicy' do + Setting.set('invoice_reference', 'YYMDDddddddX[/VL]R[/A]S[/E]') + invoice = sample_reservation_invoice(users(:user10), users(:user1)) + periodicity = Invoices::NumberService.number_periodicity(invoice) + assert_equal 'day', periodicity + end + + test 'monthly periodicy' do + Setting.set('invoice_order-nb', 'MYYYYmmmm') + invoice = sample_reservation_invoice(users(:user10), users(:user1)) + periodicity = Invoices::NumberService.number_periodicity(invoice, 'invoice_order-nb') + assert_equal 'month', periodicity + end +end diff --git a/test/services/payment_document_service_test.rb b/test/services/payment_document_service_test.rb index f422d8b3d..ee42b87e2 100644 --- a/test/services/payment_document_service_test.rb +++ b/test/services/payment_document_service_test.rb @@ -15,7 +15,7 @@ class PaymentDocumentServiceTest < ActiveSupport::TestCase test 'invoice for local payment' do invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}001", invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", invoice.order_number end test 'invoice with custom format' do @@ -29,31 +29,31 @@ class PaymentDocumentServiceTest < ActiveSupport::TestCase end test 'invoice with other custom format' do - travel_to(Time.current.beginning_of_year) + travel_to('2022-01-01') Setting.set('invoice_reference', 'YYMDDyyyyX[/VL]R[/A]S[/E]') Setting.set('invoice_order-nb', 'DMYYYYnnnnnn') invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%-m%d')}0001", invoice.reference - assert_equal "#{Time.current.strftime('%-d%-m%Y')}000018", invoice.order_number + assert_equal "#{Time.current.strftime('%-d%-m%Y')}000008", invoice.order_number travel_back end test 'invoice for online card payment' do invoice = sample_reservation_invoice(@acamus, @acamus) assert_equal "#{Time.current.strftime('%y%m')}001/VL", invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", invoice.order_number end test 'refund' do invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}001", invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", invoice.order_number refund = invoice.build_avoir(payment_method: 'wallet', invoice_items_ids: invoice.invoice_items.map(&:id)) refund.save refund.reload assert_equal "#{Time.current.strftime('%y%m')}002/A", refund.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", refund.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", refund.order_number end test 'payment schedule' do @@ -62,31 +62,31 @@ class PaymentDocumentServiceTest < ActiveSupport::TestCase assert_equal "#{Time.current.strftime('%y%m')}001/E", schedule.reference first_item = schedule.ordered_items.first assert_equal "#{Time.current.strftime('%y%m')}001", first_item.invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", first_item.invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", first_item.invoice.order_number second_item = schedule.ordered_items[1] PaymentScheduleService.new.generate_invoice(second_item, payment_method: 'check') assert_equal "#{Time.current.strftime('%y%m')}002", second_item.invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", second_item.invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", second_item.invoice.order_number third_item = schedule.ordered_items[2] PaymentScheduleService.new.generate_invoice(third_item, payment_method: 'check') assert_equal "#{Time.current.strftime('%y%m')}003", third_item.invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", third_item.invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", third_item.invoice.order_number fourth_item = schedule.ordered_items[3] PaymentScheduleService.new.generate_invoice(fourth_item, payment_method: 'check') assert_equal "#{Time.current.strftime('%y%m')}004", fourth_item.invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", fourth_item.invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", fourth_item.invoice.order_number fifth_item = schedule.ordered_items[2] PaymentScheduleService.new.generate_invoice(fifth_item, payment_method: 'check') assert_equal "#{Time.current.strftime('%y%m')}005", fifth_item.invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", fifth_item.invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", fifth_item.invoice.order_number end test 'order' do - cart = Cart::FindOrCreateService.new(users(:user_2)).call(nil) + cart = Cart::FindOrCreateService.new(users(:user2)).call(nil) cart = Cart::AddItemService.new.call(cart, Product.find_by(slug: 'panneaux-de-mdf'), 1) Checkout::PaymentService.new.payment(cart, @admin, nil) - assert_equal "000023-#{Time.current.strftime('%m-%y')}", cart.reference # here reference = order number - assert_equal "000023-#{Time.current.strftime('%m-%y')}", cart.invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", cart.reference # here reference = order number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", cart.invoice.order_number assert_equal "#{Time.current.strftime('%y%m')}001", cart.invoice.reference end @@ -95,94 +95,94 @@ class PaymentDocumentServiceTest < ActiveSupport::TestCase invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}001", invoice.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", invoice.order_number refund = invoice.build_avoir(payment_method: 'wallet', invoice_items_ids: invoice.invoice_items.map(&:id)) refund.save refund.reload assert_equal "#{Time.current.strftime('%y%m')}002/A", refund.reference - assert_equal "000023-#{Time.current.strftime('%m-%y')}", refund.order_number + assert_equal "005905-#{Time.current.strftime('%m-%y')}", refund.order_number invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}003", invoice.reference - assert_equal "000024-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005906-#{Time.current.strftime('%m-%y')}", invoice.order_number invoice = sample_reservation_invoice(@acamus, @acamus) assert_equal "#{Time.current.strftime('%y%m')}004/VL", invoice.reference - assert_equal "000025-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005907-#{Time.current.strftime('%m-%y')}", invoice.order_number invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}005", invoice.reference - assert_equal "000026-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005908-#{Time.current.strftime('%m-%y')}", invoice.order_number invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}006", invoice.reference - assert_equal "000027-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005909-#{Time.current.strftime('%m-%y')}", invoice.order_number invoice = sample_reservation_invoice(@acamus, @acamus) assert_equal "#{Time.current.strftime('%y%m')}007/VL", invoice.reference - assert_equal "000028-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005910-#{Time.current.strftime('%m-%y')}", invoice.order_number invoice = sample_reservation_invoice(@acamus, @acamus) assert_equal "#{Time.current.strftime('%y%m')}008/VL", invoice.reference - assert_equal "000029-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005911-#{Time.current.strftime('%m-%y')}", invoice.order_number refund = invoice.build_avoir(payment_method: 'wallet', invoice_items_ids: invoice.invoice_items.map(&:id)) refund.save refund.reload assert_equal "#{Time.current.strftime('%y%m')}009/A", refund.reference - assert_equal "000029-#{Time.current.strftime('%m-%y')}", refund.order_number + assert_equal "005911-#{Time.current.strftime('%m-%y')}", refund.order_number invoice = sample_reservation_invoice(@acamus, @acamus) assert_equal "#{Time.current.strftime('%y%m')}010/VL", invoice.reference - assert_equal "000030-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005912-#{Time.current.strftime('%m-%y')}", invoice.order_number invoice2 = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}011", invoice2.reference - assert_equal "000031-#{Time.current.strftime('%m-%y')}", invoice2.order_number + assert_equal "005913-#{Time.current.strftime('%m-%y')}", invoice2.order_number refund = invoice.build_avoir(payment_method: 'wallet', invoice_items_ids: invoice.invoice_items.map(&:id)) refund.save refund.reload assert_equal "#{Time.current.strftime('%y%m')}012/A", refund.reference - assert_equal "000030-#{Time.current.strftime('%m-%y')}", refund.order_number + assert_equal "005912-#{Time.current.strftime('%m-%y')}", refund.order_number refund = invoice2.build_avoir(payment_method: 'wallet', invoice_items_ids: invoice.invoice_items.map(&:id)) refund.save refund.reload assert_equal "#{Time.current.strftime('%y%m')}013/A", refund.reference - assert_equal "000031-#{Time.current.strftime('%m-%y')}", refund.order_number + assert_equal "005913-#{Time.current.strftime('%m-%y')}", refund.order_number schedule = sample_schedule(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}001/E", schedule.reference assert_equal "#{Time.current.strftime('%y%m')}014", schedule.ordered_items.first.invoice.reference - assert_equal "000032-#{Time.current.strftime('%m-%y')}", schedule.ordered_items.first.invoice.order_number + assert_equal "005914-#{Time.current.strftime('%m-%y')}", schedule.ordered_items.first.invoice.order_number - schedule = sample_schedule(users(:user_2), users(:user_2)) + schedule = sample_schedule(users(:user2), users(:user2)) assert_equal "#{Time.current.strftime('%y%m')}002/E", schedule.reference assert_equal "#{Time.current.strftime('%y%m')}015/VL", schedule.ordered_items.first.invoice.reference - assert_equal "000033-#{Time.current.strftime('%m-%y')}", schedule.ordered_items.first.invoice.order_number + assert_equal "005915-#{Time.current.strftime('%m-%y')}", schedule.ordered_items.first.invoice.order_number invoice = sample_reservation_invoice(@acamus, @acamus) assert_equal "#{Time.current.strftime('%y%m')}016/VL", invoice.reference - assert_equal "000034-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005916-#{Time.current.strftime('%m-%y')}", invoice.order_number - cart = Cart::FindOrCreateService.new(users(:user_2)).call(nil) + cart = Cart::FindOrCreateService.new(users(:user2)).call(nil) cart = Cart::AddItemService.new.call(cart, Product.find_by(slug: 'panneaux-de-mdf'), 1) Checkout::PaymentService.new.payment(cart, @admin, nil) - assert_equal "000035-#{Time.current.strftime('%m-%y')}", cart.reference # here reference = order number - assert_equal "000035-#{Time.current.strftime('%m-%y')}", cart.invoice.order_number + assert_equal "005917-#{Time.current.strftime('%m-%y')}", cart.reference # here reference = order number + assert_equal "005917-#{Time.current.strftime('%m-%y')}", cart.invoice.order_number assert_equal "#{Time.current.strftime('%y%m')}017", cart.invoice.reference - cart = Cart::FindOrCreateService.new(users(:user_2)).call(nil) + cart = Cart::FindOrCreateService.new(users(:user2)).call(nil) cart = Cart::AddItemService.new.call(cart, Product.find_by(slug: 'panneaux-de-mdf'), 1) Checkout::PaymentService.new.payment(cart, @admin, nil) - assert_equal "000036-#{Time.current.strftime('%m-%y')}", cart.reference # here reference = order number - assert_equal "000036-#{Time.current.strftime('%m-%y')}", cart.invoice.order_number + assert_equal "005918-#{Time.current.strftime('%m-%y')}", cart.reference # here reference = order number + assert_equal "005918-#{Time.current.strftime('%m-%y')}", cart.invoice.order_number assert_equal "#{Time.current.strftime('%y%m')}018", cart.invoice.reference invoice = sample_reservation_invoice(@acamus, @admin) assert_equal "#{Time.current.strftime('%y%m')}019", invoice.reference - assert_equal "000037-#{Time.current.strftime('%m-%y')}", invoice.order_number + assert_equal "005919-#{Time.current.strftime('%m-%y')}", invoice.order_number end end diff --git a/test/services/reservation_limit_service_test.rb b/test/services/reservation_limit_service_test.rb index 5c9f432cf..ea9b6f327 100644 --- a/test/services/reservation_limit_service_test.rb +++ b/test/services/reservation_limit_service_test.rb @@ -44,13 +44,14 @@ class ReservationLimitServiceTest < ActiveSupport::TestCase test 'reservation exceeds plan limit' do @plan.update(limiting: true, plan_limitations_attributes: [{ limitable_id: @machine.id, limitable_type: 'Machine', limit: 2 }]) slots = Availabilities::AvailabilitiesService.new(@acamus) - .machines([@machine], @acamus, { start: Time.current, end: 10.days.from_now }) + .machines([@machine], @acamus, { start: 1.day.from_now.beginning_of_day, + end: 1.day.from_now.end_of_day }) reservation = CartItem::MachineReservation.new( customer_profile: @acamus.invoicing_profile, operator_profile: @acamus.invoicing_profile, reservable: @machine, - cart_item_reservation_slots_attributes: [{ slot: slots[2] }, { slot: slots[3] }, { slot: slots[4] }] + cart_item_reservation_slots_attributes: [{ slot: slots[0] }, { slot: slots[1] }, { slot: slots[2] }] ) assert_not ReservationLimitService.authorized?(@plan, @acamus, reservation, []) end