Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/bill_recognizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ def calculate_attributes(version)
end

def calculate_amounts
# First: Remove false positives
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No comment please 🙈
If you want to make it super clear why you have these grouped, then make a separate method that runs these two like

def remove_false_positives
    PriceCalculation.remove_quantities
    PriceCalculation.remove_dates
end

The code should be so clear that it explains itself without comments 😉

You could also have one method in the price calculation for removing false positives. Seeing as other terms may soon have this too #369 it may be good to have these defined in the calculations and then call the methods from one method before all the calculations. What do you think? 😊

PriceCalculation.remove_quantities
PriceCalculation.remove_dates

amounts = []
prices = PriceCalculation.new
return amounts if prices.net_amount.nil?
Expand Down
18 changes: 18 additions & 0 deletions lib/calculations/price_calculation.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# frozen_string_literal: true
require 'bigdecimal'
require_relative '../models/dimensionable'

class PriceCalculation
include Dimensionable
def net_amount
return nil if PriceTerm.empty?
calculate unless @net_amount
Expand All @@ -14,6 +16,22 @@ def vat_amount
@vat_amount * 100
end

def self.remove_quantities
%w(Menge Anz.).each do |quantity_text|
quantity = Word.first(text: quantity_text)
next unless quantity
PriceTerm.each do |term|
term.destroy if in_same_column(quantity, term)
end
end
end

def self.remove_dates
PriceTerm.each do |term|
term.destroy if Word.two_words_after_matches?(term, /\./, /^\d{2}$/)
end
end

private

def calculate
Expand Down
2 changes: 0 additions & 2 deletions lib/detectors/price_detector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ def self.filter_out_dates

def self.filter
find_prices(DECIMAL_PRICE_REGEX, max_words: 3)
filter_out_quantity_column
filter_out_dates

end_word_with_space = ->(term) { term.text += ' ' }
unless Word.where(text: CurrencyDetector::HUF_SYMBOLS).empty?
Expand Down
188 changes: 188 additions & 0 deletions spec/calculations/price_calculation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,194 @@
expect(prices.vat_amount).to eq BigDecimal('0')
end

it 'removes detected pieces as prices' do
# From 29pwjsKx88nhnQKm9.pdf
create(
:word,
text: 'Menge',
left: 0.5791884816753927,
right: 0.6292539267015707,
top: 0.42298797409805733,
bottom: 0.4338575393154487
)

PriceTerm.create(
text: '1,00',
left: 0.5978403141361257,
right: 0.6243455497382199,
top: 0.4551341350601295,
bottom: 0.4641535615171138
)

PriceTerm.create(
text: '8,50',
left: 0.6861910994764397,
right: 0.7143324607329843,
top: 0.4551341350601295,
bottom: 0.4641535615171138
)

PriceTerm.create(
text: '2,00',
left: 0.5965314136125655,
right: 0.6243455497382199,
top: 0.48149861239592967,
bottom: 0.49051803885291395
)

PriceTerm.create(
text: '12,00',
left: 0.8900523560209425,
right: 0.925392670157068,
top: 0.48149861239592967,
bottom: 0.49051803885291395
)

PriceTerm.create(
text: '1,00',
left: 0.5978403141361257,
right: 0.6243455497382199,
top: 0.5212765957446809,
bottom: 0.5302960222016652
)

PriceTerm.create(
text: '4,00',
left: 0.6858638743455497,
right: 0.7143324607329843,
top: 0.5212765957446809,
bottom: 0.5302960222016652
)

PriceCalculation.remove_quantities
expect(price_strings).to eq ['8,50', '12,00', '4,00']
end

it 'removes numbers below Anz.' do
# From ihfDXTa64yYbFLa6Y.pdf
create(
:word,
text: 'Anz.',
left: 0.1197252208047105,
right: 0.1573438011122015,
top: 0.475937066173068,
bottom: 0.4854234150856085
)

PriceTerm.create(
text: '32,00',
left: 0.1122015047432123,
right: 0.1573438011122015,
top: 0.5016196205460435,
bottom: 0.512494215640907
)

PriceCalculation.remove_quantities
expect(price_strings).to be_empty
end

it 'deletes prices which are not in part of a quantity' do
# From rDxLnivxoXQw9nWa7.pdf
create(
:word,
text: 'Menge',
left: 0.5785340314136126,
right: 0.6285994764397905,
top: 0.4225254394079556,
bottom: 0.4333950046253469
)

PriceTerm.create(
text: '1,00',
left: 0.5971858638743456,
right: 0.6236910994764397,
top: 0.5074005550416282,
bottom: 0.5164199814986123
)

PriceTerm.create(
text: '1,00',
left: 0.5971858638743456,
right: 0.6236910994764397,
top: 0.5208140610545791,
bottom: 0.5298334875115633
)

PriceTerm.create(
text: '5,00',
left: 0.6855366492146597,
right: 0.7136780104712042,
top: 0.5208140610545791,
bottom: 0.5298334875115633
)

PriceTerm.create(
text: '431,25',
left: 0.09325916230366492,
right: 0.1387434554973822,
top: 0.8237742830712304,
bottom: 0.8327937095282146
)

PriceTerm.create(
text: '86,25',
left: 0.21171465968586387,
right: 0.24803664921465968,
top: 0.8237742830712304,
bottom: 0.8327937095282146
)

PriceTerm.create(
text: '517,50',
left: 0.837696335078534,
right: 0.8828534031413613,
top: 0.8237742830712304,
bottom: 0.8327937095282146
)

PriceCalculation.remove_quantities
expect(price_strings).to eq ['5,00', '431,25', '86,25', '517,50']
end

it 'deletes detected date as price' do
# From C5sri9hxpbDhha68D.png
# Dummy dimension values for the bill
BillDimension.create_image_dimensions(width: 3056, height: 4324)

PriceTerm.create(
text: '10.05',
left: 0.521978021978022,
right: 0.6131868131868132,
top: 0.724,
bottom: 0.737
)

create(
:word,
text: '.',
left: 0.6230769230769231,
right: 0.6263736263736264,
top: 0.735,
bottom: 0.737
)

create(
:word,
text: '17',
left: 0.6373626373626373,
right: 0.6703296703296703,
top: 0.724,
bottom: 0.7375
)

PriceCalculation.remove_dates
expect(price_strings).to be_empty
end

def price_strings
PriceTerm.map(&:to_s)
end

def word(attributes = {})
double(:word,
text: attributes[:text],
Expand Down
Loading