1
0

Implement shipment reader

- Add shipment object
- Add object to represent invalid shipments
- Implement reader for the csv input format
This commit is contained in:
Tim Kächele 2021-03-05 21:42:09 +01:00
parent e169921c14
commit 66886e6ae6
6 changed files with 146 additions and 0 deletions

View File

@ -4,6 +4,10 @@ require 'planet_express/version'
require 'planet_express/shipping_option'
require 'planet_express/shipping_option_repository'
require 'planet_express/shipment'
require 'planet_express/invalid_shipment'
require 'planet_express/shipment_reader'
module PlanetExpress
class Error < StandardError; end
# Your code goes here...

View File

@ -0,0 +1,11 @@
module PlanetExpress
class InvalidShipment
def initialize(raw_string)
@raw_string = raw_string
end
def if_valid(&block)
return
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module PlanetExpress
class Shipment
attr_reader :date, :shipping_option, :discounts
def initialize(date, shipping_option)
@date = date
@shipping_option = shipping_option
@discounts = []
end
def if_valid(&block)
yield self
end
def add_discount(discount)
discounts.push(discount)
end
def inspect
"#{self.class.name} [#{date} #{shipping_option}]"
end
end
end

View File

@ -0,0 +1,40 @@
require 'csv'
module PlanetExpress
class ShipmentReader
include Enumerable
attr_reader :input, :shipping_option_repository
def initialize(input, shipping_option_repository)
@input = input
@shipping_option_repository = shipping_option_repository
end
def each
CSV.new(input, headers: false, col_sep: ' ').each do |row|
date = parse_date(row)
shipping_option = find_shipping_option(row)
if date.nil? || shipping_option.nil?
yield InvalidShipment.new(row.join(" "))
else
yield Shipment.new(date, shipping_option)
end
end
end
private
def find_shipping_option(row)
shipping_option_repository.find_by_provider_and_package_size(row[2], row[1])
end
def parse_date(row)
begin
return Date.iso8601(row[0])
rescue ArgumentError => _e
nil
end
end
end
end

21
spec/fixtures/shipment_input_file.txt vendored Normal file
View File

@ -0,0 +1,21 @@
2015-02-01 S MR
2015-02-02 S MR
2015-02-03 L LP
2015-02-05 S LP
2015-02-06 S MR
2015-02-06 L LP
2015-02-07 L MR
2015-02-08 M MR
2015-02-09 L LP
2015-02-10 L LP
2015-02-10 S MR
2015-02-10 S MR
2015-02-11 L LP
2015-02-12 M MR
2015-02-13 M LP
2015-02-15 S MR
2015-02-17 L LP
2015-02-17 S MR
2015-02-24 L LP
2015-02-29 CUSPS
2015-03-01 S MR

View File

@ -0,0 +1,45 @@
# frozen_string_literal: true
RSpec.describe PlanetExpress::ShipmentReader do
let(:shipping_option_repsitory) { PlanetExpress::ShippingOptionRepository.new }
let(:input) { '' }
subject { PlanetExpress::ShipmentReader.new(input, shipping_option_repsitory) }
describe '#each' do
context 'with a file' do
let(:input) { File.read(File.expand_path('../fixtures/shipment_input_file.txt', __FILE__)) }
let(:result) { subject.to_a }
it 'parses the file' do
expect(result.length).to eq(21)
expect(result.select { |item| item.instance_of?(PlanetExpress::Shipment) }.length).to eq(20)
expect(result.select { |item| item.instance_of?(PlanetExpress::InvalidShipment) }.length).to eq(1)
end
end
context 'with valid shipment' do
let(:input) { '2015-02-01 S MR' }
let(:result) { subject.to_a }
let(:shipment) { result.first }
it 'returns a parsed shipment' do
expect(shipment.date).to eq(Date.new(2015, 2, 1))
expect(shipment.shipping_option).to eq(PlanetExpress::ShippingOption.new('MR', 'S', 200))
end
end
context 'with an invalid shipment' do
let(:input) { '2015-02-29 CUSPS' }
let(:result) { subject.to_a }
let(:shipment) { result.first }
it 'returns an invalid shipment' do
expect(shipment).to be_an_instance_of(PlanetExpress::InvalidShipment)
end
end
end
end