Created
September 30, 2023 13:39
-
-
Save jkone27/8ebdc97993bd32c1232009ea8fe4f5b3 to your computer and use it in GitHub Desktop.
fsharp test order oms example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#r "nuget: NodaMoney" | |
open NodaMoney | |
open System | |
open System.Threading.Tasks | |
module Products = | |
type Product = | |
| Shoes | |
| Skirt | |
| Pants | |
| Jeans | |
type SalePrice = | SalePrice of Money | |
let euroSalePrice (amount: decimal) = | |
amount | |
|> Money.Euro | |
|> SalePrice | |
let priceProduct product = | |
match product with | |
| Product.Shoes -> 30m | |
| Product.Skirt -> 5m | |
| Product.Pants -> 15m | |
| Product.Jeans -> 12m | |
|> euroSalePrice | |
module Orders = | |
open Products | |
type Order = | |
| NormalOrder of nr: string * products: Product list | |
| ExpressOrder of Product list | |
| FreeOrder of Product list | |
| B2BOrder of Product list | |
type PricedOrder = { | |
Nr: string | |
Sales : (Product * SalePrice) list | |
} | |
with member this.Total = this.Sales |> Seq.sumBy (fun (p,SalePrice(m)) -> m.Amount) | |
member this.Currency = this.Sales |> Seq.tryHead |> Option.map (fun (p,SalePrice(s)) -> s.Currency.Code ) | |
let priceOrder order = | |
match order with | |
| NormalOrder(nr,products) -> | |
{ | |
Nr = nr | |
Sales = products |> List.map (fun p -> p, priceProduct p) | |
} | |
| _ -> failwith "not supported" | |
let basketSummary pricedOrder = | |
printfn $"ORDER: {pricedOrder.Nr} on date: {DateTime.UtcNow}" | |
for (product, SalePrice(salePrice)) in pricedOrder.Sales do | |
printfn $"\tproduct: {product}, {salePrice}" | |
$""" | |
items: {pricedOrder.Sales.Length}, | |
total: {pricedOrder.Total} {pricedOrder.Currency.Value} | |
""" | |
|> printfn "%s" | |
pricedOrder | |
let placeOrder (pricedOrder : PricedOrder) = | |
Console.WriteLine "confirm? Y/N" | |
let r = Console.ReadLine() | |
match r with | |
|"Y"|"y" -> Some(pricedOrder) | |
|_ -> None | |
let delayOneSec () = | |
let t = TimeSpan.FromSeconds(3) |> Task.Delay | |
t.Wait() | |
let rec payment (pricedOrder : PricedOrder) = | |
Console.WriteLine "enter your card number:" | |
let r = Console.ReadLine() | |
printfn "processing your request." | |
delayOneSec() | |
printfn "processing your request.." | |
delayOneSec() | |
printfn "processing your request..." | |
delayOneSec() | |
match r with | |
|"ABCDEF" -> | |
printfn "PAYMENT SUCCESSFUL!" | |
Some(pricedOrder) | |
|_ -> | |
printfn "PAYMENT REJECTED, wanna try again?Y/N" | |
let r = Console.ReadLine() | |
if r = "Y" || r = "y" then | |
payment pricedOrder | |
else | |
None | |
let closeOrder (pricedOrderOption : PricedOrder option) = | |
pricedOrderOption | |
|> Option.map (fun o -> | |
$""" | |
ORDER: {o.Nr} is confirmed. | |
total: {o.Total} {o.Currency}, | |
estimated arrival {DateTime.UtcNow.AddDays(2)} | |
THANK YOU AND SEE YOU SOON! | |
""") | |
|> Option.defaultValue "no order was made, thank you for your time!" | |
|> printfn "%s" | |
open Products | |
open Orders | |
("0000001F", | |
[ | |
Shoes | |
Shoes | |
Skirt | |
Pants | |
Pants | |
Pants | |
]) | |
|> NormalOrder | |
|> priceOrder | |
|> basketSummary | |
|> placeOrder | |
|> Option.bind payment | |
|> closeOrder |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment