diff --git a/guides/orders/display-total-methods.md b/guides/orders/display-total-methods.md new file mode 100644 index 0000000000..d70319467d --- /dev/null +++ b/guides/orders/display-total-methods.md @@ -0,0 +1,41 @@ +# Display total methods + +The `Spree::Order` model includes a number of useful methods for displaying +totals and balances: + +- `display_outstanding_balance`: The outstanding balance for the order, calculated by + taking the `total` and subtracting the current `payment_total`. +- `display_item_total`: The total of the line items on the order. +- `display_adjustment_total`: The total of the adjustments on the order. +- `display_total`: The order total. +- `display_total_available_store_credit`: The total available store credit. +- `display_order_total_after_store_credit`: The order total after store credit + has been applied. +- `display_store_credit_remaining_after_capture`: The amount of store credit + remaining after an order payment has been captured. + + + +By default, the following methods return `Spree::Money` objects configured with +the order's currency symbol. For example: + +```ruby +@order.display_total.to_html +# => "$10.99" +``` + +Because `Spree::Money` objects are based on the [Ruby Money +library][ruby-money], you can further change what information is displayed using +its [`format`][ruby-money-format] method: + +```ruby +@order.display_total.format(with_currency: true) +# => "$10.99 USD" +``` + +[ruby-money]: https://github.com/RubyMoney/money +[ruby-money-format]: http://www.rubydoc.info/gems/money/Money/Formatting + diff --git a/guides/orders/order-state-machine.md b/guides/orders/order-state-machine.md new file mode 100644 index 0000000000..d03f10cfa0 --- /dev/null +++ b/guides/orders/order-state-machine.md @@ -0,0 +1,72 @@ +# Order state machine + +Orders flow through a state machine, which is defined in the +`Spree::Order::Checkout` module. It begins with a `cart` state and ends with +at a `complete` state. + +There are six order states by default: + +1. `cart` +2. `address` +3. `delivery` +4. `payment` +5. `confirm` +6. `complete` + +If you go through the checkout provided in the `solidus_frontend` gem, you can +see that there is a clearly defined step for each of these states during checkout. + +In some circumstances, the `payment` and `confirm` states are optional: + +- The `payment` state is only triggered if `payment_required?` returns `true`. +- The `confirm` state is only triggered if `confirmation_required?` returns + `true`. + +The `complete` state is triggered in one of two ways: + +1. No payment is required on the order. (The `total` equals `0`.) +2. Payment is required on the order, and at least the order total has been + received as payment. + +## State criteria + +Each order state has criteria that must be met before the state can change. For +example, before the state can change from `cart` to `address`, line items must be +present on the order. Then, to change from `address` to `delivery`, the user +must have a default address assigned. + +Once an order meets the criteria to go to the next state, you can call `next` on +the order object to transition into the next state. For example, in the +`solidus_frontend` gem, the [`Spree::CheckoutController`][checkout-controller] +defines a `transition_forward` method that always calls `next` unless the order +can be completed: + +```ruby +# /frontend/app/controllers/spree/checkout_controller.rb +def transition_forward + if @order.can_complete? + @order.complete + else + @order.next + end +end +``` + +If `next` returns `false`, then the order does not meet the criteria and does +not transition to the next state. + +[checkout-controller]: https://github.com/solidusio/solidus/blob/master/frontend/app/controllers/spree/checkout_controller.rb + +## Payments and shipments have their own state machines + +Note that a `Spree::Order` with the state `complete` does not mean that the +payment has been processed or the order shipments have been shipped. See also the +values of the `payment_state` and `shipment_state` attributes. + + + diff --git a/guides/orders/overview.md b/guides/orders/overview.md new file mode 100644 index 0000000000..49284efae4 --- /dev/null +++ b/guides/orders/overview.md @@ -0,0 +1,163 @@ +# Overview + +The `Spree::Order` model is one of the key models in Solidus. It provides a +central place around which to collect information about a customer order. It +collects line items, adjustments, payments, addresses, return authorizations, +and shipments. + +Whenever information about the order is updated, the `Spree::OrderUpdater` +should update the order. If your store creates or changes the functionality +around the order, you may need to [manually call the order +updater][update-orders]. + +Orders have the following attributes: + +- `number`: The unique identifier for this order generated by + `Spree::Order::NumberGeneratr`. It begins with the letter `R` and ends in a + nine-digit number (for example, `R123456789`). This number is shown to the + users, and can be used to find the order by calling + `Spree::Order.find_by(number: "R123456789")`. +- `item_total`: The sum of all the line items for this order. +- `total`: The sum of the `item_total` and the `adjustment_total` attributes. +- `state`: The current state of the order. See the [Order state + machine][order-state-machine] article for more information. +- `adjustment_total`: The sum of all adjustments on this order. +- `user_id`: The ID for the order's corresponding user. Stored only if the order + is placed by a signed-in user. +- `completed_at`: The timestamp that logs when the order is completed. +- `bill_address_id` and `ship_address_id`: The IDs for the related + `Spree::Address` objects with billing and shipping address information. +- `payment_total`: The sum of all the *finalized* payments on the order. +- `shipment_state`: The current [shipment state][shipment-states] of the order. +- `payment_state`: The current payment state of the order. +- `email`: The customer-provided email address for the order. This is stored in + case the order is for a guest user. +- `special_instructions`: Any [special shipping + instructions][special-instructions] that shave been specified by the customer + during checkout. +- `currency`: The currency for this order. Determined by the + `Spree::Config[:currency]` value that was set at the time of order. +- `last_ip_address`: The last IP address used to update this order in the + frontend. +- `created_by_id`: The ID of object that created this order. +- `shipment_total`: The sum of all the shipments associated with an order. +- `additional_tax_total`: The sum of all the `additional_tax_total`s (sales tax) + on an order's line items and shipments. +- `promo_total`: The sum of all of the `promo_total`s on an order's shipments, + line items, and promotions. +- `channel`: The channel specified when importing orders from other stores. For + example, if you operate as an Amazon Seller and import orders from Amazon, + some orders may have a channel value of `amazon`. Otherwise, this value is + `spree`. +- `included_tax_total`: The sum of all the `included_tax_total`s (value-added + tax) on an order's line items and shipments. +- `item_count`: The total amount of line items associated with the order. +- `approver_id`: The ID of user that approved the order. +- `approver_name`: The name of the user that approved the order. +- `approved_at`: The timestamp logging when this order is approved by the + approver. +- `confirmation_delivered`: Boolean value that indicates that an order + confirmation email has been delivered. +- `guest_token`: The guest token that links an uncompleted order to a specific + guest user (via browser cookies). +- `canceler_id`: The ID of user that canceled this order. +- `canceled_at`: If the order is cancelled, this timestamp logs when the order + was cancelled. +- `store_id`: The ID of `Spree::Store` in which the order has been created. + +Because orders are so integral to Solidus, there are a number of methods +available that let you easily display order totals and subtotals. For more +information, see the [Display totals methods][display-total-methods] article. + +[display-total-methods]: display-total-methods.md +[order-state-machine]: order-state-machine.md +[shipment-states]: ../shipments/overview-of-shipments.md#shipping-states +[special-instructions]: ../shipments/user-interface-for-shipments.md#shipping-instructions +[update-orders]: update-orders.md + +## Related models + +The `Spree::Order` model touches many other models. This section highlights +essential models that orders depend on and links to their existing +documentation. + +### Line items + +The `Spree::LineItem` model provides the cost of each item added to an order. +Line items provide a link between the order and `Spree::Product`s and +`Spree::Variant`s. + + + + + +### Adjustments + +The `Spree::Adjustment` model provides the cost of each adjustment to an order, +line item, or shipment on an order. Adjustments can decrease the total (via +promotions) or increase it (via [shipments][shipments] and [taxes][taxes]). + + + + + +[taxes]: ../taxation/overview-of-taxation.md + +### Shipments + +The `Spree::Shipment` model creates shipments according to the items in an +order. An order may have multiple shipments: this depends on your store's +configured shipping categories and shipping methods and the item in the order. + +Shipments use `Spree::InventoryUnit`s. An inventory unit is created for each +item added to an order for the purpose of tracking what order and shipment an +item belongs to. Inventory units provide a link between the order and +`Spree::Shipment`s. + +For more information, see the [Shipments][shipments] documentation. + +[shipments]: ../shipments/overview-of-shipment.md + +### Addresses + +The `Spree::Address` model stores customer addresses and shares them with the +order via the `ship_address_id` and `bill_address_id`. An order may have one or +two different addresses associated it, depending on the customer's preferred +shipping and billing address. + + + + + +### Payments + +The `Spree::Payment` model stores payment information for the order. Once the +payment object is updated with the amount paid, this updates the corresponding +order's `payment_total` value. + + + + + +### Return Authorizations + +The `Spree::ReturnAuthorization` model stores information about customers +returns that have been authorized by an administrator. + + + diff --git a/guides/orders/update-orders.md b/guides/orders/update-orders.md new file mode 100644 index 0000000000..73bab9e18b --- /dev/null +++ b/guides/orders/update-orders.md @@ -0,0 +1,31 @@ +# Update orders + +You need to use the `recalculate` method on a `Spree::Order` to keep its total +up-to-date. Note that the total changes every time that line items and +adjustments are added or modified. The `recalculate` method calls out to the +[`Spree::OrderUpdater` class][order-updater]. + +For example, the `solidus_backend` gem's +[`Spree::Admin::AdjustmentsController`][adjustments-controller] uses the +`recalculate` method to update totals throughout the lifetime of an order: + +```ruby +def update_totals + @order.reload.recalculate +end +``` + +The `update_totals` method is called every time that adjustments are created, +destroyed, and updated. + +Whenever you change the code that touches the values of a `Spree::Order`, use +the `recalculate` method to ensure your order's totals are accurate. For +example, you would want to call the `recalculate` method in the following +scenarios: + +- Whenever you create or modify a `Spree::Payment` that changes the order's + `payment_state` value. +- Whenever a `Spree:LineItem` on the order has a price change. + +[adjustments-controller]: https://github.com/solidusio/solidus/blob/master/backend/app/controllers/spree/admin/adjustments_controller.rb +[order-updater]: https://github.com/solidusio/solidus/blob/master/core/app/models/spree/order_updater.rb