Exodus Salesforce Docs
QA Runbooks

Safin E2E Runbook

Fresh-run Salesforce, 3PL, and fulfillment validation flow

Scope

The Safin E2E validates the full nicotine-product order path in the Salesforce dev sandbox at https://exodus--safin.sandbox.lightning.force.com/. This is not the QA org; QA links and QA deployment checks use Vesper.

Items must be created in Item Manager: https://exodus--safin.sandbox.lightning.force.com/lightning/n/Item_Bulk_Editor.

Purchase Orders and CMPOs must be created from the Pipeline New Order button: https://exodus--safin.sandbox.lightning.force.com/lightning/n/Purchase_Order_Pipeline.

Each run generates unique names and writes a manifest under .artifacts/e2e/safin/<run-label>/manifest.json. Customer Accounts are not seeded; they must be created by lead conversion. The setup phase may seed fake Vendor Accounts and fake internal Warehouses because the Salesforce custom modals expect those prerequisite records to already exist.

Commands

npm run e2e:safin:preflight
npm run e2e:safin:setup -- --allow-mutations
npm run e2e:safin:replay -- --allow-mutations
npm run e2e:safin:verify

Resume from a failed step:

npm run e2e:safin:resume -- --from create-po-and-cmpo --allow-mutations

Approval/payment submission remains separately gated:

npm run e2e:safin:replay -- --allow-mutations --allow-payment-submit

Flow

  1. Preflight checks the Chrome app, Computer Use MCP tools, Salesforce auth, Sandbox A/B payment gateways, and the existing Pakmo/Kandy Kush 3PL warehouses.
  2. Setup creates generated fake Vendor Accounts and generated fake internal Warehouses. It does not create 3PL metadata.
  3. Item setup creates one generated nicotine item group, six finished-good nicotine variants, and ten support items through Item Manager. Do not use the standard Item list-view New button.
  4. BOM setup creates one WIP BOM and finished-good BOMs that consume raw material, packaging, labor, and service components.
  5. PO/CMPO setup uses the Pipeline New Order purchase order modal to create raw material/packaging Standard POs and a finished-good CMPO, then receives them. Do not use the standard Purchase Order object New button.
  6. CRM creates duplicate leads, tests duplicate detection and merge behavior, transfers ownership, and converts a lead into Account, Contact, and Opportunity.
  7. Commissions creates item-group and item-level commission configurations for the generated nicotine products.
  8. Quote/order creates quotes, rejects the first approval attempt, approves the second, converts/syncs to a Sales Order, and creates one manual Sales Order.
  9. Fulfillment navigates the same Chrome tab through OrderDesk, Packiyo, and Katana sandboxes to fulfill the provider-backed orders.
  10. Verification checks item coverage, BOM depth, PO/CMPO receipt, inventory movement, duplicate lead conversion, commission setup, quote approval history, Sales Orders, sync state, and provider writeback.

Payment Vault Checkpoints

Quote submission must use the custom submission action and collect the required payment fields. Use Authorize.Net sandbox card 4242424242424242, expiration 12/2030, CVV 123, and save it to the customer vault. The first approval review should reject only after that submission record exists; the second review should approve through the same review action.

On the resulting Sales Order, open the payment console and verify the Account / Contact Payment Vault section. The saved 4242 card should show gateway tokens for Sandbox A and Sandbox B, and route-level token selectors should offer that saved method before the new-card option.

3PL Inventory Checkpoints

Pakmo and Kandy Kush inventory is provider-owned. Do not create Inventory Sync Audit runs or manual 3PL adjustments. The replay should assert mirrored provider rows on Inventory__c, including source system, provider snapshot time, provider quantity, and mirror status. Manual inventory controls remain valid only for generated non-3PL warehouses used for raw materials, packaging, labor/service accounting, tax/credit lines, and PO/CMPO staging.

For Salesforce-managed inventory, use Item Manager inventory controls rather than editing Inventory__c directly. Raw materials, packaging, marketing kits, and other internal stock should use Set counted on hand for cycle counts and Apply quantity change for known deltas. Every saved adjustment must include a warehouse, structured reason, required details, optional count-sheet/work-order reference, before/after quantities, and an Inventory_Transaction__c history row.

Failure Handling

If an LWC or Apex surface breaks, capture the failed step ID, preserve the manifest, fix the target component or controller, add focused Jest/Apex coverage where applicable, deploy only the changed metadata, then resume from the failed step.

Current 3PL Sandbox Notes

OrderDesk must be visited before Packiyo in sandbox runs. Open the New folder at https://app.orderdesk.me/orders?folder=689707, search the Salesforce provider display number, then click the Packiyo submit button:

button[name="submit_to_packiyo"][value="1"],
button.btn-integration-packiyo

After Packiyo receives the order, open https://sandbox.app.packiyo.com/order/<packiyoOrderId>/edit and use Mark as fulfilled only when the test intentionally exercises status-only fulfillment. If Packiyo creates no shipment or tracking record, Salesforce must not close the Sales Order. The expected Salesforce state is Status__c = In Progress, Fulfillment_Sync_Status__c = Acknowledged, and Fulfillment_Sync_Complete__c = false until packed-line evidence is available.

For SAFIN-E2E-NIC-20260512T163353Z, Packiyo order 19176 has now been fulfilled through the managed Packiyo API:

  1. Open Pack Orders and search for SO-011654-10C97805B2.
  2. Click the table row itself, not the blue order-number link. The row's packing_url should navigate to https://sandbox.app.packiyo.com/packing/single_order_shipping/19176.
  3. If Packiyo says No orders with unpacked items found, inspect the order detail. In the current run, order 19176 is not packable because Packiyo reports the three physical SKUs as backordered and the direct packing route shows 0 Items in Order / 0 Items Remain.
  4. Packiyo Create PO can populate the required stock lines without typing: open https://sandbox.app.packiyo.com/purchase_orders/create, keep or enter PO number SAFINPO011654, click Add all backorders, and assert rows for FG-BI9 = 24, FG-MF9 = 24, and FG-CM3 = 60.
  5. The next UI control is the required warehouse selector. In the current Chrome run, opening that selector displayed Please enter 1 or more characters, then Packiyo page-level Chrome controls began timing out. Normal text entry is also blocked by the missing Browser Use virtual clipboard.
  6. The local .env.safin.local Packiyo token returned 401 Unauthenticated, so stock was added through the Salesforce managed Packiyo provider account instead. Managed auth resolved to https://sandbox.app.packiyo.com, found TEST LOCATION id 318, and posted { "location_id": 318, "quantity": 120 } for products 502, 503, and 504.
  7. Verification shows all three physical SKUs at quantity_on_hand = 120, quantity_backordered = 0, and allocated quantities matching the order (24, 24, 60).
  8. Shipment was created with POST /api/v1/orders/19176/shipments using TEST BOX id 10. Packiyo returned shipment 159, tracking SAFIN-TRACK-SO-011654, and label https://sandbox.app.packiyo.com/shipment/159/label/155.
  9. Packiyo verification shows order 19176 as Fulfilled, ready_to_ship = 0, ready_to_pick = 0, and quantity_pending = 0.

Katana did not receive SO-011654 from the mixed-provider Salesforce runtime automatically, so the replay harness created and fulfilled the Kandy Kush portion through the Katana API. The run artifact is .artifacts/e2e/safin/SAFIN-E2E-NIC-20260512T163353Z/katana-fulfill-so-011654.json; it records Katana sales order 45090132, fulfillment 39275646, and row ids 109386676 / 109386677.

Salesforce writeback for SO-011654 is now complete in the sandbox. The final state is:

  • Sales_Order__c: SO-011654, Closed, Fulfilled, Fulfillment_Sync_Complete__c = true, 108/108.
  • Shipped_Line__c: SHP-001079 BI9 24, SHP-001080 MF9 24, SHP-001081 CM3 60.
  • Sales_Order_Tracking__c: SOT-000270 Packiyo shipment 159, SOT-000271 Katana fulfillment 39275646.
  • ThreePL_Record_Sync_State__c: TSS-00048 OrderDesk/Packiyo success, TSS-00049 Katana success.

The current resume point is production hardening, not data completion. The local provider-splitting/runtime fixes still need deployment after Apex size cleanup:

  • features-orders/main/default/classes/threepl/runtime/ThreePLRuntimeService.cls
  • features-orders/main/default/classes/sales_order/services/FulfillmentOrderUpdateService.cls
  • features-orders/main/default/classes/tests/threepl/ThreePLRuntimeServiceTest.cls

Validation-rule deploy 0AffY000004C0UzSAK succeeded and is already in the sandbox. Apex deploy 0AffY000004C0bRSAS for the local FulfillmentOrderUpdateService side-effect fix failed because the sandbox exceeds the 6,000,000 Apex character limit. Reduce deployed Apex size or remove stale Apex, then deploy the local fulfillment writeback fixes and rerun the strict provider replay without harness suppressors.

Screen recordings should be placed under docs/evidence/safin-e2e/<run-label>/ and linked from this page after the flow is stable.

Last updated on

On this page