Skip to content

MEP 4 - Order Modeling

Author: Rodda John Status: Superceeded (by MEP 5) Adopted: 2024-03-10

Overview

For a while, we have been flirting with figuring out an order abstraction to "rule them all" -- this is that.

Current State

Inventory Models

  • Category (has a type enum)
  • RentalClass
  • SaleClass (has a type enum for part vs sale)
  • ServiceClass
  • ExpenseClass
    • Associated with ExpenseRule (which govern when a modifier is added)
      • Rules help with the inheritance
  • Product (associated to either a SaleClass or a ProductClass)
  • Asset (associated with a Product)

Order Models

  • Order
  • RentalLineItem
  • SaleLineItem
  • ServiceLineItem
  • ExpenseLineItem (standalone or related to any of the line items above)

Problems with current state

  • There's a ton of duplicated code
    • Much of a rental class and a sale class works the same way
    • Differences are pricing + depreciation
  • Incremental lift is increased
    • The abstraction in our head is often a 'line item' and not a specific type of line item
      • e.g. making an attachment work differently has to change 3 models as opposed to 1
    • All 'receiving' should work the same regardless of if it's a purchase order or a rental.
    • Adding a new class is a pain – e.g. a fixed asset type that depreciates but isn't rental
      • Would be partially duplicative
  • The modeling breaks with some upcoming work
    • Service & repair allows different payment per line item
    • Fixed asset
    • Purchasing has it's own order concept right now…. that's….. not ideal

In short, the current abstractions are correct, but the modeling is cumbersome.

The modeling (the second take) should be redone to be significantly cleaner.

Proposal

Top level: make an order a lose grouping of line items, all state and data should be on the line item.

  • This allows for centralizing state transition logic as well as allowing different line items to do different things

Secondary objective: remove duplicated code; purchasing, rental, sales, service & repair are all permutations here

  • Preserve Category
  • Combine the classes into a single model, called Klass (to reduce clashes with class)
    • A Klass shall have upload models related to it, modifier models related to it, and pricing models related to it
    • KlassPricing
      • Shall relate a frequency to a price, if frequency is null, then the price is a sale price
  • Rename ExpenseClass to OrderModifier
    • These are never standalone (and thus not a class), but they do modify behavior
    • Leave ExpenseRule unchanged, rename to OrderModifierRule
  • Combine all line items into a single line item model
    • Should have a nullable klass_id, and an amount
      • The line items that would have a null klass would be delivery + tax
      • All modifiers shall be related to the thing that they modify
    • Should have a nullable product_id – used for puchases
    • A derived type field:
      • If 1 date and klass_id => sale
        • If the Klass is a service then it's a service sale etc
      • If 2 dates and klass_id => rental
      • If 1 date and a product_id, then it's a purchase
      • If 1 date and a klass_id
    • A line item shall either have a single date, or two dates
      • If a single date, this is a sale; if two dates, this is a rental
    • A line item shall be related to 0 - 2 OrderDelivery objects
      • These store a from address and a to address
      • A pickup order would have 0; a sale may have 1; a rental may have 0-2
    • A line item shall have a customer (if null, assumed it's the moab business)
      • i.e. a rental order is from a Moab business to a customer
    • A line item shall have a vendor (if null, assumed it's the moab business)
      • i.e. a PO is from a vendor to Moab business
    • A line item shall have a billing configuration section that shall store:
      • upfront / in arrears – for two date line items, which date is the charge date
      • billing_cycle – for two date line items, how long is the cycle
      • terms – whether there are terms (offset) applied from the charge to the due date
      • payer is either CUSTOMER or BUSINESS or WARRANTY
        • If CUSTOMER then customer_id is required
        • If WARRANTY then a warranty_id is required
    • A line item is optionally associated with a single asset
      • Even if the FE shows a quantity 4, those would be four line items on the BE