Created
May 22, 2012 13:11
-
-
Save marcusleemitchell/2768949 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@ -208,46 +202,16 @@ private | |
...skipping... | |
diff --git a/app/models/booking.rb b/app/models/booking.rb | |
index 0c52530..4443485 100644 | |
--- a/app/models/booking.rb | |
+++ b/app/models/booking.rb | |
@@ -11,7 +11,6 @@ class Booking < ActiveRecord::Base | |
does 'date_range', :check_in_date, :check_out_date | |
does 'flag', :old_style_commissions, :default => false | |
- does 'flag', :used_for_authorisation, :default => false | |
does 'flag', 'unread', :default => true | |
does 'flag', :external_terms_accepted, :default => false | |
does 'booking/payment' | |
@@ -20,15 +19,20 @@ class Booking < ActiveRecord::Base | |
does 'booking/payment_export' | |
does 'booking/messaging' | |
does 'booking/agency' | |
+ does 'booking/payment_methods' | |
+ does 'money', :exchange_rate => :payment_exchange_rate | |
does 'booking/marketing_events' | |
- does 'money', :exchange_rate => :exchange_rate, :validate => true | |
+ def payment_exchange_rate | |
+ initial_payment.exchange_rate | |
+ end | |
+ | |
+ # does 'money', :exchange_rate => :exchange_rate, :validate => true | |
does 'act_like_property_search' | |
does 'booking/kigo' | |
has_paper_trail | |
- | |
attr_writer :calendar_interface | |
delegate :is_valid_for_calendar?, :minimum_days_of_stay_on_check_in_date, :to => :calendar_interface | |
@@ -37,18 +41,17 @@ class Booking < ActiveRecord::Base | |
belongs_to :booking_offer | |
belongs_to :host, :class_name => 'User' | |
has_one :tenant_info_sheet, :as => :owner | |
- has_one :payment, :as => :owner | |
+ has_many :payments | |
+ | |
+ has_many :additional_payments | |
has_one :external_services_log | |
- belongs_to :exchange_rate | |
has_many :frozen_additional_fees | |
has_many :booking_histories, :dependent => :destroy | |
has_many :booking_events, :primary_key => :booking_key, :foreign_key => :booking_key, :dependent => :delete_all | |
has_many :booking_tests | |
- # This list contains legacy values which must not be removed to avoid old bookings becoming invalid | |
- ALLOWED_CC_CHARGED_VALUES = ['', 'authorised', 'charged', 'X', 'processing', 'rejected', 'Charged AD', 'Charged GC'] | |
- validates_presence_of :property_id, :check_in_date, :check_out_date, :total_price_of_stay | |
+ validates_presence_of :property_id, :check_in_date, :check_out_date | |
validates_presence_of :tenant_info_sheet, :unless => :pending? | |
validates_presence_of :user_id, :unless => :skip_validation_of_user_id | |
validates_numericality_of :number_of_guests, :greater_than => 0, :message => N_('!Please select the number of guests.') | |
@@ -59,8 +62,7 @@ class Booking < ActiveRecord::Base | |
attr_accessor :skip_validation_of_user_id | |
validates_inclusion_of :cancellation_policy, :in => %w[relaxed intermediate moderate strict relaxed_100_50 mid_run long_run strict_50_0] | |
- validates_inclusion_of :payment_faked_option, :in => ['fake_1', 'fake_2', 'fake_3', 'fake_4', '', nil] | |
- validates_inclusion_of :cc_charged, :in => ALLOWED_CC_CHARGED_VALUES, :allow_nil => true | |
+ | |
validate :is_valid_for_calendar!, :if => :validate_availability? | |
validates_before :check_in_date, :check_out_date | |
@@ -68,6 +70,8 @@ class Booking < ActiveRecord::Base | |
validates_does_not_overlap lambda{|booking| booking.property.try(:bookings)}, :message => N_('must not overlap with other Bookings.'), :if => lambda { |booking| booking.validate_does_not_overlap_with_other_bookings? } | |
+ accepts_nested_attributes_for :payments | |
+ | |
AVAILABLE_STATES = %w[pending requested requested_from_agency accepted denied no_response | |
agency_booking_failed_because_of_api agency_booking_failed_because_of_validation | |
cancelled cancelled_by_host cancelled_by_guest cancelled_by_housetrip | |
@@ -79,26 +83,28 @@ class Booking < ActiveRecord::Base | |
validates_inclusion_of :status, :in => AVAILABLE_STATES, :unless => :pending?, :allow_blank => true | |
validates_inclusion_of :host_reminder_sent, :review_reminder_sent, :in => [true, false] | |
- validates_inclusion_of :used_for_authorisation, :in => [false, nil], :unless => :usable_for_authorisation?, :message => 'not allowed for this booking' | |
# after_update :deliver_confirmation_emails, :if => :being_confirmed? | |
before_validation :set_booking_key | |
before_validation_on_create :set_money_fields, :set_external_fields | |
before_validation_on_create :accept_external_terms, :if => :agency_booking? | |
+ before_validation_on_create :set_booking_key | |
before_create :set_attributes | |
+ | |
before_save :build_status_change_event, :if => proc { |b| b.status_changed? } | |
before_save :set_no_payment_info, :unless => proc { |b| b.property && b.property.has_valid_payment_method? } | |
+ after_create :set_booking_reference | |
+ | |
after_save :update_crm | |
after_save :update_host | |
- after_destroy :destroy_crm | |
after_save :update_host_count, :if => :being_confirmed? | |
after_save :update_guest, :if => :being_confirmed? | |
after_save :update_property | |
after_save :confirm_booking_offer, :if => :being_confirmed? | |
- after_create :set_booking_reference | |
after_save :trust_host, :if => lambda { |booking| booking.regular_payment_email_sent_at.present? } | |
- before_validation_on_create :set_booking_key | |
after_save :freeze_hosts_contact_info | |
+ after_destroy :destroy_crm | |
+ after_save :set_money_fields | |
merge_with_existing_availabilities :start_date_method => :check_in_date, :end_date_method => :check_out_date, :callback => :after_save, :if => :merge_with_existing_availabilities? | |
@@ -124,27 +130,30 @@ class Booking < ActiveRecord::Base | |
named_scope :require_assistance_offer, lambda { { :conditions => ['pending = ? AND assistance_offer_sent_at IS NULL AND created_at > ? AND created_at < ? AND send_assistance_email = ?', true, Time.current - 2.hours, Time.current | |
named_scope :require_assistance_offer_at_create_stage, lambda { { :include => [:booking_events], :conditions => ['pending = ? AND assistance_offer_sent_at IS NULL AND bookings.created_at > ? AND bookings.created_at < ? AND sen | |
named_scope :converted, :conditions => ['status = ? AND assistance_offer_sent_at IS NOT NULL', 'accepted'] | |
- named_scope :with_invalid_payment_information, :conditions => { :payment_on_hold => INVALID_PAYMENT_INFO } | |
- | |
+ named_scope :with_invalid_payment_information, :conditions => ["payments.payment_on_hold = ?", INVALID_PAYMENT_INFO], :joins => :payments | |
named_scope :by_check_in_date, :order => 'bookings.check_in_date DESC' | |
- | |
named_scope :visible_to_host, :conditions => ['bookings.status NOT IN (?)', %w(denied no_response requested)] | |
- | |
- # def self.require_assistance_offer_at_create_stage | |
- # require_assistance_offer.delete_if{ |x| !x.booking_events.collect{ |y| y.type }.include?("BillingDetailsPageHitBookingEvent") } | |
- # end | |
+ | |
+ def initialize(args = {}) | |
+ super | |
+ self.payments << InitialPayment.new(:booking => self) | |
+ end | |
def self.ended_yesterday | |
accepted.scoped :conditions => [ 'bookings.check_out_date = ?', Date.yesterday ] | |
end | |
+ def initial_payment_creation | |
+ self.payments << InitialPayment.create(:psp_reference => self.id) | |
+ end | |
+ | |
delegate :message, :to => :tenant_info_sheet | |
delegate :has_valid_payment_method?, :to => :property | |
has_defaults :host_reminder_sent => false, :review_reminder_sent => false, :host_sms_sent => false | |
def self.for_bulk_charge(options = {}) | |
- scope = chain_safely.scoped(:conditions => { :cc_charged => 'authorised' }).chain_safely | |
+ scope = chain_safely.scoped(:conditions => "bookings.id IN (SELECT payments.booking_id FROM payments WHERE payments.cc_charged = 'authorised' AND payments.booking_id = bookings.id)").chain_safely | |
if options[:all] | |
scope | |
elsif options[:ids].present? | |
@@ -185,7 +194,7 @@ class Booking < ActiveRecord::Base | |
def confirm! | |
self.pending = false | |
self.created_at = Time.now.utc | |
- self.cc_charged = 'authorised' | |
+ self.initial_payment.authorise! | |
if agency_booking? | |
self.status = 'requested_from_agency' | |
# Although we don't care when the Agency booking fails at this point, | |
@@ -204,25 +213,24 @@ class Booking < ActiveRecord::Base | |
user.confirm_email! | |
end | |
- def payment_faked? | |
- payment_faked_option.present? | |
- end | |
- | |
def fake_payment!(payment_faked_option) | |
if pending? | |
confirm! | |
end | |
- payment_faked_attributes = {:cc_charged => 'X', :payment_faked_option => payment_faked_option} | |
- payment_faked_attributes.merge!(:credit_card_cost => 0, :money_kept_by_adyen =>0) if ['fake_2', 'fake_3', 'fake_4'].include?(payment_faked_option) | |
- payment_faked_attributes.merge!(:payment_in_advance_amount => 0, :payment_in_advance_at => nil, | |
- :regular_payment_at => nil) if ['fake_3', 'fake_4'].include?(payment_faked_option) | |
- payment_faked_attributes.merge!(:total_price_of_stay_for_host => 0) if ['fake_3'].include?(payment_faked_option) | |
- payment_faked_attributes.merge!(:credit_card_fee_amount => 0, :pre_reduction_commission_amount => 0, :total_price_of_stay => total_price_of_stay_for_host) if payment_faked_option == 'fake_4' | |
- update_attributes! payment_faked_attributes | |
+ booking_faked_attributes = {} | |
+ payment_attributes = { :cc_charged => 'X', :payment_faked_option => payment_faked_option } | |
+ payment_attributes.merge!(:credit_card_cost => 0, :money_kept_by_adyen =>0) if ['fake_2', 'fake_3', 'fake_4'].include?(payment_faked_option) | |
+ booking_faked_attributes.merge!(:payment_in_advance_amount => 0, :payment_in_advance_at => nil, :regular_payment_at => nil) if ['fake_3', 'fake_4'].include?(payment_faked_option) | |
+ payment_attributes.merge!(:total_price_of_stay_for_host => 0) if ['fake_3'].include?(payment_faked_option) | |
+ payment_attributes.merge!(:credit_card_fee_amount => 0, :pre_reduction_commission_amount => 0, :total_price_of_stay => total_price_of_stay_for_host, | |
+ :commission_amount => 0) if payment_faked_option == 'fake_4' | |
+ update_attributes! booking_faked_attributes | |
+ initial_payment.update_attributes! payment_attributes | |
if payment_faked_option == 'fake_3' | |
settlement_amount = 0 - credit_card_fee_amount.to_f - commission_amount.to_f | |
create_or_update_settlement_booking!(:total_price_of_stay_for_host => settlement_amount, :regular_payment_amount => settlement_amount) | |
end | |
+ reload | |
end | |
def accept(strict = false, notify_kigo = false) | |
@@ -457,15 +465,16 @@ class Booking < ActiveRecord::Base | |
def valid_except_for_user? | |
self.skip_validation_of_user_id = true | |
- result = valid? | |
+ set_external_fields | |
+ result = if agency_booking? | |
+ valid? && initial_payment.total_price_of_stay.present? | |
+ else | |
+ valid? | |
+ end | |
self.skip_validation_of_user_id = false | |
result | |
end | |
- def usable_for_authorisation? | |
- !%w[accepted chargeback requested].include?(status) && !payment_faked? | |
- end | |
- | |
def violates_minimum_days_of_stay? | |
if check_in_date.present? and check_out_date.present? | |
minimum_days_of_stay_on_check_in_date = calendar_interface.minimum_days_of_stay_on_check_in_date | |
@@ -474,12 +483,12 @@ class Booking < ActiveRecord::Base | |
end | |
def authorisation_received(params) | |
- if payment | |
+ if initial_payment.psp_reference.present? | |
# we sometimes receive multiple confirmations from adyen and they can contain updated info | |
set_authorisation_data(params) | |
save(false) | |
else | |
- create_payment(:psp_reference => params[:pspReference]) | |
+ initial_payment.update_attributes(:psp_reference => params[:pspReference]) | |
set_authorisation_data(params) | |
confirm! | |
end | |
@@ -490,23 +499,10 @@ class Booking < ActiveRecord::Base | |
self.merchant_account_code = params[:merchantAccountCode] | |
end | |
- def capture_received(params) | |
- if params[:success] == 'true' | |
- update_attribute :cc_charged, 'Charged AD' | |
- payment.captured_amount = params[:value].to_f / 100 | |
- payment.captured_at = Time.zone.now | |
- payment.save(false) | |
- else | |
- update_attribute :cc_charged, 'rejected' unless cc_charged == 'Charged AD' || cc_charged == 'Charged GC' | |
- end | |
- end | |
- | |
def clear_payment_caches! | |
+ #reload # do not reload, as it will let a new booking offer fail. | |
# clear frozen caches (forces them to recalculate) | |
- self.update_attribute(:total_price_of_stay, nil) | |
- self.update_attribute(:commissionable_amount_for_guest, nil) | |
- self.update_attribute(:pre_reduction_commission_amount, nil) | |
- self.update_attribute(:credit_card_fee_amount, nil) | |
+ initial_payment.recalculate! | |
# clear other caches | |
update_cache! | |
end | |
@@ -534,31 +530,12 @@ class Booking < ActiveRecord::Base | |
self.booking_tests << booking_test | |
end | |
- def human_booking_status(custom_status = status) | |
- hours = Object.new.tap { |helper| helper.extend ActionView::Helpers::TextHelper }.pluralize(hours_left_for_host_response.to_f, _('hour'), _('hours')) | |
- case custom_status | |
- when 'requested' then _('Awaiting response from host (%{hours} left)') % { :hours => hours } | |
- when 'accepted' then _('Accepted by host') | |
- when 'cancelled' then _('Cancelled') | |
- when 'denied' then _('Denied by host') | |
- when 'no_response' then _('Cancelled (no response from host)') | |
- when 'cancelled_by_host' then _('Cancelled by the host') | |
- when 'cancelled_by_guest' then _('Cancelled by the guest') | |
- when 'cancelled_by_housetrip' then _('Cancelled by HouseTrip') | |
- when 'additional_payment' then _('Additional payment') | |
- when 'chargeback' then _('Chargeback') | |
- when 'to be settled' then _('To be settled') | |
- when 'settled' then _('Settled') | |
- when 'requested_from_agency' then _('Agency booking requested (not confirmed yet)') | |
- when 'agency_booking_failed_because_of_api' then _('Agency booking failed (API)') | |
- when 'agency_booking_failed_because_of_validation' then _('Agency booking failed (validation)') | |
- end | |
+ def set_booking_key | |
+ self.booking_key ||= EventKeyGenerator.generate(self.booking_message) | |
end | |
- private | |
- | |
def set_no_payment_info | |
- self.payment_on_hold = INVALID_PAYMENT_INFO if status_changed? && accepted? | |
+ initial_payment.payment_on_hold = INVALID_PAYMENT_INFO if status_changed? && accepted? | |
end | |
def calendar_interface | |
@@ -588,8 +565,8 @@ class Booking < ActiveRecord::Base | |
end | |
def set_money_fields | |
- self.currency_code ||= property.andand.currency_code | |
- freeze_exchange_rate! | |
+ self.initial_payment.currency_code = property.andand.currency_code | |
+ initial_payment.freeze_exchange_rate! | |
end | |
def set_attributes | |
@@ -697,8 +674,11 @@ class Booking < ActiveRecord::Base | |
end | |
def build_status_change_event | |
- prev_status_name = human_booking_status(status_was) || status_was.to_s.titleize | |
- curr_status_name = human_booking_status(status) || status.to_s.titleize | |
+ helper = Object.new | |
+ helper.extend BookingsHelper | |
+ helper.extend ActionView::Helpers::TextHelper | |
+ prev_status_name = helper.human_booking_status(self, status_was) || status_was.to_s.titleize | |
+ curr_status_name = helper.human_booking_status(self, status) || status.to_s.titleize | |
event_message = if status_was | |
"Status changed from `%s' to `%s'" % [prev_status_name, curr_status_name] | |
else |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment