|
|
@@ -0,0 +1,397 @@
|
|
|
+# Feature Analysis — Per-Order-Item Print Status
|
|
|
+
|
|
|
+**Date:** 2026-05-12 (revised after dropping the "independent statuses" requirement)
|
|
|
+**Target plugin version after implementation:** 1.5.0 (minor bump — new feature, additive, non-breaking).
|
|
|
+**Status:** Analysis / planning document. No code has been written yet.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 1. Requirements as received
|
|
|
+
|
|
|
+> 1. Add new status for order item called `order-item-status`:
|
|
|
+> - `pending-print` — order item is waiting for printing process — *initial*
|
|
|
+> - `in-print` — order item is currently processing for print
|
|
|
+> - `done-print` — order item was printed
|
|
|
+> - `skip-print` — order item is skipped by some custom / system reason
|
|
|
+> 2. Add to order detail to order item possibility (combo box) to change order-item-status manually.
|
|
|
+> 3. When Order status is going to change to `done`, all order items must be `!= pending-print` and `!= in-print`.
|
|
|
+
|
|
|
+> *(Previous requirement #3 — "Order status and order-item-status are independent" — was withdrawn by the stakeholder; this analysis assumes order ↔ item coupling is allowed and beneficial. See §3 for the proposed coupling rules.)*
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. Logical revisions
|
|
|
+
|
|
|
+### 2.1 "When order status is going to change to `done`" — clarify what "done" means
|
|
|
+
|
|
|
+WooCommerce has no `wc-done` status. The plugin already adds `wc-to-print` and `wc-in-print`. The natural interpretation is the WC built-in `wc-completed`.
|
|
|
+
|
|
|
+**Proposed revision:** *"When the order status is going to change to `wc-completed`"*.
|
|
|
+
|
|
|
+### 2.2 What about non-product line items?
|
|
|
+
|
|
|
+Orders contain product items but also fee items, shipping items, coupon items, tax items, and refund items. None of these are printed.
|
|
|
+
|
|
|
+**Proposed revision:** the completion guard inspects only **product line items** (`WC_Order_Item_Product`). Other item types are not assigned a print status and never block completion.
|
|
|
+
|
|
|
+### 2.3 "Initial" value of `pending-print` — when is it set?
|
|
|
+
|
|
|
+The spec implies new items default to `pending-print`. Two strategies:
|
|
|
+
|
|
|
+- **Lazy (recommended):** the per-item meta is not written when the order is created. The `get_status()` helper returns `'pending-print'` when the meta is missing. Migration of existing orders is unnecessary.
|
|
|
+- **Eager:** write `pending-print` to every new item via `woocommerce_new_order_item`. Existing orders need a one-time backfill migration.
|
|
|
+
|
|
|
+**Proposed revision:** lazy default. Missing meta = `pending-print`. This avoids touching every existing order at activation time.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. Coupling rules between order status and item statuses
|
|
|
+
|
|
|
+With the "independence" constraint dropped, the design space opens up. The cleanest model is **one-way coupling, order → items**: changing an order status can propagate to items; changing an item status never propagates back to the order. Within that, we need to decide *which* order-status transitions propagate and how.
|
|
|
+
|
|
|
+The proposed rules:
|
|
|
+
|
|
|
+| Order status transition | Effect on product items |
|
|
|
+|--------------------------|-------------------------|
|
|
|
+| → `wc-to-print` (Prepare to Printing) | No automatic change. Items typically already `pending-print` (lazy default). |
|
|
|
+| → `wc-in-print` (In Printing) | **Items in `pending-print` advance to `in-print`.** `done-print` / `skip-print` items are untouched. |
|
|
|
+| → `wc-completed` | **Gated, not propagating** — the transition is *blocked* if any product item is still `pending-print` or `in-print`. Operator (or protocol import) must advance items first. |
|
|
|
+| → `wc-cancelled` / `wc-refunded` / `wc-failed` | No automatic change. Items stay where they are (historical record preserved). |
|
|
|
+| → `wc-processing` / `wc-pending` / `wc-on-hold` | No automatic change. |
|
|
|
+| Item status changed manually | Never propagates to order. The operator drives the order status separately. |
|
|
|
+
|
|
|
+Two distinct kinds of coupling are at play:
|
|
|
+
|
|
|
+- **Propagation** (`→ in-print`): the order transition *drives* item state. The listener that handles `woocommerce_order_status_changed` runs the propagation.
|
|
|
+- **Guard** (`→ completed`): the order transition *requires* items to already be in the right state. If not, the transition is reverted. The same listener implements the guard.
|
|
|
+
|
|
|
+Both behaviours live in a single hook on `woocommerce_order_status_changed`. The protocol imports become natural consumers of these rules:
|
|
|
+
|
|
|
+- **InPrint Protocol** calls `$order->update_status('in-print', ...)`. The propagation rule advances pending items to `in-print` automatically. No special-case code in the protocol importer.
|
|
|
+- **Delivered Protocol** calls `$order->update_status('completed', ...)`. The guard would block this if items are still `pending-print` or `in-print`. The protocol importer must therefore call `advance_remaining_to_done($order)` *before* the status flip.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. Open questions for stakeholder decision
|
|
|
+
|
|
|
+Before implementation begins, the following decisions should be confirmed:
|
|
|
+
|
|
|
+1. **Propagation on `→ in-print`** (§3): confirm "advance `pending-print` items to `in-print`" is the desired behaviour for manual order-status changes from the admin dropdown, bulk actions, *and* the InPrint Protocol import. Alternative: leave items untouched, require explicit per-item operations.
|
|
|
+2. **Audit trail:** should item-status changes write an entry to the order's activity feed? Recommendation: yes, with a brief note like *"Item #5 (Product Name): Pending Print → Done Print."*
|
|
|
+3. **`skip-print` reason:** is there a free-text "reason" field, or just the status? Recommendation: status only in v1.5.0; reason field as a future enhancement.
|
|
|
+4. **Bulk per-item operations across orders:** is there a need? Recommendation: not in v1.5.0 — single-order manual control plus protocol/propagation auto-advance covers the workflow.
|
|
|
+5. **CSV-export filter:** should "Prepare to Printing Export" filter to only `pending-print` items, or include everything? Recommendation: include everything, add `prod_print_status` column. Filtering can happen downstream.
|
|
|
+6. **Backwards-compatible behaviour for existing completed orders:** the completion guard applies only to *new* transitions to `wc-completed`. Already-completed orders are unaffected even if their items are `pending-print` (lazy default). Confirm this is acceptable.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. Proposed final specification
|
|
|
+
|
|
|
+After applying §2's revisions and §3's coupling rules:
|
|
|
+
|
|
|
+1. Each order item (specifically each `WC_Order_Item_Product`) has a print status with one of four values, persisted to per-item meta key `_print_status`. Missing meta defaults to `pending-print`.
|
|
|
+2. The order detail screen (classic order edit) adds a **"Print Status"** column to the line-items table with a `<select>` per product row. Saving the order persists changes.
|
|
|
+3. **Order → item propagation:**
|
|
|
+ - Transition into `wc-in-print` advances every `pending-print` item to `in-print`. `done-print` and `skip-print` items are untouched.
|
|
|
+ - All other order-status transitions leave item statuses unchanged.
|
|
|
+4. **Completion guard:** transition into `wc-completed` is blocked if any product item is `pending-print` or `in-print`. Blocked transition reverts to the previous status with an admin notice listing the blocking items.
|
|
|
+5. **Protocol imports:**
|
|
|
+ - **InPrint Protocol** sets order to `wc-in-print`; items auto-propagate per rule (3a). No explicit per-item code in the importer.
|
|
|
+ - **Delivered Protocol** explicitly advances every `pending-print` / `in-print` item to `done-print` before setting the order to `wc-completed`. The guard is satisfied; the operator gets one summary notice.
|
|
|
+6. **Item-status manual changes** never propagate to the order. Operator drives the order status independently.
|
|
|
+7. The CSV export from "Prepare to Printing Export" gains a `prod_print_status` column reflecting each item's current status.
|
|
|
+8. Item-status changes (manual or propagated) generate an order note: *"Item #ID (Product name): Old Status → New Status."*
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 6. Data model
|
|
|
+
|
|
|
+### 6.1 Storage
|
|
|
+
|
|
|
+- **Meta key:** `_print_status` (underscore prefix per WC convention for internal meta).
|
|
|
+- **Storage layer:** `WC_Order_Item::update_meta_data()` / `get_meta()`.
|
|
|
+- **Underlying table:** `{$wpdb->prefix}woocommerce_order_itemmeta`. This table exists under both HPOS and legacy CPT — WC uses the same item-meta storage in both modes.
|
|
|
+- **No database migration required** (lazy default).
|
|
|
+
|
|
|
+### 6.2 Constants
|
|
|
+
|
|
|
+```php
|
|
|
+class Order_Item_Status_Manager {
|
|
|
+ const STATUS_PENDING = 'pending-print';
|
|
|
+ const STATUS_IN = 'in-print';
|
|
|
+ const STATUS_DONE = 'done-print';
|
|
|
+ const STATUS_SKIP = 'skip-print';
|
|
|
+
|
|
|
+ const STATUSES_THAT_SATISFY_COMPLETION = array(
|
|
|
+ self::STATUS_DONE,
|
|
|
+ self::STATUS_SKIP,
|
|
|
+ );
|
|
|
+
|
|
|
+ public static function labels() {
|
|
|
+ return array(
|
|
|
+ self::STATUS_PENDING => __('Pending Print', 'studiou-wc-ord-print-statuses'),
|
|
|
+ self::STATUS_IN => __('In Print', 'studiou-wc-ord-print-statuses'),
|
|
|
+ self::STATUS_DONE => __('Done Print', 'studiou-wc-ord-print-statuses'),
|
|
|
+ self::STATUS_SKIP => __('Skip Print', 'studiou-wc-ord-print-statuses'),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 6.3 API surface
|
|
|
+
|
|
|
+A new `Order_Item_Status_Manager` class exposes:
|
|
|
+
|
|
|
+| Method | Purpose |
|
|
|
+|--------|---------|
|
|
|
+| `get_status(WC_Order_Item_Product $item): string` | Returns the item's print status; defaults to `STATUS_PENDING` when the meta is missing. |
|
|
|
+| `set_status(WC_Order_Item_Product $item, string $status, bool $audit = true): bool` | Validates the status, writes meta, optionally appends an order note. |
|
|
|
+| `valid_statuses(): array` | Returns the four constants. |
|
|
|
+| `is_order_ready_for_completion(WC_Order $order): array{ready:bool, blocking:WC_Order_Item_Product[]}` | Used by the completion guard and admin UI. |
|
|
|
+| `advance_pending_to_in(WC_Order $order): int` | Used by the propagation listener on `→ in-print`. Returns count advanced. |
|
|
|
+| `advance_remaining_to_done(WC_Order $order): int` | Used by `Delivered Protocol` import before completing. Returns count advanced. |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 7. Files & hooks
|
|
|
+
|
|
|
+### 7.1 New file: `includes/class-order-item-status-manager.php`
|
|
|
+
|
|
|
+Hooks registered in constructor:
|
|
|
+
|
|
|
+| Hook | Purpose |
|
|
|
+|------|---------|
|
|
|
+| `woocommerce_admin_order_item_headers` | Inject the "Print Status" column header. |
|
|
|
+| `woocommerce_admin_order_item_values` | Render the `<select>` per line item. |
|
|
|
+| `woocommerce_process_shop_order_meta` | Read `$_POST['print_status'][$item_id]`, persist via `set_status()`. Runs after WC's own item processing. |
|
|
|
+| `woocommerce_order_status_changed` (priority 5) | Combined propagation + completion guard (see §8). |
|
|
|
+
|
|
|
+### 7.2 Modified: `includes/class-db-manager.php`
|
|
|
+
|
|
|
+- `import_inprint_protocol()`: no functional change — propagation happens automatically via the listener when `$order->update_status('in-print', ...)` fires. Optionally surface the advanced count in the admin notice: *"3 line items advanced to In Print."*
|
|
|
+- `import_delivered_protocol()`: **before** calling `$order->update_status('completed', ...)`, call `Order_Item_Status_Manager::advance_remaining_to_done($order)` so the guard is satisfied. Surface the advanced count in the import-summary notice.
|
|
|
+- `get_orders_for_printing()`: extend the SELECT to surface item-level print status. Join `{$wpdb->prefix}woocommerce_order_items` (the item row) and `{$wpdb->prefix}woocommerce_order_itemmeta` (the `_print_status` meta) on `order_item_id`. Add `prod_print_status` to the CSV output. Note: the existing query groups by `(order, product, variation)` — multiple line items in one group would need a deterministic pick (e.g., `MIN()` again, or join via `order_products.order_item_id` if the lookup table exposes it).
|
|
|
+
|
|
|
+### 7.3 Modified: `studiou-wc-ord-print-statuses.php`
|
|
|
+
|
|
|
+Add the new manager to `load_dependencies()` and `initialize_managers()`, identical to the existing pattern. Bump `STUDIOU_WC_OPS_VERSION` to `1.5.0`.
|
|
|
+
|
|
|
+### 7.4 Modified: `includes/class-bulk-actions-manager.php`
|
|
|
+
|
|
|
+No code change. Bulk actions `"Set Status to Prepare to Printing"` and `"Set Status to In Printing"` already call `$order->update_status(...)` — the propagation listener handles items automatically when the transition is to `in-print`. The "Prepare to Printing" path doesn't propagate (per §3).
|
|
|
+
|
|
|
+### 7.5 Modified: `README.md`, `CLAUDE.md`, `docs/translations.txt`, `languages/studiou-wc-ord-print-statuses-cs_CZ.po`
|
|
|
+
|
|
|
+- README: new "Order item statuses" feature section + 1.5.0 changelog entry + coupling rules table from §3.
|
|
|
+- CLAUDE.md: extend the manager-pattern list with the new manager + Recent Changes entry.
|
|
|
+- Translations: add the four status labels, "Print Status" column header, guard error message, audit-note format, and the protocol auto-advance summary strings.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 8. Combined propagation + completion guard
|
|
|
+
|
|
|
+A single listener on `woocommerce_order_status_changed` handles both behaviours. Pseudocode:
|
|
|
+
|
|
|
+```php
|
|
|
+public function on_order_status_changed($order_id, $from, $to, $order) {
|
|
|
+ // Re-entrancy guard: a guard-revert below fires this hook again. Skip
|
|
|
+ // the recursive invocation.
|
|
|
+ if (self::$inside_self_revert) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($to === 'in-print') {
|
|
|
+ $advanced = $this->advance_pending_to_in($order);
|
|
|
+ if ($advanced > 0) {
|
|
|
+ UtilsLog::log("Order #{$order_id}: advanced {$advanced} item(s) to in-print on order → in-print");
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($to === 'completed') {
|
|
|
+ $check = $this->is_order_ready_for_completion($order);
|
|
|
+ if ($check['ready']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ self::$inside_self_revert = true;
|
|
|
+ try {
|
|
|
+ $order->update_status(
|
|
|
+ $from,
|
|
|
+ __('Cannot complete: product line items still pending print. Resolve item statuses first.', 'studiou-wc-ord-print-statuses')
|
|
|
+ );
|
|
|
+ } finally {
|
|
|
+ self::$inside_self_revert = false;
|
|
|
+ }
|
|
|
+ UtilsLog::message(
|
|
|
+ sprintf(
|
|
|
+ __('Order #%1$d completion blocked — %2$d product items not yet "Done Print" or "Skip Print".', 'studiou-wc-ord-print-statuses'),
|
|
|
+ $order_id,
|
|
|
+ count($check['blocking'])
|
|
|
+ ),
|
|
|
+ 'error'
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Caveats:**
|
|
|
+
|
|
|
+1. `woocommerce_order_status_changed` fires *after* the change is committed. Reverting via `update_status` is post-hoc — the order shows the reverted state on the next page load. Slightly disorienting but workable, and the admin notice explains it.
|
|
|
+2. The static `$inside_self_revert` flag prevents infinite recursion when the revert itself fires the hook.
|
|
|
+3. For cleaner UX on the admin form path, a complementary interception in `woocommerce_admin_process_order_object` can validate **before** save. The post-hoc revert still covers programmatic / API / protocol paths. Belt-and-braces.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 9. UI mockup (text)
|
|
|
+
|
|
|
+In the order edit screen's Items meta box, the table grows by one column:
|
|
|
+
|
|
|
+```
|
|
|
+| Item | Cost | Qty | Total | Print Status |
|
|
|
+|-----------------------|--------|-----|--------|----------------------|
|
|
|
+| Product A (variation) | 100.00 | 2 | 200.00 | [Pending Print ▼] |
|
|
|
+| Product B (variation) | 50.00 | 1 | 50.00 | [Done Print ▼] |
|
|
|
+| Shipping | — | — | 10.00 | — |
|
|
|
+| Coupon: SUMMER10 | -20.00 | — | -20.00 | — |
|
|
|
+```
|
|
|
+
|
|
|
+Non-product items show `—` and aren't editable.
|
|
|
+
|
|
|
+Optional v1.5.0 sweetener: a one-line summary above the table — *"Print readiness: 3 of 4 items ready (1 pending)."*
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 10. Edge cases & open behaviour decisions
|
|
|
+
|
|
|
+| Scenario | Proposed behaviour |
|
|
|
+|----------|---------------------|
|
|
|
+| Order has 0 product items | Completion allowed (vacuously satisfies the guard). |
|
|
|
+| Order has only refunds / shipping / fees | Completion allowed. |
|
|
|
+| Existing `wc-completed` order with items in `pending-print` | No effect — the guard only fires on the *transition* into `completed`, not on stored state. |
|
|
|
+| Manual order status flip Pending → Completed (skipping in-print) | Guard fires. Items are still `pending-print` → blocked. Operator must advance items or use protocol imports. |
|
|
|
+| Order in `wc-in-print` reverted to `wc-processing` then back to `wc-in-print` | First revert: no item change (per §3). Second forward: pending items advance again (no-op since they're already `in-print`). Done items stay done. |
|
|
|
+| Item is removed from order after being set to `done-print` | The meta is deleted along with the item. No orphan record. |
|
|
|
+| Item status changed *after* order is `completed` | Allowed. Order doesn't revert. |
|
|
|
+| Bulk action "Set Status to In Printing" on 100 orders | Each order's pending items propagate to `in-print` via the listener. |
|
|
|
+| Multiple `wc-in-print` ↔ `wc-to-print` ping-pong | Each → `in-print` advances any remaining `pending-print` items. Items previously moved stay in `in-print`. |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 11. Test plan
|
|
|
+
|
|
|
+### 11.1 Unit-style scenarios
|
|
|
+
|
|
|
+1. **Default value:** new order item has no `_print_status` meta; `get_status()` returns `'pending-print'`.
|
|
|
+2. **Set status:** `set_status($item, 'in-print')` writes the meta and (with `$audit=true`) appends an order note.
|
|
|
+3. **Invalid status:** `set_status($item, 'foo')` rejects and returns `false` without writing.
|
|
|
+4. **Completion guard ready:** all items in `done-print` or `skip-print` — `is_order_ready_for_completion()` returns `{ready:true}`.
|
|
|
+5. **Completion guard blocked:** at least one item in `pending-print` or `in-print` — returns `{ready:false, blocking:[…]}`.
|
|
|
+6. **Non-product items ignored:** an order with one product item (`done-print`) and one shipping item — guard returns ready.
|
|
|
+7. **`advance_pending_to_in`:** order with items `[pending, in, done, skip]` → result has items `[in, in, done, skip]`. Count = 1.
|
|
|
+8. **`advance_remaining_to_done`:** order with items `[pending, in, done, skip]` → result `[done, done, done, skip]`. Count = 2.
|
|
|
+
|
|
|
+### 11.2 Integration
|
|
|
+
|
|
|
+1. **Admin UI manual change:** open an order with three items, change one to `done-print`, click Update, reload → meta persisted, audit note added.
|
|
|
+2. **Propagation:** change order status to `wc-in-print` via the admin dropdown → all `pending-print` items in the order are now `in-print`. Order note from `update_status` plus per-item audit notes.
|
|
|
+3. **Completion guard via admin:** with one item still `pending-print`, change order status to `wc-completed`, click Update → order reverts to previous status (visible after reload), admin notice shows the block reason.
|
|
|
+4. **Completion guard via programmatic call:** `wp wc shop_order update <id> --status=completed` on an order with `pending-print` items → status reverts.
|
|
|
+5. **InPrint Protocol import:** prepare a CSV with one `order_no`, run the import → order is in `in-print`, all the order's `pending-print` items advanced to `in-print` via the listener, `done-print` and `skip-print` items untouched. Import notice mentions advanced count.
|
|
|
+6. **Delivered Protocol import:** prepare a CSV with one `order_no`, run the import → items advance to `done-print` first, then order flips to `completed`. Guard is satisfied. Import notice mentions advanced count.
|
|
|
+7. **CSV export:** "Prepare to Printing Export" bulk action — output contains a `prod_print_status` column with per-item values.
|
|
|
+
|
|
|
+### 11.3 Regression
|
|
|
+
|
|
|
+1. The "Set Status to Prepare to Printing" bulk action still works without touching items (no propagation on `→ to-print`).
|
|
|
+2. The "Set Status to In Printing" bulk action now also propagates items (new behaviour — expected).
|
|
|
+3. Existing completed orders are unaffected by the new guard.
|
|
|
+4. The Print Information panel on the order edit screen still renders.
|
|
|
+5. The custom orders-list columns still render.
|
|
|
+6. The order search by external reference still works.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 12. Rollout
|
|
|
+
|
|
|
+### 12.1 Versioning
|
|
|
+
|
|
|
+- New plugin version: **1.5.0** (minor — feature addition, no breaking changes).
|
|
|
+- `STUDIOU_WC_OPS_VERSION` constant updated accordingly.
|
|
|
+
|
|
|
+### 12.2 Activation behaviour
|
|
|
+
|
|
|
+- No database migration. Lazy defaults handle existing items.
|
|
|
+- No new tables. The `woocommerce_order_itemmeta` table is already created by WC.
|
|
|
+
|
|
|
+### 12.3 Deactivation behaviour
|
|
|
+
|
|
|
+- Same policy as today: meta keys are not cleaned up. Reactivation preserves all data.
|
|
|
+
|
|
|
+### 12.4 Internationalisation
|
|
|
+
|
|
|
+~12 new translatable strings:
|
|
|
+
|
|
|
+- 4 status labels: `Pending Print`, `In Print`, `Done Print`, `Skip Print`.
|
|
|
+- 1 column header: `Print Status`.
|
|
|
+- 1 placeholder for non-product items: `—` (literal, not translated).
|
|
|
+- 1 completion-guard order note: `Cannot complete: product line items still pending print. Resolve item statuses first.`
|
|
|
+- 1 admin notice: `Order #%1$d completion blocked — %2$d product items not yet "Done Print" or "Skip Print".`
|
|
|
+- 1 audit-note format: `Item #%1$d (%2$s): %3$s → %4$s.`
|
|
|
+- 2 protocol-auto-advance order notes: `%d items advanced to In Print by order-status change.`, `%d items advanced to Done Print by Delivered Protocol import.`
|
|
|
+- 1 readiness summary (optional UI sweetener): `Print readiness: %1$d of %2$d items ready (%3$d pending).`
|
|
|
+
|
|
|
+### 12.5 Documentation
|
|
|
+
|
|
|
+- README: new "Order item statuses" feature section + coupling rules table + 1.5.0 changelog entry + Known Limitations updated (block-based screen still unsupported).
|
|
|
+- CLAUDE.md: new manager added to the manager-pattern list + Recent Changes entry.
|
|
|
+- New review doc (post-release): `docs/revise-1.5.0.md` once the feature lands.
|
|
|
+- `docs/feature-order-item-status-analysis.md` (this document) → archive or supersede after implementation.
|
|
|
+
|
|
|
+### 12.6 Phasing (suggested)
|
|
|
+
|
|
|
+- **Phase 1 (v1.5.0):** core feature — data model, admin UI, propagation listener, completion guard, Delivered Protocol explicit advance, CSV export column. Classic order edit screen only.
|
|
|
+- **Phase 2 (v1.5.x or later):** AJAX live status changes (no full page reload), bulk-change items across orders, optional `skip-print` reason field, block-based order edit screen support.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 13. Effort estimate
|
|
|
+
|
|
|
+Rough sizing for Phase 1:
|
|
|
+
|
|
|
+| Area | Effort |
|
|
|
+|------|--------|
|
|
|
+| `Order_Item_Status_Manager` class (data model + admin UI + combined propagation/guard listener) | ~6–10 hours |
|
|
|
+| `Studiou_DB_Manager` integration (Delivered Protocol advance, CSV column with new join) | ~2–3 hours |
|
|
|
+| Bootstrap + manager wiring + version bump | ~30 minutes |
|
|
|
+| README / CLAUDE.md / translations / .po | ~2 hours |
|
|
|
+| Test pass (manual scenarios in §11) | ~3–4 hours |
|
|
|
+| **Total** | **~14–20 hours** |
|
|
|
+
|
|
|
+Phase 2 items add ~6–10 hours each depending on scope.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 14. Risk register
|
|
|
+
|
|
|
+| Risk | Likelihood | Impact | Mitigation |
|
|
|
+|------|------------|--------|------------|
|
|
|
+| Listener recursion (propagation → save → propagation, or guard-revert → revert → revert) | Medium | High | Static `$inside_self_revert` flag; propagation only fires on `→ in-print` not on every save. |
|
|
|
+| Existing orders break on first edit because meta is missing | Low | Low | Lazy default handles this — `get_status` returns `pending-print` for missing meta. |
|
|
|
+| Operator surprise: clicking "Set Status to In Printing" silently advances items | Low | Low | Documented in README; per-item audit notes show what happened. |
|
|
|
+| Block-based order edit screen doesn't render the new column | Medium | Low | Documented as a known limitation since 1.4.1; carried forward. |
|
|
|
+| `_print_status` meta key collides with another plugin | Very low | Medium | If collision found, fall back to a namespaced key (`_studiou_print_status`). |
|
|
|
+| Delivered Protocol "advance to done" advances items the operator intended to leave in `skip-print` | None | — | `skip-print` already satisfies the completion guard; the advance helper only touches `pending-print` / `in-print`. |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 15. Recommendation
|
|
|
+
|
|
|
+Implement Phase 1 as described above, subject to stakeholder confirmation of the §4 open questions — particularly:
|
|
|
+
|
|
|
+- Open question 1 (propagation on `→ in-print`). The proposed design assumes "yes, advance pending items". This is the workflow-consistent choice, but it does change the behaviour of the existing **bulk action "Set Status to In Printing"** (previously order-only, now also touches items). If the stakeholder prefers the bulk action to remain strictly order-only, the propagation rule can be limited to specific paths (e.g., only the InPrint Protocol import) — but that re-introduces some of the awkwardness the old §2.5 grappled with.
|
|
|
+
|
|
|
+The shape of the design with requirement #3 dropped is materially cleaner than the original analysis: a single listener implements both behaviours, the protocol-import code paths are minimally changed, and the rules can be summarised in one table (§3).
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+*End of analysis.*
|