Skip to content

Instantly share code, notes, and snippets.

@jkone27
Created September 30, 2023 13:39
Show Gist options
  • Save jkone27/8ebdc97993bd32c1232009ea8fe4f5b3 to your computer and use it in GitHub Desktop.
Save jkone27/8ebdc97993bd32c1232009ea8fe4f5b3 to your computer and use it in GitHub Desktop.
fsharp test order oms example
#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