# Admin Orders Management

Use this document for changes to the GM order-management page or its internal approval flow. Do not re-analyze the customer cart, purchase-history, or PayPal flow unless the requested change explicitly affects them.

## File Map

| Area | File | Relevant contract |
|---|---|---|
| Route | `src/pages/routes.php` | `orders-management` is an admin-only route |
| Controller | `src/pages/admin/orders-management/orders-management.controller.php` | Search, owner resolution, approval dispatch |
| View | `src/pages/admin/orders-management/orders-management.view.php` | Search form, order table, order details, approval form |
| Shared selectors | `src/core/modules/PaymentModule/PaymentHelpers.php` | `PaymentHelpers::getPaymentMethods()` is the single selector source |
| Admin payment entry | `src/core/modules/admin_approval/admin_approval.php` | Loads the internal payment class |
| Admin payment logic | `src/core/modules/admin_approval/admin_approval.class.php` | `AdminApprovalPayment::validatePayment()` performs approval; `createRequest()` is empty |
| Payment completion | `src/core/modules/PaymentModule/PaymentModule.php` | Shared completion plus admin hook |
| Order API | `src/model/base/order.model.php` | Admin queries and admin-only paid update |
| Schema | `installation/cms.sql` | Order status includes `REJECTED` |

## Admin Order API

Use these methods instead of customer methods:

```php
OrderModel::getAdminOrders($startOrder, $limitOrders, $orderId = null, $owner = null);
OrderModel::getAdminOrder($orderId);
OrderModel::getAdminHistory($orderId, $accountModel);
OrderModel::markPaidByAdmin($orderId, $paymentMethod, $transactionId, $totalAfterDiscount, $discountApplied);
```

- `getAdminOrders()` orders by `order_id DESC` and accepts start/limit for future pagination.
- The current page calls `getAdminOrders(0, 50, ...)`.
- Admin queries must not call `expirePending()` or `OrderModel::isPayable()`.
- `markPaidByAdmin()` accepts only `PENDING` and `REJECTED` and has no payment-age condition.
- Existing `getById()`, `getHistory()`, `markPaid()`, and `isPayable()` belong to customer/provider flows and must remain unchanged.

## Owner Resolution

`StoreModel::$ownerField` determines the stored order owner:

- `Username`: use `AccountModel::getByUsername($order['owner'])`.
- `UID`: use `AccountModel::getByUID((int) $order['owner'])`.

For a username search, resolve the account first, then pass `$account[StoreModel::$ownerField]` to `getAdminOrders()`. Do not query `cms_orders.owner` with the username directly for UID-based sources.

## Approval Flow

`AdminApprovalPayment` is internal and is intentionally absent from `PAYMENT_MODULES` and `config.php`.

`validatePayment()` must:

1. Enforce the current GM user and `die()` when the caller is not a GM.
2. Validate the CSRF token and paid-confirmation checkbox.
3. Load the order with `getAdminOrder()`.
4. Allow only `PENDING` or `REJECTED` orders.
5. Validate the selected normal payment method and final paid price.
6. Resolve the order owner using `StoreModel::$ownerField`.
7. Call the inherited completion path with the selected payment method.

`createRequest()` does not redirect or process a request. The admin page calls `validatePayment()` directly. The selected method, not `admin_approval`, is stored as the order/payment method and determines the configured price calculation.

## View Rules

- Use `FormComponents` for fields, selectors, checkbox, button, token, and alerts.
- Use `ComponentsTemplate::showAButton()` for order links. It echoes output; do not wrap it in `echo`.
- Use the shared `PaymentHelpers::getPaymentMethods()` in both `manual-sell` and `orders-management`; do not recreate selector logic in a page controller.
- Show the original order total only when it differs from `total_after_discount`; otherwise show only the final total.
- The list is shown only when no Order ID is supplied. An Order ID switches to the detail/approval view.
- Deep links use `orders-management?OrderID={orderId}&Username={accountName}`. `OrderID` selects the detail view; `Username` is used when listing an account's orders.

## Search Filters

When investigating this feature, restrict searches to the files above and these symbols:

```text
orders-management
getAdminOrders
getAdminOrder
getAdminHistory
markPaidByAdmin
AdminApprovalPayment
getPaymentMethods
isAdminApproval
```

Skip templates, source-specific models, PayPal internals, and unrelated payment configuration unless the requested change names them or changes owner-field behavior.

For email-generated admin links, do not inspect the full admin page or payment providers: the query parameter contract above and `StoreModel::getTransactionByTrxIDByTrxID()` are sufficient.
