Skip to content

Commit

Permalink
Merge pull request #384 from diegosteiner/refactor/settings_model
Browse files Browse the repository at this point in the history
feat: booking state editable as setting
  • Loading branch information
diegosteiner authored Jan 8, 2025
2 parents 4c6c0d8 + 9b97971 commit ec78147
Show file tree
Hide file tree
Showing 41 changed files with 257 additions and 270 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ gem 'sidekiq-cron'
gem 'slim-rails'
gem 'stackprof'
gem 'statesman'
gem 'store_model'
gem 'thruster'
gem 'translation'
gem 'ttfunk', '~> 1.7.0' # https://github.com/prawnpdf/prawn/issues/1346
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ GEM
stackprof (0.2.26)
statesman (12.1.0)
statsd-ruby (1.5.0)
store_model (4.2.0)
activerecord (>= 7.0)
stringio (3.1.2)
strscan (3.1.2)
temple (0.10.3)
Expand Down Expand Up @@ -640,6 +642,7 @@ DEPENDENCIES
squasher
stackprof
statesman
store_model
thruster
translation
ttfunk (~> 1.7.0)
Expand Down
7 changes: 4 additions & 3 deletions app/controllers/manage/bookings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ def calendar
end

def new
transition_to = current_organisation.booking_state_settings.default_manage_transition_to_state
@booking = preparation_service.prepare_new(booking_params)
@booking.assign_attributes(organisation: current_organisation,
transition_to: current_organisation.settings.default_manage_transition_to_state)
@booking.assign_attributes(organisation: current_organisation, transition_to:)
process_booking_question_responses

respond_with :manage, @booking
Expand Down Expand Up @@ -116,7 +116,8 @@ def booking_question_responses_params
end

def default_booking_filter_params
{ 'concluded' => 'inconcluded', 'current_booking_states' => BookingStates.displayed_by_default }
{ 'concluded' => 'inconcluded',
'current_booking_states' => current_organisation.booking_flow_class.displayed_by_default }
end

class Import < Import::ApplicationImport
Expand Down
2 changes: 1 addition & 1 deletion app/domain/booking_flows/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def initialize(object, options = {})
def booking_state
return @booking_state if @booking_state&.to_s == current_state.to_s && @booking_state.booking == booking

@booking_state = BookingStates.all[current_state&.to_sym]&.new(booking)
@booking_state = BookingStates[current_state&.to_sym]&.new(booking)
end

def booking
Expand Down
17 changes: 17 additions & 0 deletions app/domain/booking_flows/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,22 @@ class Default < Base
state BookingStates::DeclinedRequest, to: %i[open_request]
state BookingStates::CancelationPending, to: %i[cancelled]
state BookingStates::Cancelled

def self.all
@all ||= states.to_h { |state| [state.to_sym, BookingStates[state.to_sym]] }
end

def self.displayed_by_default
@displayed_by_default ||= all.values.filter_map { |state| state.to_sym unless state.hidden }
end

def self.occupied_by_default
@occupied_by_default ||= %i[definitive_request awaiting_tenant awaiting_contract upcoming upcoming_soon]
end

def self.editable_by_default
@editable_by_default ||= %i[initial unconfirmed_request open_request provisional_request
booking_agent_request awaiting_tenant overdue_request]
end
end
end
13 changes: 4 additions & 9 deletions app/domain/booking_states.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
# frozen_string_literal: true

module BookingStates
def self.[](key)
all[key&.to_sym]
end

def self.all
@all ||= [
UnconfirmedRequest, OpenRequest, ProvisionalRequest, DefinitiveRequest, BookingAgentRequest, AwaitingTenant,
AwaitingContract, Overdue, UpcomingSoon, Upcoming, Active, Past, PaymentDue, CancelationPending, Completed,
CancelledRequest, DeclinedRequest, Cancelled, OverdueRequest, PaymentOverdue, Initial
].index_by(&:to_sym)
end

def self.displayed_by_default
all.values.filter_map { |state| state.to_sym unless state.hidden }
end

def self.occupied_occupancy_able
@occupied_occupancy_able ||= [DefinitiveRequest, AwaitingTenant, AwaitingContract,
Upcoming, UpcomingSoon].index_by(&:to_sym)
end
end
4 changes: 2 additions & 2 deletions app/domain/booking_states/awaiting_contract.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ def self.to_sym
end

after_transition do |booking|
booking.create_deadline(length: booking.organisation.settings.awaiting_contract_deadline,
postponable_for: booking.organisation.settings.deadline_postponable_for,
booking.create_deadline(length: booking.organisation.deadline_settings.awaiting_contract_deadline,
postponable_for: booking.organisation.deadline_settings.deadline_postponable_for,
remarks: booking.booking_state.t(:label))
end

Expand Down
8 changes: 2 additions & 6 deletions app/domain/booking_states/awaiting_tenant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ def invoice_type
Invoices::Deposit
end

def editable
true
end

def self.to_sym
:awaiting_tenant
end
Expand All @@ -34,8 +30,8 @@ def self.to_sym
end

after_transition do |booking|
booking.create_deadline(length: booking.organisation.settings.awaiting_tenant_deadline,
postponable_for: booking.organisation.settings.deadline_postponable_for,
booking.create_deadline(length: booking.organisation.deadline_settings.awaiting_tenant_deadline,
postponable_for: booking.organisation.deadline_settings.deadline_postponable_for,
remarks: booking.booking_state.t(:label))
MailTemplate.use!(:awaiting_tenant_notification, booking, to: :tenant, &:autodeliver!)
next if booking.agent_booking.blank?
Expand Down
4 changes: 2 additions & 2 deletions app/domain/booking_states/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def guard_transition(from: nil, &)
end

def occupied_occupancy_state?(booking)
booking&.organisation&.settings&.occupied_occupancy_states&.include?(to_s) # rubocop:disable Style/SafeNavigationChainLength
booking&.organisation&.booking_state_settings&.occupied_occupancy_states&.include?(to_sym.to_s) # rubocop:disable Style/SafeNavigationChainLength
end

def available_public_actions
Expand Down Expand Up @@ -123,7 +123,7 @@ def manage_actions
def relevant_time; end

def editable
false
@booking.organisation&.booking_state_settings&.editable_occupancy_states&.include?(to_sym.to_s)
end
end
end
6 changes: 1 addition & 5 deletions app/domain/booking_states/booking_agent_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ def invoice_type
Invoices::Deposit
end

def editable
true
end

def self.to_sym
:booking_agent_request
end
Expand All @@ -26,7 +22,7 @@ def self.to_sym

after_transition do |booking|
booking.create_deadline(at: booking.booking_agent.request_deadline_minutes.minutes.from_now,
postponable_for: booking.organisation.settings.deadline_postponable_for,
postponable_for: booking.organisation.deadline_settings.deadline_postponable_for,
remarks: booking.booking_state.t(:label))
end

Expand Down
4 changes: 0 additions & 4 deletions app/domain/booking_states/initial.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,5 @@ def self.to_sym
def self.hidden
true
end

def editable
true
end
end
end
4 changes: 0 additions & 4 deletions app/domain/booking_states/open_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ def invoice_type
Invoices::Deposit
end

def editable
true
end

def self.to_sym
:open_request
end
Expand Down
6 changes: 1 addition & 5 deletions app/domain/booking_states/overdue_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@ def self.to_sym
:overdue_request
end

def editable
true
end

after_transition do |booking|
booking.deadline&.clear
length = booking.organisation.settings.overdue_request_deadline
length = booking.organisation.deadline_settings.overdue_request_deadline
booking.create_deadline(length:, remarks: booking.booking_state.t(:label)) unless length.negative?
MailTemplate.use(:overdue_request_notification, booking, to: :tenant, &:autodeliver!)
end
Expand Down
4 changes: 2 additions & 2 deletions app/domain/booking_states/payment_due.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def self.to_sym
payable_until = unpaid_invoices.map(&:payable_until).compact.max
next if payable_until.blank?

booking.create_deadline(at: payable_until + booking.organisation.settings.payment_overdue_deadline,
postponable_for: booking.organisation.settings.deadline_postponable_for)
booking.create_deadline(at: payable_until + booking.organisation.deadline_settings.payment_overdue_deadline,
postponable_for: booking.organisation.deadline_settings.deadline_postponable_for)
end

infer_transition(to: :completed) do |booking|
Expand Down
8 changes: 2 additions & 6 deletions app/domain/booking_states/provisional_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,13 @@ def self.to_sym
:provisional_request
end

def editable
true
end

after_transition from: :definitive_request do |booking|
booking.update(committed_request: false)
end

after_transition do |booking|
booking.create_deadline(length: booking.organisation.settings.provisional_request_deadline,
postponable_for: booking.organisation.settings.deadline_postponable_for,
booking.create_deadline(length: booking.organisation.deadline_settings.provisional_request_deadline,
postponable_for: booking.organisation.deadline_settings.deadline_postponable_for,
remarks: booking.booking_state.t(:label))
booking.tentative!
next if booking.committed_request
Expand Down
6 changes: 1 addition & 5 deletions app/domain/booking_states/unconfirmed_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ def self.to_sym
:unconfirmed_request
end

def editable
true
end

infer_transition(to: :declined_request) do |booking|
booking.deadline_exceeded?
end
Expand All @@ -28,7 +24,7 @@ def editable
end

after_transition do |booking|
booking.create_deadline(length: booking.organisation.settings.unconfirmed_request_deadline,
booking.create_deadline(length: booking.organisation.deadline_settings.unconfirmed_request_deadline,
remarks: booking.booking_state.t(:label))
booking.tentative!
MailTemplate.use(:unconfirmed_request_notification, booking, to: :tenant, &:autodeliver!)
Expand Down
4 changes: 3 additions & 1 deletion app/models/accounting_settings.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class AccountingSettings < Settings
class AccountingSettings
include StoreModel::Model

attribute :enabled, :boolean, default: -> { false }
attribute :debitor_account_nr, :string
attribute :rental_yield_account_nr, :string
Expand Down
19 changes: 19 additions & 0 deletions app/models/booking_state_settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class BookingStateSettings
include StoreModel::Model
extend ActiveModel::Naming
extend ActiveModel::Translation

attribute :default_manage_transition_to_state, :string, default: -> { BookingStates::ProvisionalRequest.to_s }
attribute :occupied_occupancy_states, array: true, default: lambda {
BookingFlows::Default.occupied_by_default.map(&:to_sym)
}
attribute :editable_occupancy_states, array: true, default: lambda {
BookingFlows::Default.editable_by_default.map(&:to_sym)
}

def self.manage_transition_to_states(organisation)
organisation.booking_flow_class.successors['initial'].map { BookingStates[_1.to_sym] }.compact_blank
end
end
22 changes: 22 additions & 0 deletions app/models/deadline_settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

class DeadlineSettings
include StoreModel::Model
extend ActiveModel::Naming
extend ActiveModel::Translation

attribute :awaiting_contract_deadline, DurationType.new, default: -> { 10.days }
attribute :awaiting_tenant_deadline, DurationType.new, default: -> { 10.days }
attribute :overdue_request_deadline, DurationType.new, default: -> { 3.days }
attribute :payment_overdue_deadline, DurationType.new, default: -> { 3.days }
attribute :unconfirmed_request_deadline, DurationType.new, default: -> { 3.days }
attribute :provisional_request_deadline, DurationType.new, default: -> { 10.days }
attribute :invoice_payment_deadline, DurationType.new, default: -> { 30.days }
attribute :deposit_payment_deadline, DurationType.new, default: -> { 10.days }
attribute :deadline_postponable_for, DurationType.new, default: -> { 3.days }

validates :awaiting_contract_deadline, :awaiting_tenant_deadline, :overdue_request_deadline,
:payment_overdue_deadline, :unconfirmed_request_deadline, :provisional_request_deadline,
:invoice_payment_deadline, :deposit_payment_deadline, :deadline_postponable_for,
numericality: { less_than_or_equal: 5.years, greater_than_or_equal: 0 }
end
9 changes: 4 additions & 5 deletions app/models/invoice/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,14 @@ def template_context(invoice)
end

def payable_until(invoice)
return invoice.booking.begins_at if invoice.payment_info.is_a?(PaymentInfos::OnArrival)
booking = invoice.booking
return booking.begins_at if invoice.payment_info.is_a?(PaymentInfos::OnArrival)

settings = invoice.booking.organisation.settings
if invoice.is_a?(Invoices::Deposit)
return [settings.deposit_payment_deadline.from_now,
invoice.booking.begins_at].min
return [booking.organisation.deadline_settings.deposit_payment_deadline.from_now, booking.begins_at].min
end

settings.invoice_payment_deadline.from_now
booking.organisation.deadline_settings.invoice_payment_deadline.from_now
end

def payment_required(invoice)
Expand Down
2 changes: 1 addition & 1 deletion app/models/occupiable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Occupiable < ApplicationRecord
belongs_to :organisation, inverse_of: :occupiables
belongs_to :home, inverse_of: :occupiables, optional: true

attribute :settings, Settings::Type.new(OccupiableSettings), default: -> { OccupiableSettings.new }
attribute :settings, OccupiableSettings.to_type, default: -> { OccupiableSettings.new }

translates :name, :description, column_suffix: '_i18n', locale_accessors: true
ranks :ordinal, with_same: :organisation_id, class_name: 'Occupiable'
Expand Down
4 changes: 3 additions & 1 deletion app/models/occupiable_settings.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class OccupiableSettings < Settings
class OccupiableSettings
include StoreModel::Model

attribute :booking_margin, DurationType.new, default: 0
attribute :accounting_cost_center_nr

Expand Down
11 changes: 5 additions & 6 deletions app/models/organisation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,17 @@ class Organisation < ApplicationRecord
validates :logo, :contract_signature, content_type: { in: ['image/png', 'image/jpeg'] }
validates :locale, presence: true
validate do
errors.add(:settings, :invalid) unless settings.valid?
errors.add(:smtp_settings, :invalid) unless smtp_settings.nil? || smtp_settings.valid?
errors.add(:accounting_settings, :invalid) unless accounting_settings.nil? || accounting_settings.valid?
errors.add(:creditor_address, :invalid) if creditor_address&.lines&.count&.> 3
errors.add(:account_address, :invalid) if account_address&.lines&.count&.> 3
errors.add(:iban, :invalid) if iban.present? && !iban.valid?
end

attribute :booking_flow_type, default: -> { BookingFlows::Default.to_s }
attribute :settings, Settings::Type.new(OrganisationSettings), default: -> { OrganisationSettings.new }
attribute :accounting_settings, Settings::Type.new(AccountingSettings), default: -> { AccountingSettings.new }
attribute :smtp_settings, Settings::Type.new(SmtpSettings)
attribute :settings, OrganisationSettings.to_type, default: -> { OrganisationSettings.new }
attribute :accounting_settings, AccountingSettings.to_type, default: -> { AccountingSettings.new }
attribute :smtp_settings, SmtpSettings.to_type
attribute :booking_state_settings, BookingStateSettings.to_type, default: -> { BookingStateSettings.new }
attribute :deadline_settings, DeadlineSettings.to_type, default: -> { DeadlineSettings.new }
attribute :iban, IBAN::Type.new
attribute :tenant_ref_template, default: -> { RefBuilders::Tenant::DEFAULT_TEMPLATE }
attribute :booking_ref_template, default: -> { RefBuilders::Booking::DEFAULT_TEMPLATE }
Expand Down
Loading

0 comments on commit ec78147

Please sign in to comment.