module DATAD (DATAP) is !update "2021-b" -- use standard operator priority ------------------------------------------------------------------------------- type Order is MkOrder (ref: Reference, prd: Product, amt: Amount, sta: Status) with ==, != end type ------------------------------------------------------------------------------- type Stock is MkStock (prd: Product, amt: Amount) with ==, != end type ------------------------------------------------------------------------------- type Orders is NoOrders, AddOrder (ord: Order, ords: Orders) with ==, != end type ------------------------------------------------------------------------------- function StatOrder (ref1: Reference, ords1: Orders): Status is var ref2: Reference, sta2: Status, ords2: Orders in case ords1 in NoOrders -> return None | AddOrder (MkOrder (ref2, any Product, any Amount, sta2), ords2) -> if ref1 == ref2 then return sta2 else return StatOrder (ref1, ords2) end if end case end var end function ------------------------------------------------------------------------------- function RemOrder (ord1: Order, ords1: Orders): Orders is var ref1, ref2: Reference, ord2: Order, ords2: Orders in case ord1 in MkOrder (ref1, any Product, any Amount, any Status) -> case ords1 in NoOrders -> return NoOrders | AddOrder (ord2 as MkOrder (ref2, any Product, any Amount, any Status), ords2) -> if ref1 == ref2 then return ords2 else return AddOrder (ord2, RemOrder (ord1, ords2)) end if end case end case end var end function ------------------------------------------------------------------------------- type Stocks is NoStocks, AddStock0 (stk: Stock, stks: Stocks) with ==, != end type ------------------------------------------------------------------------------- function InStock (prd1: Product, stks1: Stocks): Bool is var prd2: Product, stks2: Stocks in case stks1 in NoStocks -> return false | AddStock0 (MkStock (prd2, any Amount), stks2) -> return prd1 == prd2 or InStock (prd1, stks2) end case end var end function ------------------------------------------------------------------------------- function AddStock (stk1: Stock, stks1: Stocks): Stocks is var prd1, prd2: Product, amt1, amt2: Amount, stk2: Stock, stks2: Stocks in case stk1 in MkStock (prd1, amt1) -> case stks1 in NoStocks -> return AddStock0 (stk1, NoStocks) | AddStock0 (stk2 as MkStock (prd2, amt2), stks2) -> if prd1 == prd2 then return AddStock0 (MkStock (prd1, amt1 + amt2), stks2) else return AddStock0 (stk2, AddStock (stk1, stks2)) end if end case end case end var end function ------------------------------------------------------------------------------- function RemStock (stk1: Stock, stks1: Stocks): Stocks is var prd1, prd2: Product, amt1, amt2: Amount, stk2: Stock, stks2: Stocks in case stk1 in MkStock (prd1, amt1) -> case stks1 in NoStocks -> return NoStocks | AddStock0 (stk2 as MkStock (prd2, amt2), stks2) -> if prd1 == prd2 then return AddStock0 (MkStock (prd1, amt2 - amt1), stks2) else return AddStock0 (stk2, RemStock (stk1, stks2)) end if end case end case end var end function ------------------------------------------------------------------------------- function StockOf (prd1: Product, stks1: Stocks): Amount is var prd2: Product, amt2: Amount, stks2: Stocks in case stks1 in NoStocks -> return 0 of Amount | AddStock0 (MkStock (prd2, amt2), stks2) -> if prd1 == prd2 then return amt2 else return StockOf (prd1, stks2) end if end case end var end function ------------------------------------------------------------------------------- function UpdateOrders (ords1: Orders, stks1: Stocks): Orders is var ref2: Reference, prd2: Product, amt2: Amount, sta2: Status, ord2: Order, ords2: Orders in case ords1 in NoOrders -> return NoOrders | AddOrder (ord2 as MkOrder (ref2, prd2, amt2, sta2), ords2) -> if sta2 == Pending and StockOf (prd2, stks1) >= amt2 then return AddOrder (MkOrder (ref2, prd2, amt2, Invoiced), UpdateOrders (ords2, RemStock (MkStock (prd2, amt2), stks1))) elsif sta2 == Invoiced or StockOf (prd2, stks1) < amt2 then return AddOrder (ord2, UpdateOrders (ords2, stks1)) end if end case end var; return ords1 end function ------------------------------------------------------------------------------- function UpdateStocks (ords1: Orders, stks1: Stocks): Stocks is var prd: Product, amt: Amount, sta: Status, ords2: Orders in case ords1 in NoOrders -> return stks1 | AddOrder (MkOrder (any Reference, prd, amt, sta), ords2) -> if sta == Pending and StockOf (prd, stks1) >= amt then return UpdateStocks (ords2, RemStock (MkStock (prd, amt), stks1)) elsif sta == Invoiced or StockOf (prd, stks1) < amt then return UpdateStocks (ords2, stks1) end if end case end var; return stks1 end function ------------------------------------------------------------------------------- end module