Developer notes
Overview · Installation · Configuration · Usage · FAQ
How the desk finds orders
Section titled “How the desk finds orders”Every list, count, bulk scope and single-order check starts from what core fn_get_orders() builds for the current user (get_conditions): the company condition (vendor = own orders, Ultimate = selected storefront), the 4.21 storefront restrictions of administrators, hidden parent orders, and every condition that core and other add-ons add through the pre_get_orders / get_orders hooks. The desk filters are added on top. So the desk never shows or changes an order that the core orders list hides from the same user.
- Paging and counting run on the server (
COUNT(DISTINCT order_id)+LIMIT), sorted by indexed columns (timestamp,order_id,status,total). - The quick search uses the indexed order id; e-mail, name and phone use
LIKE; the SKU search uses a sub-query onorder_details.product_code(prefix match). - Row data (items, thumbnails, shipping and payment names, tags, note counts, customer order counts, countries) is loaded per page in one query per kind, never per row, and only for the visible columns.
- Measured on Multi-Vendor 4.21.2 with 50,000 orders: see the FAQ.
Status changes
Section titled “Status changes”The desk changes statuses only with core fn_change_order_status() and the core notification rules (fn_get_notification_rules()), exactly like the core orders list. Stock, invoices and credit memos, e-mails, the order history of other add-ons and their hooks behave as usual. If core or another add-on keeps the old status, the desk reports it.
Duplicate / reorder opens the core order editor (order_management.edit?order_id=N©=1). Invoices and packing slips use core fn_print_order_invoices() / fn_print_order_packing_slips().
Data model
Section titled “Data model”| Table | Contents |
|---|---|
?:kv_oap_tags |
tag_id, company_id (owner scope: 0 = store administration, vendor id on Multi-Vendor), name, color, position |
?:kv_oap_order_tags |
order_id, tag_id (primary key both; index on tag_id) |
?:kv_oap_events |
timeline: event_id, order_id, company_id (author scope), user_id, type (status, note, tag_add, tag_remove, email, print, export), data (JSON), created_at; index (order_id, event_id) |
?:kv_oap_views |
saved views: user, scope, name, shared flag, params (JSON) |
?:kv_oap_prefs |
per-user columns, sorting, page size |
?:kv_oap_templates |
message templates per scope |
?:kv_oap_jobs |
running bulk actions (spec, order ids, cursor, counters); rows older than 7 days are removed when a new job starts |
Deleting an order (core fn_delete_order()) removes its tags and timeline entries (delete_order hook).
Hooks used
Section titled “Hooks used”| Hook | Why |
|---|---|
change_order_status_post |
Timeline entry for every status change (same arguments in 4.17.2 and 4.21.2) |
delete_order |
Cleanup of tags and timeline entries |
Template hook orders:tabs_extra + orders.post.php |
The Tags & timeline tab on the order page |
The add-on prints nothing on the storefront and writes nothing on storefront GET requests (4.21 full page cache: nothing to do). The status hook also runs at checkout and in payment callbacks; it only inserts one row and never throws.
Endpoints (admin.php / vendor.php?dispatch=kv_order_admin_pro.<mode>)
Section titled “Endpoints (admin.php / vendor.php?dispatch=kv_order_admin_pro.<mode>)”| Mode | Method | Purpose |
|---|---|---|
manage |
GET | The desk page |
rows |
GET | JSON page of orders (filters, columns, sort, dir, page, per_page) |
quick_view, timeline |
GET | JSON with the drawer / timeline HTML |
status, tags_set, note_add |
POST | Single-order actions |
tag_save, tag_delete, view_save, view_delete, prefs_save, template_save, template_delete |
POST | Settings of the desk |
bulk_preview, bulk_start, bulk_step |
POST | Bulk actions (scope = ids or filters) |
export, print, pick_list |
POST | CSV download, invoices / packing slips, pick list |
All POST requests use the core form protection (security_hash). Permission schema: view_orders; the controller checks change_order_status, update_order_details and exim_access per action, and the order scope for every order id.
Licence gate
Section titled “Licence gate”License\Client::isActive() gates bulk_preview, bulk_start, export, print and pick_list. A started bulk job is always finished (bulk_step is not gated), so no half-applied action is left behind. The desk, quick view, single status changes, tags, notes and the timeline are never gated.
File map
Section titled “File map”app/addons/kv_order_admin_pro/ addon.xml settings, tables, e-mail template init.php, func.php hooks, settings info, licence helpers controllers/backend/kv_order_admin_pro.php desk controller (admin + vendor panel) controllers/backend/orders.post.php Tags & timeline tab on the order page controllers/backend/kv_order_admin_pro_license.php "Check now" / cron licence check schemas/menu/menu.post.php, menu_vendor.post.php Orders > Order desk schemas/permissions/admin.post.php, vendor_multivendor.post.php Tygh/Addons/KvOrderAdminPro/ Access.php privileges, scope, licence Query.php core order conditions + desk filters, paging, scope ids Rows.php batch loading of the row data Tags.php, Timeline.php, Views.php, Prefs.php, Templates.php Bulk.php preview, jobs, steps, status change Export.php CSV PickList.php aggregated SKUs Ui.php desk configuration, statuses, formatting License/ domain-bound licence client Upgrade/ self-healing upgrade synchronizerdesign/backend/templates/addons/kv_order_admin_pro/ views/kv_order_admin_pro/manage.tpl, quick_view.tpl, pick_list.tpl, components/timeline.tpl hooks/orders/tabs_extra.post.tpl, hooks/index/styles.post.tpl, license/*design/backend/css/addons/kv_order_admin_pro/styles.less, license.lessjs/addons/kv_order_admin_pro/desk.jsvar/langs/en/addons/kv_order_admin_pro.po