Files @ ff281c17ee63
Branch filter:

Location: symposion_app/vendor/registrasion/design/design.md - annotation

Joel Addison
Add speaker bio to JSON API
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
3c29e3db8c32
# Logic

## Definitions
- User has one 'active Cart' at a time. The Cart remains active until a paid Invoice is attached to it.
- A 'paid Cart' is a Cart with a paid Invoice attached to it, where the Invoice has not been voided.
- An unpaid Cart is 'reserved' if
 - CURRENT_TIME - "Time last updated" <= max(reservation duration of Products in Cart),
 - A Voucher was added and CURRENT_TIME - "Time last updated" < VOUCHER_RESERVATION_TIME (15 minutes?)
- An Item is 'reserved' if:
  - it belongs to a reserved Cart
  - it belongs to a paid Cart
- A Cart can have any number of Items added to it, subject to limits.


## Entering Vouchers
- Vouchers are attached to Carts
- A user can enter codes for as many different Vouchers as they like.
- A Voucher is added to the Cart if the number of paid or reserved Carts containing the Voucher is less than the "total available" for the voucher.
- A cart is invalid if it contains a voucher that has been overused


## Are products available?

- Availability is determined by the number of items we want to add to the cart: items_to_add

- If items_to_add + count(Product in their active and paid Carts) > "Limit per user" for the Product, the Product is "unavailable".
- If the Product belongs to an exhausted Ceiling, the Product is "unavailable".
- Otherwise, the product is available


## Displaying Products:

- If there is at least one mandatory EnablingCondition attached to the Product, display it only if all EnablingConditions are met
- If there is at least one EnablingCondition attached to the Product, display it only if at least one EnablingCondition is met
- If there are zero EnablingConditions attached to the Product, display it
- If the product is not available for items_to_add=0, mark it as "unavailable"

- If the Product is displayed and available, its price is the price for the Product, minus the greatest Discount available to this Cart and Product

- The product is displayed per the rendering characteristics of the Category it belongs to


## Displaying Categories

- If the Category contains only "unavailable" Products, mark it as "unavailable"
- If the Category contains no displayed Products, do not display the Category
- If the Category contains at least one EnablingCondition, display it only if at least one EnablingCondition is met
- If the Category contains no EnablingConditions, display it


## Exhausting Ceilings

- Exhaustion is determined by the number of items we want to add to the cart: items_to_add

- A ceiling is exhausted if:
 - Its start date has not yet been reached
 - Its end date has been exceeded
 - items_to_add + sum(paid and reserved Items for each Product in the ceiling) > Total available


## Applying Discounts

- Discounts only apply to the current cart
- Discounts can be applied to multiple carts until the user has exhausted the quantity for each product attached to the discount.
- Only one discount discount can be applied to each single item. Discounts are applied as follows:
 - All non-exhausted discounts for the product or its category are ordered by value
 - The highest discount is applied for the lower of the quantity of the product in the cart, or the remaining quantity from this discount
 - If the quantity remaining is non-zero, apply the next available discount

- Individual discount objects should not contain more than one DiscountForProduct for the same product
- Individual discount objects should not contain more than one DiscountForCategory for the same category
- Individual discount objects should not contain a discount for both a product and its category


## Adding Items to the Cart

- Products that are not displayed may not be added to a Cart
- The requested number of items must be available for those items to be added to a Cart
- If a different price applies to a Product when it is added to a cart, add at the new price, and display an alert to the user
- If a discount is used when adding a Product to the cart, add the discount as well
- Adding an item resets the "Time last updated" for the cart
- Each time carts have items added or removed, the revision number is updated


## Generating an invoice

- User can ask to 'check out' the active Cart. Doing so generates an Invoice. The invoice corresponds to a revision number of the cart.
- Checking out the active Cart resets the "Time last updated" for the cart.
- The invoice represents the current state of the cart.
- If the revision number for the cart is different to the cart's revision number for the invoice, the invoice is void.
- The invoice is void if


## Paying an invoice

- A payment can only be attached to an invoice if all of the items in it are available at the time payment is processed

### One-Shot
- Update the "Time last updated" for the cart based on the expected time it takes for a payment to complete
- Verify that all items are available, and if so:
- Proceed to make payment
- Apply payment record from amount received


### Authorization-based approach:
- Capture an authorization on the card
- Verify that all items are available, and if so:
- Apply payment record
- Take payment


# Registration workflow:

## User has not taken a guided registration yet:

User is shown two options:

1. Undertake guided registration ("for current user")
1. Purchase vouchers


## User has not purchased a ticket, and wishes to:

This gives the user a guided registration process.

1. Take list of categories, sorted by display order, and display the next lowest enabled & available category
1. Take user to category page
1. User can click "back" to go to previous screen, or "next" to go the next lowest enabled & available category

Once all categories have been seen:
1. Ask for badge information -- badge information is *not* the same as the invoicee.
1. User is taken to the "user has purchased a ticket" workflow


## User is buying vouchers
TODO: Consider separate workflow for purchasing ticket vouchers.


## User has completed a guided registration or purchased vouchers

1. Show list of products that are pending purchase.
1. Show list of categories + badge information, as well as 'checkout' button if the user has items in their current cart


## Category page

- User can enter a voucher at any time
- User is shown the list of products that have been paid for
- User has the option to add/remove products that are in the current cart


## Checkout

1. Ask for invoicing details (pre-fill from previous invoice?)
1. Ask for payment


# User Models

- Profile:
 - User
 - Has done guided registration?
 - Badge
 -

## Transaction Models

- Cart:
 - User
 - {Items}
 - {Voucher}
 - {DiscountItems}
 - Time last updated
 - Revision Number
 - Active?

- Item
 - Product
 - Quantity

- DiscountItem
 - Product
 - Discount
 - Quantity

- Invoice:
 - Invoice number
 - User
 - Cart
 - Cart Revision
 - {Line Items}
 - (Invoice Details)
 - {Payments}
 - Voided?

- LineItem
 - Description
 - Quantity
 - Price

- Payment
 - Time
 - Amount
 - Reference


## Inventory Model

- Product:
 - Name
 - Description
 - Category
 - Price
 - Limit per user
 - Reservation duration
 - Display order
 - {Ceilings}


- Voucher
 - Description
 - Code
 - Total available


- Category?
 - Name
 - Description
 - Display Order
 - Rendering Style


## Product Modifiers

- Discount:
 - Description
 - {DiscountForProduct}
 - {DiscountForCategory}

 - Discount Types:
    - TimeOrStockLimitDiscount:
     * A discount that is available for a limited amount of time, e.g. Early Bird sales *
     - Start date
     - End date
     - Total available

    - VoucherDiscount:
     * A discount that is available to a specific voucher *
     - Voucher

    - RoleDiscount
     * A discount that is available to a specific role *
     - Role

    - IncludedProductDiscount:
     * A discount that is available because another product has been purchased *
     - {Parent Product}

- DiscountForProduct
 - Product
 - Amount
 - Percentage
 - Quantity

- DiscountForCategory
 - Category
 - Percentage
 - Quantity


- EnablingCondition:
 - Description
 - Mandatory?
 - {Products}
 - {Categories}

 - EnablingCondition Types:
   - ProductEnablingCondition:
    * Enabling because the user has purchased a specific product *
    - {Products that enable}

   - CategoryEnablingCondition:
    * Enabling because the user has purchased a product in a specific category *
    - {Categories that enable}

   - VoucherEnablingCondition:
    * Enabling because the user has entered a voucher code *
     - Voucher

   - RoleEnablingCondition:
     * Enabling because the user has a specific role *
     - Role

   - TimeOrStockLimitEnablingCondition:
    * Enabling because a time condition has been met, or a number of items underneath it have not been sold *
    - Start date
    - End date
    - Total available