Skip to content
This repository has been archived by the owner on Nov 22, 2017. It is now read-only.

Commit

Permalink
Add TradeTariffBackend::NumberFormatter
Browse files Browse the repository at this point in the history
Helps format duty expression amounts. Cases:

* If we have 0.3435 we want this exact number => 0.3435
* If we have 0.34528 we want it rounded to 4 precision points => 0.3453
* If we have 0.23 we want to leave it as it is => 0.23
* If we have 0.2 we want add single leading zero => 0.20
* If we have 1 we want to add two leading zeros => 1.00
  • Loading branch information
saulius committed Nov 7, 2013
1 parent e934adc commit cf6fa3b
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 79 deletions.
124 changes: 65 additions & 59 deletions app/formatters/duty_expression_formatter.rb
Original file line number Diff line number Diff line change
@@ -1,68 +1,74 @@
class DutyExpressionFormatter
class << self
def prettify(float)
TradeTariffBackend.number_formatter.number_with_precision(
float,
minimum_decimal_points: 2,
precision: 4,
strip_insignificant_zeros: true
)
end

def self.prettify(float)
sprintf("%.2f", float)
end

def self.format(opts={})
duty_expression_id = opts[:duty_expression_id]
duty_expression_description = opts[:duty_expression_description]
duty_expression_abbreviation = opts[:duty_expression_abbreviation]
duty_amount = opts[:duty_amount]
monetary_unit = opts[:monetary_unit_abbreviation].presence || opts[:monetary_unit]
measurement_unit = opts[:measurement_unit]
measurement_unit_qualifier = opts[:formatted_measurement_unit_qualifier]
def format(opts={})
duty_expression_id = opts[:duty_expression_id]
duty_expression_description = opts[:duty_expression_description]
duty_expression_abbreviation = opts[:duty_expression_abbreviation]
duty_amount = opts[:duty_amount]
monetary_unit = opts[:monetary_unit_abbreviation].presence || opts[:monetary_unit]
measurement_unit = opts[:measurement_unit]
measurement_unit_qualifier = opts[:formatted_measurement_unit_qualifier]

output = []
output = []

case duty_expression_id
when "99"
output << measurement_unit
when "12", "14", "37", "40", "41", "42", "43", "44", "21", "25", "27", "29"
if duty_expression_abbreviation.present?
output << duty_expression_abbreviation
elsif duty_expression_description.present?
output << duty_expression_description
end
when "02", "04", "15", "17", "19", "20", "36"
if duty_expression_abbreviation.present?
output << duty_expression_abbreviation
elsif duty_expression_description.present?
output << duty_expression_description
end
if duty_amount.present?
output << prettify(duty_amount).to_s
end
if monetary_unit.present?
output << monetary_unit
case duty_expression_id
when "99"
output << measurement_unit
when "12", "14", "37", "40", "41", "42", "43", "44", "21", "25", "27", "29"
if duty_expression_abbreviation.present?
output << duty_expression_abbreviation
elsif duty_expression_description.present?
output << duty_expression_description
end
when "02", "04", "15", "17", "19", "20", "36"
if duty_expression_abbreviation.present?
output << duty_expression_abbreviation
elsif duty_expression_description.present?
output << duty_expression_description
end
if duty_amount.present?
output << prettify(duty_amount).to_s
end
if monetary_unit.present?
output << monetary_unit
else
output << "%"
end
if measurement_unit.present? && measurement_unit_qualifier.present?
output << "/ (#{measurement_unit}/#{measurement_unit_qualifier})"
elsif measurement_unit.present?
output << "/ #{measurement_unit}"
end
else
output << "%"
end
if measurement_unit.present? && measurement_unit_qualifier.present?
output << "/ (#{measurement_unit}/#{measurement_unit_qualifier})"
elsif measurement_unit.present?
output << "/ #{measurement_unit}"
end
else
if duty_amount.present?
output << prettify(duty_amount).to_s
end
if duty_expression_abbreviation.present? && !monetary_unit.present?
output << duty_expression_abbreviation
elsif duty_expression_description.present? && !monetary_unit.present?
output << duty_expression_description
elsif duty_expression_description.blank?
output << "%"
end
if monetary_unit.present?
output << monetary_unit
end
if measurement_unit.present? && measurement_unit_qualifier.present?
output << "/ (#{measurement_unit}/#{measurement_unit_qualifier})"
elsif measurement_unit.present?
output << "/ #{measurement_unit}"
if duty_amount.present?
output << prettify(duty_amount).to_s
end
if duty_expression_abbreviation.present? && !monetary_unit.present?
output << duty_expression_abbreviation
elsif duty_expression_description.present? && !monetary_unit.present?
output << duty_expression_description
elsif duty_expression_description.blank?
output << "%"
end
if monetary_unit.present?
output << monetary_unit
end
if measurement_unit.present? && measurement_unit_qualifier.present?
output << "/ (#{measurement_unit}/#{measurement_unit_qualifier})"
elsif measurement_unit.present?
output << "/ #{measurement_unit}"
end
end
output.join(" ").html_safe
end
output.join(" ").html_safe
end
end
45 changes: 26 additions & 19 deletions app/formatters/requirement_duty_expression_formatter.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
class RequirementDutyExpressionFormatter
def self.prettify(float)
sprintf("%.2f", float)
end
class << self
def prettify(float)
TradeTariffBackend.number_formatter.number_with_precision(
float,
precision: 4,
minimum_decimal_points: 2,
strip_insignificant_zeros: true
)
end

def self.format(opts={})
duty_amount = opts[:duty_amount]
monetary_unit = opts[:monetary_unit_abbreviation].presence || opts[:monetary_unit]
measurement_unit = opts[:measurement_unit]
measurement_unit_qualifier = opts[:formatted_measurement_unit_qualifier]
def format(opts={})
duty_amount = opts[:duty_amount]
monetary_unit = opts[:monetary_unit_abbreviation].presence || opts[:monetary_unit]
measurement_unit = opts[:measurement_unit]
measurement_unit_qualifier = opts[:formatted_measurement_unit_qualifier]

output = []
output = []

if duty_amount.present?
output << prettify(duty_amount).to_s
end
if duty_amount.present?
output << prettify(duty_amount).to_s
end

if monetary_unit.present? && measurement_unit.present? && measurement_unit_qualifier.present?
output << "#{monetary_unit}/(#{measurement_unit}/#{measurement_unit_qualifier})"
elsif monetary_unit.present? && measurement_unit.present?
output << "#{monetary_unit}/#{measurement_unit}"
elsif measurement_unit.present?
output << measurement_unit
if monetary_unit.present? && measurement_unit.present? && measurement_unit_qualifier.present?
output << "#{monetary_unit}/(#{measurement_unit}/#{measurement_unit_qualifier})"
elsif monetary_unit.present? && measurement_unit.present?
output << "#{monetary_unit}/#{measurement_unit}"
elsif measurement_unit.present?
output << measurement_unit
end
output.join(" ").html_safe
end
output.join(" ").html_safe
end
end
7 changes: 6 additions & 1 deletion lib/trade_tariff_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ module TradeTariffBackend
autoload :DataMigrator, 'trade_tariff_backend/data_migrator'
autoload :Indexer, 'trade_tariff_backend/indexer'
autoload :Mailer, 'trade_tariff_backend/mailer'
autoload :NumberFormatter, 'trade_tariff_backend/number_formatter'
autoload :SearchIndex, 'trade_tariff_backend/search_index'
autoload :Validator, 'trade_tariff_backend/validator'
autoload :Validator, 'trade_tariff_backend/validator'

class << self

Expand Down Expand Up @@ -76,6 +77,10 @@ def search_index
SearchIndex
end

def number_formatter
@number_formatter ||= TradeTariffBackend::NumberFormatter.new
end

private

def load_secrets
Expand Down
33 changes: 33 additions & 0 deletions lib/trade_tariff_backend/number_formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module TradeTariffBackend
class NumberFormatter
# NOTE: Port to ActiveSupport::NumberHelper when on Rails 4
include ActionView::Helpers::NumberHelper

# Extension to #number_with_precision that allows
# to have certain number of decimal zeros even
# when stripping of insignificant zeros is enabled
#
# E.g.:
#
# number_with_precision(1.2, minimum_decimal_points: 2) => '1.20'
# number_with_precision(1.2456, minimum_decimal_points: 2, precision: 4, strip_insignificant_zeros: true) => '1.2456'
# number_with_precision(1.3, minimum_decimal_points: 2, precision: 4, strip_insignificant_zeros: true) => '1.30'

def number_with_precision(number, opts = {})
minimum_decimal_points = opts.delete(:minimum_decimal_points)
formatted_number = super(number, opts)

if minimum_decimal_points && precision_for(formatted_number) < minimum_decimal_points
"%.#{minimum_decimal_points}f" % formatted_number.to_f
else
formatted_number
end
end

private

def precision_for(number)
number.to_f.to_s.split('.').last.size
end
end
end
14 changes: 14 additions & 0 deletions spec/formatters/duty_expression_formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,18 @@
end
end
end

describe '.prettify' do
context 'has less than 4 decimal places' do
it 'returns number with insignificant zeros stripped up to 2 decimal points' do
expect(DutyExpressionFormatter.prettify(1.2)).to eq '1.20'
end
end

context 'has 4 or more decimal places' do
it 'returns formatted number with 4 decimal places' do
expect(DutyExpressionFormatter.prettify(1.23456)).to eq '1.2346'
end
end
end
end
14 changes: 14 additions & 0 deletions spec/formatters/requirement_duty_expression_formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,18 @@
end
end
end

describe '.prettify' do
context 'has less than 4 decimal places' do
it 'returns number with insignificant zeros stripped up to 2 decimal points' do
expect(RequirementDutyExpressionFormatter.prettify(1.2)).to eq '1.20'
end
end

context 'has 4 or more decimal places' do
it 'returns formatted number with 4 decimal places' do
expect(RequirementDutyExpressionFormatter.prettify(1.23456)).to eq '1.2346'
end
end
end
end
49 changes: 49 additions & 0 deletions spec/unit/trade_tariff_backend/number_formatter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'spec_helper'

describe TradeTariffBackend::NumberFormatter do
let(:number_formatter) { described_class.new }

describe '#number_with_precision' do
context 'with minimum_decimal_points option' do
it 'adds leading zero decimal numbers up to specified count' do
expect(number_formatter.number_with_precision(1.2, minimum_decimal_points: 4)).to eq '1.2000'
expect(number_formatter.number_with_precision(1, minimum_decimal_points: 4)).to eq '1.0000'
expect(number_formatter.number_with_precision(1.23, minimum_decimal_points: 4)).to eq '1.2300'
end

context 'with precision specified' do
it 'rounds to specified precision and adds leading decimal numbers if needed' do
expect(
number_formatter.number_with_precision(
1.256,
minimum_decimal_points: 2,
precision: 1
)
).to eq '1.30'
end
end

context 'with stripping of insignificant zeros enabled' do
it 'strips insignificant zeroes up to minimum decimal points size' do
expect(
number_formatter.number_with_precision(
1.256,
minimum_decimal_points: 2,
precision: 1,
strip_insignificant_zeroes: true
)
).to eq '1.30'

expect(
number_formatter.number_with_precision(
1.25656,
minimum_decimal_points: 4,
precision: 3,
strip_insignificant_zeroes: true
)
).to eq '1.2570'
end
end
end
end
end

0 comments on commit cf6fa3b

Please sign in to comment.