Skip to content

Commit 56d357d

Browse files
committed
feat(pricing): add domain types
1 parent 84a07fc commit 56d357d

File tree

1 file changed

+92
-0
lines changed
  • pricing/src/main/scala/dev/atedeg/mdm/pricing

1 file changed

+92
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package dev.atedeg.mdm.pricing
2+
3+
import java.util.UUID
4+
import java.time.LocalDateTime
5+
6+
import dev.atedeg.mdm.products.Product
7+
import dev.atedeg.mdm.utils.*
8+
import dev.atedeg.mdm.utils.given
9+
import cats.data.NonEmptyList
10+
11+
/**
12+
* A [[Product product]] with its ordered [[Quantity quantity]].
13+
*/
14+
final case class IncomingOrderLine(quantity: Quantity, product: Product)
15+
16+
/**
17+
* A quantity of something.
18+
*/
19+
final case class Quantity(n: PositiveNumber)
20+
21+
/**
22+
* Associates to each [[Product product]] its [[PriceInEuroCents unitary price]].
23+
*/
24+
final case class PriceList(priceList: Map[Product, PriceInEuroCents])
25+
26+
/**
27+
* A price expressed in cents, the smallest currency unit for euros.
28+
*/
29+
final case class PriceInEuroCents(n: PositiveNumber) derives Plus
30+
31+
/**
32+
* A physical or legal entity that places [[IncomingOrderLine order lines]].
33+
*/
34+
final case class Client(code: ClientID)
35+
36+
/**
37+
* An ID which uniquely identifies a [[Client client]].
38+
*/
39+
final case class ClientID(id: UUID)
40+
41+
/**
42+
* A list of all the promotions for each [[Client client]].
43+
*/
44+
final case class PromotionsList(promotions: Map[Client, NonEmptyList[Promotion]])
45+
46+
/**
47+
* A promotion for a [[Client client]], with an expiry date.
48+
* It can either be fixed or by threshold.
49+
* If it is fixed, a product is discounted by a fixed amount;
50+
* if it is by threshold, only the products above the threshold are discounted.
51+
*/
52+
enum Promotion:
53+
/**
54+
* A fixed promotion.
55+
*/
56+
case Fixed(client: Client, expiryDate: LocalDateTime, lines: NonEmptyList[PromotionLine.Fixed])
57+
/**
58+
* A threshold promotion.
59+
*/
60+
case Threshold(client: Client, expiryDate: LocalDateTime, lines: NonEmptyList[PromotionLine.Threshold])
61+
62+
/**
63+
* A promotion line, which describes either the
64+
* [[Promotion.Fixed fixed]] or the [[Promotion.Threshold threshold]] promotion.
65+
*/
66+
enum PromotionLine:
67+
/**
68+
* A line that describes part of a [[Promotion.Fixed fixed promotion]].
69+
* It contains the discounted product and how much to discount it by.
70+
*
71+
* Every order line which contains the product is discounted by the specified amount.
72+
*
73+
* @note For example, if a 100g casatella normally costs 100 cents and the promotion line specifies
74+
* a 50% discount, each 100g casatella will cost 50 cents.
75+
*/
76+
case Fixed(product: Product, discount: DiscountPercentage)
77+
/**
78+
* A line that describes part of a [[Promotion.Threshold threshold promotion]].
79+
* It contains the discounted product, the threshold and how much to discount it by.
80+
*
81+
* Only the products above the threshold are discounted; the other ones are at full price.
82+
*
83+
* @note For example, if a 100g casatella normally costs 100 cents and the promotion line specifies
84+
* a 50% discount above 5 casatellas, the first 5 casatella will cost 100 cents, while from the 6th onwards
85+
* they will cost 50 cents each.
86+
*/
87+
case Threshold(product: Product, threshold: Quantity, discount: DiscountPercentage)
88+
89+
/**
90+
* A discount percentage, expressed as a number between 0 (exclusive) and 100 (inclusive).
91+
*/
92+
final case class DiscountPercentage(n: DecimalInOpenClosedRange[0, 100])

0 commit comments

Comments
 (0)