Skip to content

Instantly share code, notes, and snippets.

@martink-io
Created November 15, 2018 02:04
Show Gist options
  • Save martink-io/0eb97eacb868c65338365635d12b7da4 to your computer and use it in GitHub Desktop.
Save martink-io/0eb97eacb868c65338365635d12b7da4 to your computer and use it in GitHub Desktop.
class JobItem < ApplicationRecord
VAT_RATE = 0.2
AMENDMENT_FORM_LABELS = ['Lateness', 'Full Refund'].freeze
AMENDMENT_TYPES = ['JobItems::Lateness', 'JobItems::Refund'].freeze
CHARGABLE_TYPES = ['JobItems::GuardBooking', 'JobItems::LateBookingPenalty'].freeze
REFUNDABLE_TYPES = ['JobItems::Lateness', 'JobItems::Refund'].freeze
PERCENTAGE_TYPES = ['JobItems::CancelationPenalty', 'JobItems::LateBookingPenalty'].freeze
HOURS_TYPES = ['JobItems::GuardBooking', 'JobItems::Lateness',].freeze
belongs_to :job
belongs_to :resource, polymorphic: true
has_one :job_item_payment, dependent: :destroy
has_one :payment, through: :job_item_payment, dependent: :destroy
validate :quantity_is_present
validate :guard_job_exists
validate :max_hours
validate :max_refund_exceeded
before_save :set_vat
def total_pay
if quantity.present?
if PERCENTAGE_TYPES.include?(type)
(((pay_rate * self.job.number_of_hours) * quantity) / 100.0).round(2)
else
(pay_rate * quantity).round(2)
end
end
end
def total_charge
if quantity.present?
if PERCENTAGE_TYPES.include?(type)
(((charge_rate * self.job.number_of_hours) * quantity) / 100.0).round(2)
else
(charge_rate * quantity).round(2)
end
end
end
def total
(total_charge + vat).round(2)
end
def quantity_is_present
errors[:hours] << "Please select a duration" unless quantity.present?
end
def guard_job_exists
errors[:guard_id] << "Please select a guard" unless resource.present?
end
def max_hours
return unless quantity.present?
if HOURS_TYPES.include?(type)
errors[:hours] << "The amount of hours can not exceed job's length#{self.job.number_of_hours}" if quantity > self.job.number_of_hours
end
end
def max_refund_exceeded
return unless quantity.present?
amendments_amount = self.job.job_items.where(type: REFUNDABLE_TYPES).map(&:total).sum
if amendments_amount > self.job.total_charge
errors[:base] << "You've exceeded maximum refundable amount"
end
end
def vat
vat = (total_charge * VAT_RATE).round(2)
end
private
def set_vat
vat = (total_charge * VAT_RATE).round(2)
end
end
@zainfur
Copy link

zainfur commented Nov 25, 2018

Why do you have to work add column for type - can you not work out from Type of JobItem what quantity will be?
i.e.
if JI is lateness - we know it is hrs.
If JI is Penalty we know it is %

In Java we can do something like this

Switch (TYPE){ //Type of JobItem

case Penalty, LBP, CancellationCharge: {
//% do percentage calculation
}
break;
case GuardBooking, Lateness: {
//This is always hours
}
break:

} //Close Switch

With this approach we don't need new column of % or hrs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment