This is just a pet project of mine to play with Kotlin stdlib
For this, I'm simulating an eCommerce platform as close as I can, model-wise. I took inspiration based on my understanding of how Amazon handles Physical, Digital and Subscription Orders
fun main() {
    val cart = ShoppingCart()
        .add(Product("PS4 Slim 1TB", ProductType.PHYSICAL, 1899.00), 1)
        .add(Product("PDP Chair", ProductType.PHYSICAL, 399.00), 2)
        .add(Product("Cracking the Code Interview", ProductType.PHYSICAL_TAX_FREE, 219.57), 2)
        .add(Product("The Hitchhiker's Guide to the Galaxy", ProductType.PHYSICAL_TAX_FREE, 120.00), 1)
        .add(Product("Stairway to Heaven", ProductType.DIGITAL, 5.00), 1)
        .add(Product("Nier:Automata", ProductType.DIGITAL, 129.90), 4)
        .add(Product("Netflix Familiar Plan", ProductType.SUBSCRIPTION, 29.90), 1)
        .add(Product("Spotify Premium", ProductType.SUBSCRIPTION, 14.90), 1)
        .add(Product("Amazon Prime", ProductType.SUBSCRIPTION, 12.90), 1)
    val account = Account("john doe", "[email protected]", "passwd")
    val orders = cart.checkout(account)
    // Pick one or Iterate through the orders
    val physicalOrder = orders.first { it.type == OrderType.PHYSICAL } as PhysicalOrder
    val digitalOrder = orders.first { it.type == OrderType.DIGITAL } as DigitalOrder
    val subscriptionOrder = orders.first { it.type == OrderType.SUBSCRIPTION } as SubscriptionOrder
    val address = Address.builder
        .country("Brazil")
        .city("Sao Paulo")
        .state("SP")
        .zipCode("01000-000")
        .streetAddress("Av Paulista, 1000")
        .build()
    val myCreditCard = CreditCard(
        nameOnCard = "John Doe",
        number = "123.456.789-00",
        securityCode = 123,
        expiresAt =  YearMonth.of(2027, 7),
        billingAddress = address
    )
    val physicalOrderInvoice = physicalOrder
        .withShippingAddress(address)
        .withPaymentMethod(myCreditCard)
        .place()
        .pay()
        .invoice()
    val digitalOrderInvoice = digitalOrder
        .withPaymentMethod(myCreditCard)
        .place()
        .pay()
        .invoice()
    val membershipOrderInvoice = subscriptionOrder
        .withPaymentMethod(myCreditCard)
        .place()
        .pay()
        .invoice()
}These are pretty self explanatory, right ? :) ProductType has an enum parameter, mapping to what kind of Order that product would be in
Represents a given amount of Product in the Shopping Cart or in an Order
Represents an interface defining the implementations for  Physical, Digital and Membership Orders,
each with its own set of rules for place(), pay(), fulfill() and complete()
May only contain products which the ProductType is 'Physical' or 'PHYSICAL_TAX_FREE'
- 
place():- Setups the Packaging for Shipping
- Includes a Shipping and Handlingcost of extra $10 per package
- Ready the order to the PENDINGstatus
- Note: Provided that there are items that fall under the PHYSICAL_BOOKcategory, they're grouped together into another shipment with the labelTAX_FREE
 
- 
pay():- Provided that the Order has been placed, and not yet payed:
- //TODO:Process the Payment
- Updates the OrderStatus to UNSHIPPED
 
- 
fulfill():- Provided that the order has been payed and not yet shipped:
- //TODO:Notifies the seller to fulfill/process the Order on its end
- Updates the OrderStatus to SHIPPED
 
- 
complete():- // TODO:: Track the packages/shipment they're all delivered
- Updates the OrderStatus to DELIVERED
 
May only contain products which the ProductType is 'Digital'
- 
place():- Includes a Voucherdiscount of $10 for the Order
- Ready the order to the PENDINGstatus
 
- Includes a 
- 
pay():- Provided that the Order has been placed, and not yet payed:
- //TODO:Process the Payment
- Updates the OrderStatus to UNSENT
 
- 
fulfill():- Provided that the order has been payed and not yet sent:
- //TODO:Notifies the seller to fulfill/process the Order on its end
- Updates the OrderStatus to SENT
 
- 
complete():- // TODO:: Track when the the Buyer clicks on the emailed link to redeem the item
- Updates the OrderStatus to REDEEMED
 
May only contain products which the ProductType is 'Subscription'
- 
place():- Ensures there's only one Subscription per Order
- Ready the order to the PENDINGstatus
- Note: In a scenario with multiple MembershipItems in the Shopping Cart, each will spawn a different Order
 
- 
pay():- Provided that the Order has been placed, and not yet payed:
- //TODO:Process the Payment
- Updates the OrderStatus to PENDING_ACTIVATION
 
- 
fulfill():- Provided that the order has been payed and not yet activated:
- //TODO:Activates the Subscription Service
- Updates the OrderStatus to ACTIVATED
 
To better simulate the user experience in an e-commerce platform, and also to wrap all the complexity of creating an Order, this Shopping Cart entity was created
- 
add(product: Product, n: Int):- Adds the N-amounts of the given productto the shopping Cart
- Note: if the product is already in the Cart, adds up in the quantity
 
- Adds the N-amounts of the given 
- 
updateQuantity(product: Product, n: Int):- Overrides whatever amount there is of the given productwih the specifiednamount. If(n == 0), the product is deleted from the cart
 
- Overrides whatever amount there is of the given 
- 
delete(product: Product)Deletes the product from the cart regardless of the quantity
- 
subtotal()Computes the sum of (unittest price of each product in the Cart * quantity)
- 
checkout(account: Account):- All items that fall under Physical(regardless if their product category will be tax-free on Shipment or not) are grouped together to create aPhysicalOrder
- All items that fall under Digitalare grouped together to create aDigitalOrder
- Each item that falls under Membershipwill create a different Membership Order (due to the complexity of activating each subscription individually, and probably through 3rd-party APIs)
 
- All items that fall under 
- Build Automation with CI (Travis CI)
- Code Coverage check
- Code Inspection for maintainability
- GitHub CI