Implement LP L discount rule
This commit is contained in:
parent
2f34945418
commit
6c4c9c75fe
@ -13,13 +13,14 @@ require 'planet_express/invalid_shipment'
|
||||
require 'planet_express/shipment'
|
||||
require 'planet_express/shipment_repository'
|
||||
require 'planet_express/shipment_reader'
|
||||
# require 'planet_express/shipment_formatter'
|
||||
|
||||
require 'planet_express/shipping_option'
|
||||
require 'planet_express/shipping_option_repository'
|
||||
|
||||
require 'planet_express/rule'
|
||||
require 'planet_express/s_shipment_discount_rule'
|
||||
# require 'planet_express/l_shipment_discount_rule'
|
||||
require 'planet_express/l_shipment_discount_rule'
|
||||
|
||||
require 'planet_express/shipment_discount_calculator'
|
||||
|
||||
|
39
lib/planet_express/l_shipment_discount_rule.rb
Normal file
39
lib/planet_express/l_shipment_discount_rule.rb
Normal file
@ -0,0 +1,39 @@
|
||||
module PlanetExpress
|
||||
class LShipmentDiscountRule < Rule
|
||||
protected
|
||||
|
||||
def applicable_to?(shipment)
|
||||
lp_provider_shipment?(shipment) &&
|
||||
third_l_shipment_in_month?(shipment) &&
|
||||
rule_not_applied_in_month_already?(shipment)
|
||||
end
|
||||
|
||||
def discount_for(shipment)
|
||||
Discount.new(discount_amount(shipment), self)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def lp_provider_shipment?(shipment)
|
||||
shipment.lp_provider?
|
||||
end
|
||||
|
||||
def third_l_shipment_in_month?(shipment)
|
||||
provider = shipment.provider
|
||||
month = shipment.month
|
||||
|
||||
count = shipment_repository.l_shipment_count_for_provider_and_month(provider,
|
||||
month)
|
||||
(count % 3) == 2
|
||||
end
|
||||
|
||||
def rule_not_applied_in_month_already?(shipment)
|
||||
!shipment_repository.rule_applied_in_month?(shipment.month, self.class)
|
||||
end
|
||||
|
||||
def discount_amount(shipment)
|
||||
desired_amount = price(shipment)
|
||||
discount_budget(shipment).maximum_possible_discount(desired_amount)
|
||||
end
|
||||
end
|
||||
end
|
@ -14,6 +14,18 @@ module PlanetExpress
|
||||
date.begin_of_month
|
||||
end
|
||||
|
||||
def price_with_discounts
|
||||
shipping_option.price_in_cents - total_discount_amount
|
||||
end
|
||||
|
||||
def total_discount_amount
|
||||
discounts.map(&:amount).sum
|
||||
end
|
||||
|
||||
def lp_provider?
|
||||
shipping_option.lp_provider?
|
||||
end
|
||||
|
||||
def s_shipment?
|
||||
shipping_option.s_shipment?
|
||||
end
|
||||
|
@ -10,6 +10,10 @@ module PlanetExpress
|
||||
package_size == 'L'
|
||||
end
|
||||
|
||||
def lp_provider?
|
||||
provider == 'LP'
|
||||
end
|
||||
|
||||
def inspect
|
||||
"ShippingOption [proivder=#{provider} package_size=#{package_size} price_in_cents=#{price_in_cents}]"
|
||||
end
|
||||
|
77
spec/l_shipment_discount_rule_spec.rb
Normal file
77
spec/l_shipment_discount_rule_spec.rb
Normal file
@ -0,0 +1,77 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe PlanetExpress::LShipmentDiscountRule do
|
||||
let(:budget_repo) { PlanetExpress::DiscountBudgetForMonthRepository.new }
|
||||
let(:shipping_option_repo) { PlanetExpress::ShippingOptionRepository.new }
|
||||
let(:shipment_repo) { PlanetExpress::ShipmentRepository.new(data: []) }
|
||||
|
||||
subject do
|
||||
described_class.new(
|
||||
discount_budget_for_month_repository: budget_repo,
|
||||
shipping_option_repository: shipping_option_repo,
|
||||
shipment_repository: shipment_repo)
|
||||
end
|
||||
|
||||
let(:correct_shipping_option) do
|
||||
shipping_option_repo.find_by_provider_and_package_size('LP', 'L')
|
||||
end
|
||||
|
||||
let(:applicable_shipment) do
|
||||
PlanetExpress::Shipment.new(Date.today, correct_shipping_option)
|
||||
end
|
||||
|
||||
context 'l_shipment' do
|
||||
context 'not the third shipment' do
|
||||
it 'does not apply the discount' do
|
||||
expect do
|
||||
subject.apply_to(applicable_shipment)
|
||||
end.to_not(change { applicable_shipment.discounts })
|
||||
end
|
||||
end
|
||||
|
||||
context 'third shipment for LP' do
|
||||
context 'LP provider' do
|
||||
before(:each) do
|
||||
shipment_repo.add(applicable_shipment)
|
||||
shipment_repo.add(applicable_shipment)
|
||||
end
|
||||
|
||||
it 'does apply the discount' do
|
||||
expect do
|
||||
subject.apply_to(applicable_shipment)
|
||||
end.to(change { applicable_shipment.discounts.length }.by(1))
|
||||
|
||||
discount = applicable_shipment.discounts.last
|
||||
expect(discount.amount).to eq(applicable_shipment.shipping_option.price_in_cents)
|
||||
end
|
||||
|
||||
it 'updates the discount budget' do
|
||||
expected_difference = -applicable_shipment.shipping_option.price_in_cents
|
||||
|
||||
expect do
|
||||
subject.apply_to(applicable_shipment)
|
||||
end.to(change { budget_repo.for_month(applicable_shipment.month).available_budget }.by(expected_difference))
|
||||
end
|
||||
end
|
||||
|
||||
context 'non LP provider' do
|
||||
before(:each) do
|
||||
shipment_repo.add(applicable_shipment)
|
||||
shipment_repo.add(applicable_shipment)
|
||||
end
|
||||
let(:shipping_option) do
|
||||
shipping_option_repo.find_by_provider_and_package_size('MR', 'L')
|
||||
end
|
||||
let(:shipment) do
|
||||
PlanetExpress::Shipment.new(Date.today, shipping_option)
|
||||
end
|
||||
|
||||
it 'does not update the discounts' do
|
||||
expect do
|
||||
subject.apply_to(shipment)
|
||||
end.to_not(change { shipment.discounts })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -32,4 +32,22 @@ RSpec.describe PlanetExpress::ShippingOption do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#lp_provider?' do
|
||||
context 'with LP provider' do
|
||||
subject { build(:shipping_option, provider: 'LP') }
|
||||
|
||||
it 'returns true' do
|
||||
expect(subject.lp_provider?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non L package size' do
|
||||
subject { build(:shipping_option, provider: 'MP') }
|
||||
|
||||
it 'returns false' do
|
||||
expect(subject.lp_provider?).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user