-
-
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 |
The issue is the the JobItem has Qty and total, but doesn't have a type. this is why I want to add the new column of type and then it would be easy. The whole issue just comes from the fact that Refund could be both of % and h type. New column will solve this instantly :)
Yes, we can use switch statement to determine TYPES and use different formula based on it. However, with the new column, we wouldn't need the immutable arrays (enums in Java) and will only switch(self.type) case '%', case 'h' and whatever we have later on
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.
JobItem should have Qty, total, vat etc.
For last bit