-
-
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 |
def total_charge
if quantity.present?
if PERCENTAGE_TYPES.include?(type)
percentage = (quantity / 100.0).round(2)
(charge_rate * self.job.number_of_hours * percentage).round(2)
else if HOURS_TYPES.include?(type) //Put this in - to future proof incase in future we have more - maybe a switch stamens will be better.
(charge_rate * quantity).round(2)
end
end
end
JobItem should have Qty, total, vat etc.
Because of this I have the following situation:
GB -> 100 (qty - 9.5 h)
LBP -> 25 (qty - 25%)(On cancelling unfilled job)
Refund -> 100 (qty - 9.5) - correct
Refund -> charge_rate(10.52) * qty(25) -> 250+ - wrong //Z: Can't we look at type and determine if % or not?
For last bit
refund = totalOfJobItem x -1. - will give you negative of refund.
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.
Could you have a look at the total_charge method?
I have an issue with the JobItems::Refund item.
The issue is that this will accept both hour for quantity or %, depending on the case. At the moment the JobItems::Refund item is not in the PERCENTAGE_TYPES or HOUR_TYPES since it could be in both.
Because of this I have the following situation:
GB -> 100 (qty - 9.5 h)
LBP -> 25 (qty - 25%)
(On cancelling unfilled job)
Refund -> 100 (qty - 9.5) - correct
Refund -> charge_rate(10.52) * qty(25) -> 250+ - wrong
The last refund item should use the % way of calculating its total_charge value. Any ideas?