Architecture¶
Class overview¶
AsyncBulkOrderCompletionLoader (entry point, wires all modules via Module trait)
├── Backend\Application (injects <order-completion-app> web component into wp-admin footer)
├── Backend\Orders (enqueues JS, shows pending-completion admin notice on order edit screen)
├── Backend\OrderActions (registers & handles "Change status to completed" bulk action)
├── Backend\Scheduler (Action Scheduler listener; processes batches, auto-retries on failure)
├── RESTndpointsndpoints (registers REST namespace + routes)
│ └── RESTndpoints\Jobs (GET /wp-json/async-bulk-order-completion/v1/jobs)
└── Data\
├── Database (creates custom tables on activation)
├── Models\Job (job entity: id, user_id, completed, created_at, completed_at)
├── Models\JobOrder (order-in-job entity: id, job_id, order_id, completed_at)
├── Stores\JobStore (CRUD for order_completion_jobs)
└── Stores\JobOrderStore (CRUD for order_completion_orders)
The front-end is a compiled Vue web component (src/assets/js/order-completion-app.min.js) that polls the REST API and displays job/order status in the WooCommerce admin footer.
Database schema¶
erDiagram
WP_USERS {
bigint ID PK
string user_login
string display_name
}
ORDER_COMPLETION_JOBS {
int id PK
bigint user_id FK
tinyint completed
datetime created_at
datetime completed_at
}
ORDER_COMPLETION_ORDERS {
int id PK
int job_id FK
int order_id
datetime completed_at
}
WC_ORDERS_OR_POSTS {
int ID PK
string status
}
WP_USERS ||--o{ ORDER_COMPLETION_JOBS : "created_by"
ORDER_COMPLETION_JOBS ||--o{ ORDER_COMPLETION_ORDERS : "contains"
ORDER_COMPLETION_ORDERS }o--|| WC_ORDERS_OR_POSTS : "references" Tables are prefixed with $wpdb->prefix. The foreign key from order_completion_orders.job_id to order_completion_jobs.id uses ON DELETE CASCADE.
Async completion flow¶
sequenceDiagram
actor Admin
participant WC_Admin as WooCommerce Admin
participant OrderActions
participant functions.php
participant ActionScheduler as Action Scheduler
participant Scheduler
Admin->>WC_Admin: Select orders → bulk action "Change status to completed"
WC_Admin->>OrderActions: handle_bulk_actions()
OrderActions->>functions.php: create_async_order_completion_batch($order_ids)
functions.php->>functions.php: INSERT job into order_completion_jobs
functions.php->>functions.php: INSERT each order into order_completion_orders
functions.php->>ActionScheduler: as_enqueue_async_action("batch-order-completion", {job_id})
ActionScheduler-->>Admin: Redirect back (immediate)
Note over ActionScheduler,Scheduler: Background processing
ActionScheduler->>Scheduler: on_batch_order_completion($job_id)
loop For each pending JobOrder
Scheduler->>Scheduler: Fetch WC order
Scheduler->>Scheduler: update_status("completed")
Scheduler->>Scheduler: Mark JobOrder completed_at
end
Scheduler->>Scheduler: Mark Job completed Failure recovery¶
If Action Scheduler marks the batch-order-completion action as failed, Scheduler::maybe_restart_batch_job() listens on action_scheduler_failed_action and resets the action status back to pending, causing it to be retried automatically.