bakool 0.1.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5009031cd942deffbc62f4c505271d2da9fabf81779928e5f9210a280c4439d
4
- data.tar.gz: 6dfde5cdd258e3349488aeaee4312f0308072cbaf58b7f30c8358636b2ae9244
3
+ metadata.gz: 9f6b718a875f6d825342d460912a7c58d03263727f6e333b7d1b235906d1c1e9
4
+ data.tar.gz: 287a1c88f79cfd3408603a60a74de5a4b33374ad1f7f295419c3ca6620416271
5
5
  SHA512:
6
- metadata.gz: 6ad281d985e7ff08ca30a5f48878c5604df6eb62822f3f2a4d539d30ec34815117b881c2de08ce96cabb2e88547e3815418d68c10771b0e8473fbc662d670890
7
- data.tar.gz: 66e506ce07373e4d5d3b122e6349972d7c62e8f5fb68f09457f3371f550f9e10baffb62cb7929fc86563bbac6d00374dff7c4e18abda3bb1677989c41bdb7b37
6
+ metadata.gz: ec15dabe54e1dfffba8f6b57cd79ea392dbcbd97218e55388b4fee67ef05597302e9ceecff8f3114f054b0bd040d8ae48b3f0265dc3bae5522b6d71fda72b9cb
7
+ data.tar.gz: a503865557c9e83744cba6f209d8bfc21285b6caf3843e88da58fe58a234e56a3ecd9427e2db65543b28a60f0b4d2c2319fda615e000727cda4ece1d3eb7b113
data/README.md CHANGED
@@ -88,6 +88,114 @@ The gem comes with a default catalogue containing:
88
88
  | G01 | Green Widget | $24.95 |
89
89
  | B01 | Blue Widget | $7.95 |
90
90
 
91
+ ### Custom Catalogues
92
+
93
+ You can create your own custom catalogue with your own products. This is useful when you want to use different products or pricing than the default catalogue.
94
+
95
+ #### Creating a Custom Catalogue
96
+
97
+ ```ruby
98
+ # Create a new empty catalogue
99
+ catalogue = Bakool::Catalogue.new
100
+
101
+ # Add products to your catalogue
102
+ catalogue.add_product(Bakool::Product.new("Laptop", "LAP01", 999.99))
103
+ catalogue.add_product(Bakool::Product.new("Mouse", "MOU01", 25.50))
104
+ catalogue.add_product(Bakool::Product.new("Keyboard", "KEY01", 75.00))
105
+ catalogue.add_product(Bakool::Product.new("Monitor", "MON01", 299.99))
106
+
107
+ # Create a basket with your custom catalogue
108
+ basket = Bakool::Basket.new(catalogue: catalogue)
109
+
110
+ # Add products using your custom codes
111
+ basket.add("LAP01") # Laptop
112
+ basket.add("MOU01") # Mouse
113
+ basket.add("KEY01") # Keyboard
114
+
115
+ # Calculate total
116
+ total = basket.total
117
+ puts "Total: $#{total}"
118
+ ```
119
+
120
+ #### Complete Custom Catalogue Example
121
+
122
+ ```ruby
123
+ # Create a custom catalogue for an electronics store
124
+ electronics_catalogue = Bakool::Catalogue.new
125
+
126
+ # Add electronics products
127
+ electronics_catalogue.add_product(Bakool::Product.new("iPhone 15", "IPH15", 799.99))
128
+ electronics_catalogue.add_product(Bakool::Product.new("AirPods Pro", "AIRPODS", 249.99))
129
+ electronics_catalogue.add_product(Bakool::Product.new("MacBook Air", "MBA", 1199.99))
130
+ electronics_catalogue.add_product(Bakool::Product.new("iPad Air", "IPAD", 599.99))
131
+
132
+ # Create custom delivery charge rule for electronics
133
+ electronics_delivery = Bakool::DeliveryChargeRule.new(lambda do |order_total|
134
+ if order_total < 10000 then 995 # $9.95 for orders under $100
135
+ elsif order_total < 50000 then 495 # $4.95 for orders under $500
136
+ else 0 # Free delivery for orders $500+
137
+ end
138
+ end)
139
+
140
+ # Create custom discount for AirPods (buy one get one 25% off)
141
+ class AirPodsDiscount < Bakool::Discount
142
+ def calculate(basket)
143
+ airpods = basket.items.filter { |item| item.code == "AIRPODS" }
144
+ if airpods.count >= 2
145
+ # Apply 25% discount to every second AirPod
146
+ (airpods.count / 2) * (airpods.first.price_in_cents * 0.25)
147
+ else
148
+ 0
149
+ end
150
+ end
151
+ end
152
+
153
+ # Create basket with custom catalogue, delivery, and discount
154
+ basket = Bakool::Basket.new(
155
+ catalogue: electronics_catalogue,
156
+ delivery_charge_rule: electronics_delivery,
157
+ discount: AirPodsDiscount.new
158
+ )
159
+
160
+ # Add items
161
+ basket.add("IPH15") # iPhone 15
162
+ basket.add("AIRPODS") # AirPods Pro
163
+ basket.add("AIRPODS") # Second AirPods Pro (25% off)
164
+ basket.add("MBA") # MacBook Air
165
+
166
+ # Calculate total
167
+ total = basket.total
168
+ puts "Total: $#{total}"
169
+ ```
170
+
171
+ #### Catalogue API Reference
172
+
173
+ ##### `Bakool::Catalogue.new`
174
+
175
+ Creates a new empty catalogue.
176
+
177
+ ```ruby
178
+ catalogue = Bakool::Catalogue.new
179
+ ```
180
+
181
+ ##### `catalogue.add_product(product)`
182
+
183
+ Adds a product to the catalogue.
184
+
185
+ - `product` (Bakool::Product): Product object to add
186
+
187
+ ```ruby
188
+ catalogue.add_product(Bakool::Product.new("Product Name", "CODE", 29.99))
189
+ ```
190
+
191
+ ##### `Bakool::Catalogue.default_catalogue`
192
+
193
+ Returns a catalogue with the default products (Red Widget, Green Widget, Blue Widget).
194
+
195
+ ```ruby
196
+ default_catalogue = Bakool::Catalogue.default_catalogue
197
+ ```
198
+
91
199
  ### Custom Delivery Charges
92
200
 
93
201
  ```ruby
@@ -225,16 +333,28 @@ Manages the product inventory.
225
333
 
226
334
  Creates a new empty catalogue.
227
335
 
336
+ ```ruby
337
+ catalogue = Bakool::Catalogue.new
338
+ ```
339
+
228
340
  #### `catalogue.add_product(product)`
229
341
 
230
342
  Adds a product to the catalogue.
231
343
 
232
344
  - `product` (Bakool::Product): Product object to add
233
345
 
346
+ ```ruby
347
+ catalogue.add_product(Bakool::Product.new("Product Name", "CODE", 29.99))
348
+ ```
349
+
234
350
  #### `Bakool::Catalogue.default_catalogue`
235
351
 
236
352
  Returns a catalogue with default products (Red Widget, Green Widget, Blue Widget).
237
353
 
354
+ ```ruby
355
+ default_catalogue = Bakool::Catalogue.default_catalogue
356
+ ```
357
+
238
358
  ### DeliveryChargeRule
239
359
 
240
360
  Handles delivery charge calculations.
data/lib/bakool/basket.rb CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  # A shopping basket that can hold products and calculate totals with discounts and delivery charges
4
4
  module Bakool
5
+ # Represents a shopping basket that can hold products and calculate totals
6
+ # with discounts and delivery charges applied.
7
+ #
8
+ # @example
9
+ # basket = Bakool::Basket.new
10
+ # basket.add("R01")
11
+ # basket.add("G01")
12
+ # total = basket.total
13
+ #
14
+ # @attr_reader catalogue [Bakool::Catalogue] The product catalogue
15
+ # @attr_reader items [Array<Bakool::Product>] The items in the basket
16
+ # @attr_reader delivery_charge_rule [Bakool::DeliveryChargeRule] The delivery charge calculation rule
17
+ # @attr_reader discount [Bakool::Discount] The discount strategy to apply
5
18
  class Basket
6
19
  attr_accessor :catalogue, :items, :delivery_charge_rule, :discount_rule, :discount
7
20
 
@@ -2,6 +2,15 @@
2
2
 
3
3
  # A catalogue that holds a collection of products
4
4
  module Bakool
5
+ # Represents a catalogue that holds a collection of products.
6
+ # Provides methods to add products and retrieve the default catalogue.
7
+ #
8
+ # @example
9
+ # catalogue = Bakool::Catalogue.new
10
+ # catalogue.add_product(Bakool::Product.new("Widget", "W01", 10.00))
11
+ # default_catalogue = Bakool::Catalogue.default_catalogue
12
+ #
13
+ # @attr_reader products [Array<Bakool::Product>] The products in the catalogue
5
14
  class Catalogue
6
15
  attr_accessor :products
7
16
 
@@ -2,6 +2,17 @@
2
2
 
3
3
  # A rule that calculates delivery charges based on order total
4
4
  module Bakool
5
+ # Represents a rule that calculates delivery charges based on order total.
6
+ # Can be customized with a custom calculation function or use the default logic.
7
+ #
8
+ # @example
9
+ # rule = Bakool::DeliveryChargeRule.new
10
+ # charge = rule.calculate(5000) # 495 cents for orders over 0
11
+ #
12
+ # @example Custom rule
13
+ # custom_rule = Bakool::DeliveryChargeRule.new(->(total) { total > 5000 ? 0 : 1000 })
14
+ #
15
+ # @attr_reader func [Proc] The function that calculates delivery charges
5
16
  class DeliveryChargeRule
6
17
  attr_accessor :func
7
18
 
@@ -4,6 +4,14 @@ require_relative "discount"
4
4
 
5
5
  # Default discount strategy that applies no discount
6
6
  module Bakool
7
+ # Default discount strategy that applies no discount to the basket.
8
+ # This is the fallback discount strategy when no other discounts are applicable.
9
+ #
10
+ # @example
11
+ # discount = Bakool::DefaultDiscount.new
12
+ # amount = discount.calculate(basket) # Always returns 0
13
+ #
14
+ # @see Bakool::Discount
7
15
  class DefaultDiscount < Discount
8
16
  def calculate(_basket)
9
17
  0
@@ -2,6 +2,18 @@
2
2
 
3
3
  # Abstract base class for discount strategies
4
4
  module Bakool
5
+ # Abstract base class for discount strategies.
6
+ # Subclasses must implement the #calculate method to provide specific discount logic.
7
+ #
8
+ # @example
9
+ # class MyDiscount < Bakool::Discount
10
+ # def calculate(basket)
11
+ # # Custom discount logic here
12
+ # 1000 # Return discount amount in cents
13
+ # end
14
+ # end
15
+ #
16
+ # @abstract Subclasses must implement {#calculate}
5
17
  class Discount
6
18
  def calculate(basket)
7
19
  raise NotImplementedError, "Subclasses must implement this method"
@@ -2,6 +2,14 @@
2
2
 
3
3
  # Discount strategy that applies 50% off the second item of the same type
4
4
  module Bakool
5
+ # Discount strategy that applies 50% off the second item of the same type.
6
+ # This discount is applied when there are 2 or more items with the same product code.
7
+ #
8
+ # @example
9
+ # discount = Bakool::FiftyPercentOff2ndSameItemDiscount.new("R01")
10
+ # amount = discount.calculate(basket) # Returns discount amount in cents
11
+ #
12
+ # @see Bakool::Discount
5
13
  class FiftyPercentOff2ndSameItemDiscount < Discount
6
14
  def initialize(item_code)
7
15
  super()
@@ -2,6 +2,16 @@
2
2
 
3
3
  # A product that can be added to a shopping basket
4
4
  module Bakool
5
+ # Represents a product that can be added to a shopping basket.
6
+ # Each product has a name, code, and price.
7
+ #
8
+ # @example
9
+ # product = Bakool::Product.new("Red Widget", "R01", 32.95)
10
+ # price_in_cents = product.price_in_cents # 3295
11
+ #
12
+ # @attr_reader name [String] The product name
13
+ # @attr_reader code [String] The product code
14
+ # @attr_reader price [Numeric] The product price in dollars
5
15
  class Product
6
16
  attr_accessor :name, :code, :price
7
17
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bakool
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bakool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fadhil Luqman