> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sitestorepro.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Order Management, Fulfillment, and Refunds in Site Store Pro

> Manage orders in Site Store Pro — pending queue, order details, partial refunds, payment history, shipment confirmation emails, and checkout custom fields.

&

## Admin Home Dashboard

Navigate to `/admin/dashboard` for a real-time overview of store performance.

### KPI Cards

Four headline metrics appear at the top of the dashboard:

<CardGroup cols={4}>
  <Card title="Total Sales Revenue" icon="dollar-sign">
    Aggregate revenue from all completed orders in the selected date window.
  </Card>

  <Card title="Orders Processed" icon="box-check">
    Count of orders that have moved past the pending state.
  </Card>

  <Card title="Pending Orders" icon="clock">
    Active orders awaiting fulfillment action.
  </Card>

  <Card title="Active Customers" icon="users">
    Unique customers who placed at least one order in the period.
  </Card>
</CardGroup>

### Dashboard Widgets

| Widget                              | Description                                                                  |
| ----------------------------------- | ---------------------------------------------------------------------------- |
| **Order Activity & Revenue Trends** | SVG line/bar graph of daily order volume and revenue                         |
| **Orders vs Abandoned Carts**       | Conversion rate widget comparing completed orders to abandoned cart sessions |
| **Cart Conversion Funnel**          | Step-by-step funnel from product view → add-to-cart → checkout → purchase    |
| **Customer Spend Analysis**         | Distribution of spend per customer segment                                   |
| **Product Sales Performance**       | Top-performing products by revenue and unit count                            |

### Date Filters

<Info>
  The dashboard defaults to the last **30 days**. All KPI cards and widgets update when you change the range.
</Info>

Available presets:

| Filter       | Window                        |
| ------------ | ----------------------------- |
| 30d          | Last 30 days (default)        |
| 60d          | Last 60 days                  |
| 90d          | Last 90 days                  |
| 120d         | Last 120 days                 |
| YTD          | January 1 → today             |
| Custom Range | Any start/end date you choose |

***

## Pending Orders Queue

```http theme={null}
GET /admin/pending-orders
```

Displays **all active non-completed orders** that require a fulfillment action. Results are paginated at **25 per page**.

<Note>
  An order appears in the Pending Queue as long as its status has not been set to completed or cancelled. Use this view as your primary daily fulfillment worklist.
</Note>

***

## Orders List

```http theme={null}
GET /admin/ecommerce/orders
```

Full order lookup across all statuses. Paginated at **25 per page**. Use the search bar to filter by order ID, customer name, or email.

***

## Order Details

```http theme={null}
GET /admin/ecommerce/orders/{id}
```

The Order Details page is the central hub for invoice review, fulfillment, and refund actions.

### Order Comments Block

Customer-submitted comments are rendered **above the Items Purchased section** on the invoice. No action is required — they display automatically if the customer entered a comment at checkout.

### Payment History Log

A structured log of every payment event for the order:

| Column             | Description                                 |
| ------------------ | ------------------------------------------- |
| Date               | Timestamp of the payment event              |
| Method             | Payment gateway used (e.g. Stripe, PayPal)  |
| Status             | Outcome: Approved, Declined, Refunded, etc. |
| Authorization Code | Gateway-returned auth reference             |
| Amount             | Dollar value of the transaction             |

### Mark Shipped

Clicking the **Mark Shipped** button immediately:

1. Updates the order status to **Shipped (status 2)**.
2. Triggers and sends a **shipment confirmation email** to the customer.

<Warning>
  The shipment confirmation email is sent the moment you click Mark Shipped. Confirm the shipping address and tracking details are correct before clicking.
</Warning>

You can also trigger the same action via the **Status dropdown**: selecting status value `2` (Shipped) has identical behavior — the confirmation email fires immediately.

### Send Download Reminder

For orders containing digital items, the **Send Download Reminder** button manually re-dispatches the download reminder email to the customer on demand.

<Info>
  This button is only visible on orders that include at least one digital download item.
</Info>

### Double-Confirmation Action Gate

High-consequence email actions — **Resend Order Confirmation** and **Send Download Reminder** — require **two clicks** to execute:

1. The first click reveals a confirmation prompt inline on the page.
2. The second click sends the email.

<Warning>
  This two-step gate prevents accidental duplicate emails. Do not click through both steps unless you intentionally want to re-send the email to the customer.
</Warning>

### Status Dropdown Reference

| Order Status DB Value | Label                            | Notes                                |
| --------------------- | -------------------------------- | ------------------------------------ |
| 1                     | Open \| Pending                  | Default on order placement           |
| 7                     | Completed                        | No Email Sent                        |
| 2                     | Shipped                          | Triggers shipment confirmation email |
| 6                     | Back-Ordered                     | No Email Sent                        |
| 8                     | Partially Refunded               | No Email Sent                        |
| 3                     | Refunded                         | No Email Sent                        |
| 4                     | Cancelled                        | No Email Sent                        |
| 0                     | Order Failed Or Awaiting Payment | n/a                                  |
| 10                    | Awaiting Payment By Check or PO  | n/a                                  |

***

## Partial or Full Refunds

Partial or full refunds are issued directly from the Order Details page (`/admin/ecommerce/orders/{id}`).

<Steps>
  <Step title="Open the Order">
    Navigate to **Admin → Orders** and click the order you need to refund.
  </Step>

  <Step title="Set Order Status (Optional for Full Refunds)">
    Change the order status using the **Update Order Status** dropdown to either **Refunded** or **Partially Refunded** and then click the **Apply Status** button (this will not send the customer an email automatically).

    > **Note:** If the entire order amount is refunded across payments, the order status will automatically update to **Refunded** upon processing the refund, allowing you to skip this manual status update.
  </Step>

  <Step title="Click the Refund Button in Payments List">
    Locate the **Payments** section and click the **Refund** button next to the specific payment you want to refund.

    > **Automatic Gateway Dispatch:** If the payment was processed via **Stripe**, **PayPal**, or **Paddle**, the refund will automatically post directly to the customer's payment provider via their API.
  </Step>

  <Step title="Enter Refund Amount">
    In the refund modal, review the maximum refundable balance. The field **defaults to the full remaining payment amount**, but can be modified to any smaller amount for partial refunds. You may also add an optional administrative note or reason.
  </Step>

  <Step title="Confirm & Process Refund">
    Ensure the **Post refund via Payment Processor API** toggle is enabled (auto-checked for gateway transactions), and click **Confirm & Process Refund**. The gateway executes the credit, records the refund transaction in `order_refunds`, updates the payment status, and recalculates the balance due.
  </Step>
</Steps>

***

## 1. Direct Gateway API Linkages

When an admin processes a refund, the system resolves the associated payment method and interacts with the respective processor API:

### 1. Stripe Integration

* **Driver**: `App\Services\Payments\Processors\StripeProcessor`
* **Mechanism**: Calls the Stripe REST API via `\Stripe\Refund::create()`.
* **Identifier Resolution**:
  * Automatically handles Payment Intent IDs (`pi_...`), Charge IDs (`ch_...`), or Customer Payment Methods (`pm_...`).
  * If a Subscription agreement ID (`sub_...`) is provided, it retrieves the latest invoice and its underlying PaymentIntent to execute the refund.
* **Amount Handling**: Converted to integer cents with currency preservation.

### 2. PayPal Integration

* **Driver**: `App\Services\Payments\Processors\PayPalProcessor`
* **Mechanism**: Calls the PayPal Captures API v2 (`POST /v2/payments/captures/{capture_id}/refund`).
* **Identifier & Subscription Fallback**:
  * Automatically resolves capture IDs from PayPal Checkout Order IDs or Subscription agreement IDs (`I-...`).
  * If the transaction is a subscription billing agreement sale, it automatically falls back to PayPal's Sale Refund API (`POST /v1/payments/sale/{sale_id}/refund`).
* **Error Diagnostics**: Intercepts granular error issues and descriptions from PayPal API responses (e.g., already refunded, capture expired, or balance limits) and displays clear toast notifications.

### 3. Paddle Billing Integration

* **Driver**: `App\Services\Payments\Processors\PaddleProcessor`
* **Mechanism**: Calls the Paddle Billing Adjustments API (`POST /adjustments`).
* **Adjustment Types**:
  * **Full Refund**: Dispatches `action: 'refund'`, `type: 'full'`, and the `transaction_id`.
  * **Partial Refund**: Retrieves the transaction line items and creates a partial line adjustment with `type: 'partial'` and item-level amount tracking.
* **Identifier Resolution**: Resolves transaction IDs directly or via Subscription IDs (`sub_...`) and Customer IDs (`ctm_...`).

### 4. Test Gateway & Offline Ledgers

* **Test Driver**: `App\Services\Payments\Processors\TestProcessor` returns simulated refund authorizations (`TEST-RFND-XXXXXXXX`) for testing environments.
* **Offline / Manual Override**: Administrators can uncheck the **Post refund via Payment Processor API** toggle if the payment was already settled outside the gateway (e.g., cash, check, wire transfer, or direct bank chargeback resolution).

***

## 2. Payments Table & Status Behavior

The **Payments** table on the Order Details view provides clear real-time visibility into the lifecycle of each charge:

| Status Badge                   | Condition                                          | Description                                                                                                 |
| :----------------------------- | :------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |
| **Paid** (Green)               | `payment_status = 1`                               | Charge is captured with no refund balance deducted.                                                         |
| **Partially Refunded** (Amber) | `payment_status = 3` or `refunded_amount > 0`      | A portion of the payment has been refunded. Displays the refunded amount subtext (e.g. `-$25.00 refunded`). |
| **Refunded** (Red)             | `payment_status = 2` or `remaining_refundable = 0` | The payment has been 100% refunded. The Refund button is disabled with a checkmark.                         |
| **Pending** (Slate)            | `payment_status = 0`                               | Payment authorization is incomplete or awaiting settlement.                                                 |

### Balance Summary Calculations

The order ledger dynamically reflects:

* **Order Total**: Original total order charge.
* **Total Paid**: Sum of all payments recorded in `order_payments`.
* **Total Refunded**: Sum of all refunds recorded in `order_refunds` (displayed in red).
* **Balance Due**: `max(0, Order Total - Total Paid + Total Refunded)`. Displays a green **Paid in Full** badge when the net balance due is \$0.00.

***

## 3. Automated Order Status & Inventory Safeguards

### Automatic Order Status Elevation

* When cumulative refunds equal or exceed the order's total charge (`order_total`), the overall `orders.order_status` is automatically set to **3 (Refunded)**.
* For partial refunds, administrators can optionally set the order status to **Partially Refunded** via the status dropdown.

### Inventory Restocking Safeguard

* When the **first refund** on an order is created, the system iterates over the order line items (`order_details`) and increments the available product stock (`product_inventory.quantity_available += item_qty`).
* Subsequent partial refunds on the same order will not duplicate inventory restocks.

***

## 4. Code & Architecture Reference

| Component               | Path                                                            | Description                                                                                                      |
| :---------------------- | :-------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- |
| **Refund Service**      | `app/Services/Payments/PaymentRefundService.php`                | Centralized refund orchestrator managing validation, gateway API dispatch, and database transactions.            |
| **Contract**            | `app/Services/Payments/Contracts/PaymentProcessorInterface.php` | Defines the standard `refund(string $transactionId, float $amount, ?string $reason, string $currency)` contract. |
| **Stripe Processor**    | `app/Services/Payments/Processors/StripeProcessor.php`          | Stripe API refund implementation.                                                                                |
| **PayPal Processor**    | `app/Services/Payments/Processors/PayPalProcessor.php`          | PayPal Captures v2 and Subscriptions v1 refund implementation.                                                   |
| **Paddle Processor**    | `app/Services/Payments/Processors/PaddleProcessor.php`          | Paddle Billing Adjustments API refund implementation.                                                            |
| **Test Processor**      | `app/Services/Payments/Processors/TestProcessor.php`            | Simulated sandbox test refund driver.                                                                            |
| **Order Payment Model** | `app/Models/OrderPayment.php`                                   | Includes `refunds()` relation, `refunded_amount`, and `remaining_refundable` accessors.                          |
| **Order Refund Model**  | `app/Models/OrderRefund.php`                                    | Includes `payment()` relation and `order_payment_id` attribute.                                                  |
| **Admin Controller**    | `app/Livewire/AdminOrderDetails.php`                            | Livewire component managing modal state, validation, and refund execution.                                       |
| **Blade View**          | `resources/views/livewire/admin-order-details.blade.php`        | Renders the Payments table, status badges, and interactive refund modal.                                         |
| **Toast Component**     | `resources/views/components/toast-alert.blade.php`              | Renders real-time success and error alerts with secure HTML entity encoding.                                     |

***

## Invoice Address Formatting

US and Canadian order invoices display the city, state, and ZIP in the standard inline format:

```text theme={null}
San Diego, CA 92101
```

* **City** — customer's city
* **State** — two-letter abbreviation positioned between city and ZIP (US) or province abbreviation (CA)
* **ZIP / Postal Code** — appended after the state abbreviation

***

## Checkout Custom Fields Manager

```http theme={null}
GET /admin/ecommerce/checkout/processors
```

<Info>
  Access to the Checkout Custom Fields Manager is restricted to **Admin** role only.
</Info>

Use this tool to inject custom data-collection fields directly into the checkout flow.

### Field Positions

| Position            | Step               | Placement                                    |
| ------------------- | ------------------ | -------------------------------------------- |
| Checkout Step 1     | Shipping form page | Rendered **below** the shipping address form |
| Billing Page Step 2 | Payment page       | Rendered **above** the payment card input    |

### Field Types

| Type             | Renders As                    |
| ---------------- | ----------------------------- |
| `input`          | Single-line text input        |
| `textarea`       | Multi-line text area          |
| `select`         | Dropdown `<select>`           |
| `radio`          | Radio button group            |
| `checkbox`       | Single checkbox               |
| `checkbox_group` | Multiple-selection checkboxes |

### Billing Page User Type Filter

Step-2 fields can be targeted to specific customer segments:

| Setting        | Visibility                                       |
| -------------- | ------------------------------------------------ |
| Both           | Shown to all customers                           |
| Public Only    | Shown only to standard (non-wholesale) customers |
| Wholesale Only | Shown only to wholesale accounts                 |

### Data Storage

All custom field responses are stored in the `orders.custom_field_data` JSON column on the order record. The data is available in the Order Details view and exportable via the Orders export.

### Session Carryover

Step-1 (shipping page) field values are **held in session** after the customer advances. When the order is placed, Step-1 values are **merged with Step-2 values** and written together into `orders.custom_field_data`.

```text theme={null}
Session (Step 1 values)
        +
Form POST (Step 2 values)
        ↓
orders.custom_field_data  (single merged JSON object)
```
