<commit_before><?php

namespace SilverShop\Model;

use SilverShop\Cart\OrderTotalCalculator;
use SilverShop\Checkout\OrderEmailNotifier;
use SilverShop\Extension\MemberExtension;
use SilverShop\Extension\ShopConfigExtension;
use SilverShop\Model\Modifiers\OrderModifier;
use SilverShop\ORM\Filters\MultiFieldPartialMatchFilter;
use SilverShop\ORM\OrderItemList;
use SilverShop\Page\AccountPage;
use SilverShop\Page\CheckoutPage;
use SilverShop\ShopTools;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Dev\Debug;
use SilverStripe\Forms\CheckboxSetField;
use SilverStripe\Forms\DateField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\TabSet;
use SilverStripe\Omnipay\Extensions\Payable;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBCurrency;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\FieldType\DBEnum;
use SilverStripe\ORM\Filters\GreaterThanFilter;
use SilverStripe\ORM\Filters\LessThanFilter;
use SilverStripe\ORM\HasManyList;
use SilverStripe\ORM\Search\SearchContext;
use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;

/**
 * The order class is a databound object for handling Orders
 * within SilverStripe.
 *
 * @mixin Payable
 *
 * @property DBCurrency $Total
 * @property string $Reference
 * @property DBDatetime $Placed
 * @property DBDatetime $Paid
 * @property DBDatetime $ReceiptSent
 * @property DBDatetime $Printed
 * @property DBDatetime $Dispatched
 * @property DBEnum $Status
 * @property string $FirstName
 * @property string $Surname
 * @property string $Email
 * @property string $Notes
 * @property string $IPAddress
 * @property bool $SeparateBillingAddress
 * @property string $Locale
 * @property int $MemberID
 * @property int $ShippingAddressID
 * @property int $BillingAddressID
 * @method   Member|MemberExtension Member()
 * @method   Address BillingAddress()
 * @method   Address ShippingAddress()
 * @method   OrderItem[]|HasManyList Items()
 * @method   OrderModifier[]|HasManyList Modifiers()
 * @method   OrderStatusLog[]|HasManyList OrderStatusLogs()
 */
class Order extends DataObject
{
    /**
     * Status codes and what they mean:
     *
     * Unpaid (default): Order created but no successful payment by customer yet
     * Query: Order not being processed yet (customer has a query, or could be out of stock)
     * Paid: Order successfully paid for by customer
     * Processing: Order paid for, package is currently being processed before shipping to customer
     * Sent: Order paid for, processed for shipping, and now sent to the customer
     * Complete: Order completed (paid and shipped). Customer assumed to have received their goods
     * AdminCancelled: Order cancelled by the administrator
     * MemberCancelled: Order cancelled by the customer (Member)
     */
    private static $db = [
        'Total' => 'Currency',
        'Reference' => 'Varchar', //allow for customised order numbering schemes
        //status
        'Placed' => 'Datetime', //date the order was placed (went from Cart to Order)
        'Paid' => 'Datetime', //no outstanding payment left
        'ReceiptSent' => 'Datetime', //receipt emailed to customer
        'Printed' => 'Datetime',
        'Dispatched' => 'Datetime', //products have been sent to customer
        'Status' => "Enum('Unpaid,Paid,Processing,Sent,Complete,AdminCancelled,MemberCancelled,Cart','Cart')",
        //customer (for guest orders)
        'FirstName' => 'Varchar',
        'Surname' => 'Varchar',
        'Email' => 'V<PASSWORD>',
        'Notes' => 'Text',
        'IPAddress' => 'Varchar(15)',
        //separate shipping
        'SeparateBillingAddress' => 'Boolean',
        // keep track of customer locale
        'Locale' => 'Locale',
    ];

    private static $has_one = [
        'Member' => Member::class,
        'ShippingAddress' => Address::class,
        'BillingAddress' => Address::class,
    ];

    private static $has_many = [
        'Items' => OrderItem::class,
        'Modifiers' => OrderModifier::class,
        'OrderStatusLogs' => OrderStatusLog::class,
    ];

    private static $defaults = [
        'Status' => 'Cart',
    ];

    private static $casting = [
        'FullBillingAddress' => 'Text',
        'FullShippingAddress' => 'Text',
        'Total' => 'Currency',
        'SubTotal' => 'Currency',
        'TotalPaid' => 'Currency',
        'Shipping' => 'Currency',
        'TotalOutstanding' => 'Currency',<commit_msg>FEAT: Add table index for Status and the Status/Placed/Created tuple to allow much faster DB queries when search for 'Cart' orders<commit_after><?php

namespace SilverShop\Model;

use SilverShop\Cart\OrderTotalCalculator;
use SilverShop\Checkout\OrderEmailNotifier;
use SilverShop\Extension\MemberExtension;
use SilverShop\Extension\ShopConfigExtension;
use SilverShop\Model\Modifiers\OrderModifier;
use SilverShop\ORM\Filters\MultiFieldPartialMatchFilter;
use SilverShop\ORM\OrderItemList;
use SilverShop\Page\AccountPage;
use SilverShop\Page\CheckoutPage;
use SilverShop\ShopTools;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Dev\Debug;
use SilverStripe\Forms\CheckboxSetField;
use SilverStripe\Forms\DateField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\Tab;
use SilverStripe\Forms\TabSet;
use SilverStripe\Omnipay\Extensions\Payable;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBCurrency;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\FieldType\DBEnum;
use SilverStripe\ORM\Filters\GreaterThanFilter;
use SilverStripe\ORM\Filters\LessThanFilter;
use SilverStripe\ORM\HasManyList;
use SilverStripe\ORM\Search\SearchContext;
use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\Security\Member;
use SilverStripe\Security\Security;

/**
 * The order class is a databound object for handling Orders
 * within SilverStripe.
 *
 * @mixin Payable
 *
 * @property DBCurrency $Total
 * @property string $Reference
 * @property DBDatetime $Placed
 * @property DBDatetime $Paid
 * @property DBDatetime $ReceiptSent
 * @property DBDatetime $Printed
 * @property DBDatetime $Dispatched
 * @property DBEnum $Status
 * @property string $FirstName
 * @property string $Surname
 * @property string $Email
 * @property string $Notes
 * @property string $IPAddress
 * @property bool $SeparateBillingAddress
 * @property string $Locale
 * @property int $MemberID
 * @property int $ShippingAddressID
 * @property int $BillingAddressID
 * @method   Member|MemberExtension Member()
 * @method   Address BillingAddress()
 * @method   Address ShippingAddress()
 * @method   OrderItem[]|HasManyList Items()
 * @method   OrderModifier[]|HasManyList Modifiers()
 * @method   OrderStatusLog[]|HasManyList OrderStatusLogs()
 */
class Order extends DataObject
{
    /**
     * Status codes and what they mean:
     *
     * Unpaid (default): Order created but no successful payment by customer yet
     * Query: Order not being processed yet (customer has a query, or could be out of stock)
     * Paid: Order successfully paid for by customer
     * Processing: Order paid for, package is currently being processed before shipping to customer
     * Sent: Order paid for, processed for shipping, and now sent to the customer
     * Complete: Order completed (paid and shipped). Customer assumed to have received their goods
     * AdminCancelled: Order cancelled by the administrator
     * MemberCancelled: Order cancelled by the customer (Member)
     */
    private static $db = [
        'Total' => 'Currency',
        'Reference' => 'Varchar', //allow for customised order numbering schemes
        //status
        'Placed' => 'Datetime', //date the order was placed (went from Cart to Order)
        'Paid' => 'Datetime', //no outstanding payment left
        'ReceiptSent' => 'Datetime', //receipt emailed to customer
        'Printed' => 'Datetime',
        'Dispatched' => 'Datetime', //products have been sent to customer
        'Status' => "Enum('Unpaid,Paid,Processing,Sent,Complete,AdminCancelled,MemberCancelled,Cart','Cart')",
        //customer (for guest orders)
        'FirstName' => 'Varchar',
        'Surname' => 'Varchar',
        'Email' => '<PASSWORD>',
        'Notes' => 'Text',
        'IPAddress' => 'Varchar(15)',
        //separate shipping
        'SeparateBillingAddress' => 'Boolean',
        // keep track of customer locale
        'Locale' => 'Locale',
    ];

    private static $has_one = [
        'Member' => Member::class,
        'ShippingAddress' => Address::class,
        'BillingAddress' => Address::class,
    ];

    private static $has_many = [
        'Items' => OrderItem::class,
        'Modifiers' => OrderModifier::class,
        'OrderStatusLogs' => OrderStatusLog::class,
    ];

    private static $indexes = [
        'Status' => true,
        'StatusPlacedCreated' => [
            'type' => 'index',
            'columns' => ['Status', 'Placed', 'Created']
        ]
    ];

    private static $defaults = [
        'Status' => 'Cart',
    ];

    private static $casting = [
        'FullBillingAddress' => 'Text',
        'FullShippingAddress' => 'Text',
        'Total' => 'Currency',
        'SubTotal' => 'Currency',
        'TotalPaid' => 'Currency',
        'Shipping' => 'Currency',
        'TotalOutstanding' => 'Currency',
{'fraction_non_alphanumeric': 0.11169717654359293, 'fraction_numerical': 0.0004136932464577516, 'mean_word_length': 3.7800296589223925, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '309695', 'n_tokens_mistral': 2831, 'n_tokens_neox': 2827, 'n_words': 763}