-
-
Save jferris/b0a7a2debdf54213f164 to your computer and use it in GitHub Desktop.
Refactoring from the Weekly Iteration http://forum.thoughtbot.com/t/balancing-negative-numbers-from-text/1700/8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FastOrderParser | |
attr_reader :errors | |
def initialize(user, lines) | |
@user = user | |
@lines = lines | |
@errors = [] | |
end | |
def parse | |
FastOrderLine.transaction do | |
orders = lines.map.each_with_index do |line, index| | |
line.chomp! | |
vending_layout = /^(.+\/\d+\/\d+)\|(\d\d-\d\d-\d\d)\|(-?\d+)\|([^|]+)\|([^|]+)$/ | |
if line.match(vending_layout) | |
line = line.match(vending_layout).to_a | |
all, location, prnum, qty, ref1, ref2 = line | |
entry = FastOrderLine.find_by_entered_prnum_and_checkoutref3_and_user_id_and_checkoutref1(prnum, ref1, user.id, location) | |
if entry | |
existing_qty = entry.qty | |
entry.update_attributes(qty: existing_qty.to_i + qty.to_i) | |
else | |
FastOrderLine.create!({ | |
entered_prnum: prnum, | |
qty: qty, | |
vat_rate: Cart.default_vat_rate, | |
line_vat: 0, | |
product_id: 0, | |
price: 0.0, | |
selling_unit: 1, | |
special_id: 0, | |
user_id: user.id, | |
checkoutref1: location, | |
checkoutref3: ref1, | |
checkoutref4: ref2 | |
}) | |
end | |
else | |
errors << "There was an error on line #{index + 1}" | |
errors << "#{line}" | |
end | |
end | |
negative_qtys = FastOrderLine.where('qty < 0') | |
if !negative_qtys.empty? | |
errors << "You have a negative quantity(s), please fix it, and retry." | |
end | |
if !errors.empty? | |
raise ActiveRecord::Rollback | |
end | |
zero_qtys = FastOrderLine.where(qty: 0, user_id: user.id) | |
zero_qtys.destroy_all if zero_qtys | |
end | |
end | |
private | |
attr_reader :lines, :user | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe FastOrderParser do | |
context "#parse" do | |
it 'creates a fast order line for each parsed line' do | |
parse <<-LINES | |
F1234/0/1|11-87-17|1|JOHN DOE|COMPANY | |
F1234/0/1|11-87-38|1|JOHN DOE|COMPANY | |
LINES | |
expect(fast_order_attributes).to eq([ | |
{ | |
entered_prnum: '11-87-17', | |
qty: 1, | |
checkoutref1: 'F1234/0/1', | |
checkoutref3: 'JOHN DOE', | |
checkoutref4: 'COMPANY' | |
}, | |
{ | |
entered_prnum: '11-87-38', | |
qty: 1, | |
checkoutref1: 'F1234/0/1', | |
checkoutref3: 'JOHN DOE', | |
checkoutref4: 'COMPANY' | |
} | |
]) | |
end | |
it 'sets default attributes' do | |
default_attributes = { | |
vat_rate: Cart.default_vat_rate, | |
line_vat: 0, | |
product_id: 0, | |
price: 0.0, | |
selling_unit: 1, | |
special_id: 0, | |
user_id: stub_user.id, | |
} | |
parse <<-LINES | |
F1234/0/1|11-87-17|1|JOHN DOE|COMPANY | |
LINES | |
order_attributes = FastOrderLine. | |
last. | |
attributes. | |
symbolize_keys. | |
slice(*default_attributes.keys) | |
expect(order_attributes).to eq(default_attributes) | |
end | |
it 'combines multiple lines for the same product' do | |
parse <<-LINES | |
F1234/0/1|11-87-17|1|JOHN DOE|COMPANY | |
F1234/0/1|11-87-38|1|JOHN DOE|COMPANY | |
F1234/0/1|11-87-38|1|JOHN DOE|COMPANY | |
LINES | |
expect(fast_order_attributes).to eq([ | |
{ | |
entered_prnum: '11-87-17', | |
qty: 1, | |
checkoutref1: 'F1234/0/1', | |
checkoutref3: 'JOHN DOE', | |
checkoutref4: 'COMPANY' | |
}, | |
{ | |
entered_prnum: '11-87-38', | |
qty: 2, | |
checkoutref1: 'F1234/0/1', | |
checkoutref3: 'JOHN DOE', | |
checkoutref4: 'COMPANY' | |
} | |
]) | |
end | |
it 'returns errors for invalid lines' do | |
parser = parse <<-LINES | |
F1234/0/1|11-87-17|1|JOHN DOE|COMPANY | |
invalid line | |
LINES | |
expect(FastOrderLine.count).to eq(0) | |
expect(parser.errors).to eq([ | |
'There was an error on line 2', | |
'invalid line' | |
]) | |
end | |
it 'returns errors for negative lines' do | |
parser = parse <<-LINES | |
F1234/0/1|11-87-38|1|JOHN DOE|COMPANY | |
F1234/0/1|11-87-38|-1|JOHN DOE|COMPANY | |
F1234/0/1|11-87-38|-1|JOHN DOE|COMPANY | |
LINES | |
expect(FastOrderLine.count).to eq(0) | |
expect(parser.errors).to eq([ | |
'You have a negative quantity(s), please fix it, and retry.' | |
]) | |
end | |
it 'removes purchases for zero quantities' do | |
parse <<-LINES | |
F1234/0/1|11-87-17|1|JOHN DOE|COMPANY | |
F1234/0/1|11-87-38|1|JOHN DOE|COMPANY | |
F1234/0/1|11-87-38|-1|JOHN DOE|COMPANY | |
LINES | |
expect(fast_order_attributes).to eq([ | |
{ | |
entered_prnum: '11-87-17', | |
qty: 1, | |
checkoutref1: 'F1234/0/1', | |
checkoutref3: 'JOHN DOE', | |
checkoutref4: 'COMPANY' | |
} | |
]) | |
end | |
end | |
def fast_order_attributes | |
compared_attributes = %w( | |
entered_prnum | |
qty | |
checkoutref1 | |
checkoutref3 | |
checkoutref4 | |
) | |
FastOrderLine. | |
all. | |
sort_by { |order| [order.entered_prnum, order.checkoutref1] }. | |
map(&:attributes). | |
map { |attributes| attributes.slice(*compared_attributes) }. | |
map { |attributes| attributes.symbolize_keys } | |
end | |
def parse(string) | |
lines = string.strip_heredoc.scan(/(.*\n)/).flatten | |
parser = FastOrderParser.new(stub_user, lines) | |
parser.parse | |
parser | |
end | |
def stub_user | |
double('user', id: 1) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FastOrdersController < ApplicationController | |
def process_vending | |
parser = FastOrderParser.new(current_user, params[:template1].lines) | |
parser.parse | |
flash[:import_errors] = parser.errors | |
redirect_to "/backoffice/fastorder" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment