order_optimizer 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +12 -1
- data/lib/order_optimizer.rb +13 -7
- data/lib/order_optimizer/sku.rb +7 -4
- data/lib/order_optimizer/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21b6b1f9358d26572d0f3fe4d2a237c2da2a217bbb5f2d241d7a98683a9a43e1
|
4
|
+
data.tar.gz: 29987d3e12a263c8f18acdcf6c1972dcfa91204ece002e1a778ccc72a38a2843
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32b08adac0ba68f5133e60506b72a2f969d2e5617fd02ab16e922a05088e0afb81294041d6cbf6762dc70e8877a522733dc6160bb5583a30f744d67668efbee7
|
7
|
+
data.tar.gz: e8808b19221863663091640750d3765fccbf9dea0a4191f8cb9b1d13c46f49a3fa47f7ba8f906efaaa7bf5f3a6f7f13873ccdf19a59fcd32e81025b409676300
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -72,7 +72,7 @@ cheapest_exact_order_for_58_units.total # => 322
|
|
72
72
|
cheapest_exact_order_for_58_units.skus # => { '10-pack' => 5, '1-pack' => 8 }
|
73
73
|
```
|
74
74
|
|
75
|
-
It is possible to define
|
75
|
+
It is possible to define discount prices with a minimum quantity:
|
76
76
|
|
77
77
|
```ruby
|
78
78
|
order_optimizer = OrderOptimizer.new(
|
@@ -100,6 +100,17 @@ order_optimizer.cheapest_order(required_qty: 29).skus
|
|
100
100
|
#=> { '20-pack' => 1, '10-discount' => 10 }
|
101
101
|
```
|
102
102
|
|
103
|
+
It is also possible to define discount prices with a maximum quantity:
|
104
|
+
```ruby
|
105
|
+
order_optimizer = OrderOptimizer.new(
|
106
|
+
'1-pack' => { quantity: 1, price_per_unit: 9 },
|
107
|
+
'10-pack' => { quantity: 10, price_per_unit: 8, max_quantity: 20 },
|
108
|
+
)
|
109
|
+
|
110
|
+
order_optimizer.cheapest_order(required_qty: 30).skus
|
111
|
+
#=> { '10-pack' => 2, '1-pack' => 10 }
|
112
|
+
```
|
113
|
+
|
103
114
|
If you're just interested in all possible order combinations:
|
104
115
|
|
105
116
|
```ruby
|
data/lib/order_optimizer.rb
CHANGED
@@ -32,19 +32,19 @@ class OrderOptimizer
|
|
32
32
|
|
33
33
|
skus.each do |sku|
|
34
34
|
orders.reject(&:complete?).each do |order|
|
35
|
-
count, remainder = count_and_remainder_for_sku(order.missing_qty, sku)
|
35
|
+
count, remainder, skip_increase = count_and_remainder_for_sku(order.missing_qty, sku)
|
36
36
|
|
37
37
|
orders << order.dup.add(sku, count: count) unless count.zero?
|
38
|
-
orders << order.dup.add(sku, count: count + 1) unless remainder.zero?
|
38
|
+
orders << order.dup.add(sku, count: count + 1) unless remainder.zero? || skip_increase
|
39
39
|
end
|
40
40
|
|
41
|
-
count, remainder = count_and_remainder_for_sku(required_qty, sku)
|
41
|
+
count, remainder, skip_increase = count_and_remainder_for_sku(required_qty, sku)
|
42
42
|
|
43
43
|
unless count.zero?
|
44
44
|
orders << OrderOptimizer::Order.new(required_qty: required_qty).add(sku, count: count)
|
45
45
|
end
|
46
46
|
|
47
|
-
unless remainder.zero?
|
47
|
+
unless remainder.zero? || skip_increase
|
48
48
|
orders << OrderOptimizer::Order.new(required_qty: required_qty).add(sku, count: count + 1)
|
49
49
|
end
|
50
50
|
end
|
@@ -55,12 +55,18 @@ class OrderOptimizer
|
|
55
55
|
def count_and_remainder_for_sku(quantity, sku)
|
56
56
|
count, remainder = quantity.divmod(sku.quantity)
|
57
57
|
|
58
|
-
if sku.
|
58
|
+
if sku.max_quantity && count * sku.quantity > sku.max_quantity
|
59
|
+
new_count = (sku.max_quantity / sku.quantity).ceil
|
60
|
+
remainder = (count - new_count) * sku.quantity
|
61
|
+
|
62
|
+
[new_count, [remainder, 0].max, true]
|
63
|
+
elsif sku.min_quantity && count * sku.quantity < sku.min_quantity
|
59
64
|
new_count = (sku.min_quantity / sku.quantity).ceil
|
60
65
|
remainder -= (new_count - count) * sku.quantity
|
61
|
-
|
66
|
+
|
67
|
+
[new_count, [remainder, 0].max, false]
|
62
68
|
else
|
63
|
-
[count, remainder]
|
69
|
+
[count, remainder, false]
|
64
70
|
end
|
65
71
|
end
|
66
72
|
end
|
data/lib/order_optimizer/sku.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
class OrderOptimizer
|
2
2
|
class Sku
|
3
|
-
attr_reader :id, :quantity, :price_per_unit, :price_per_sku, :min_quantity
|
3
|
+
attr_reader :id, :quantity, :price_per_unit, :price_per_sku, :min_quantity, :max_quantity
|
4
4
|
|
5
|
-
def initialize(id, quantity:, price_per_sku: nil, price_per_unit: nil, min_quantity: nil)
|
5
|
+
def initialize(id, quantity:, price_per_sku: nil, price_per_unit: nil, min_quantity: nil, max_quantity: nil)
|
6
6
|
@id = id
|
7
7
|
@quantity = BigDecimal(quantity, 2)
|
8
8
|
@min_quantity = BigDecimal(min_quantity, 2) if min_quantity
|
9
|
+
@max_quantity = BigDecimal(max_quantity, 2) if max_quantity
|
9
10
|
|
10
|
-
|
11
|
-
raise '
|
11
|
+
if min_quantity && max_quantity && (min_quantity > max_quantity)
|
12
|
+
raise ArgumentError, "min_quantity can't be larger than max_quantity"
|
12
13
|
end
|
13
14
|
|
15
|
+
raise ArgumentError, ':price_per_sku or :price_per_unit must be set' unless price_per_unit || price_per_sku
|
16
|
+
|
14
17
|
@price_per_unit = BigDecimal(price_per_unit, 2) if price_per_unit
|
15
18
|
@price_per_unit ||= BigDecimal(price_per_sku, 2) / quantity
|
16
19
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: order_optimizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- crispymtn
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-04-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -101,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
103
|
requirements: []
|
104
|
-
rubygems_version: 3.2.
|
104
|
+
rubygems_version: 3.2.15
|
105
105
|
signing_key:
|
106
106
|
specification_version: 4
|
107
107
|
summary: Helps to optimize orders if the goods are offered in different pack sizes
|