# Fix: Courtesy Cushion DuplicateMostRecentScanRequest Missing Job Assignment

## Context

When a courtesy/replacement cushion `BigOrder` is created via `POST /admin/shop/shopify_order` with `scanRequestAction: DuplicateMostRecentScanRequest`, the customer's most recent scan request is correctly duplicated and linked to the new BigOrder. However, the code stops there — it never proceeds to create a `Job` and assign it to the cushion line item on the BigOrder. This means the line item's `currentJobId` is never set, making the BigOrder not shippable even after the physical item is produced.

By contrast, when `CreateNewScanRequest` is used, the code calls `updateBigOrderInternal` with a `SendScanRequest` action, which enters the full checklist workflow and eventually leads to job creation + line item assignment.

## Root Cause

In `api/src/fabricator/FabricatorAdminApi.ts`, the `DuplicateMostRecentScanRequest` code path in `createCustomShopifyOrder` (lines 833-849) only calls `duplicateScanRequestInternal`, which creates/verifies the scan request but never triggers job creation. The same bug exists in two other locations:
- `createCustomShopifyOrder2` (lines 988-1004)
- `createBigOrder` (lines 1137-1161)

## Fix

**File:** `api/src/fabricator/FabricatorAdminApi.ts`

After the successful `duplicateScanRequestInternal` call in each of the three `DuplicateMostRecentScanRequest` code paths, add a call to `updateBigOrderInternal` with `CreateJob` action. This mirrors the lock-acquire + updateBigOrderInternal pattern used by the `CreateNewScanRequest` path, but uses `CreateJob` since the scan is already verified and ready.

### Location 1: `createCustomShopifyOrder` (~line 844)
After `const newScanRequest = await FabricatorAdminApi.duplicateScanRequestInternal(...)`, add:
```typescript
// After duplicating the scan request, create a job and assign it to the line item
try {
    const bigOrderLock = await FactoryApiUtils.ACQUIRE_ITEM_LOCK("createBigOrderFromShopifyOrder", result.bigOrder);
    try {
        await FabricatorAdminApi.updateBigOrderInternal(req, { action: FabricatorSchemas.BigOrderAction.CreateJob, bigOrderId: result.bigOrder.id }, bigOrderLock);
    } finally {
        await FactoryApiUtils.RELEASE_ITEM_LOCK(bigOrderLock);
    }
} catch (ex) {
    Logger.error(ex);
    result.errors.push({ message: "Failed to create job from duplicated scan request." });
}
```

### Location 2: `createCustomShopifyOrder2` (~line 1000)
Same pattern as Location 1, using the same `result.bigOrder` variable.

### Location 3: `createBigOrder` (~line 1154)
Same pattern, but using `createdBigOrder` instead of `result.bigOrder`.

## New Test

**File:** `tests/fabricator/146.CourtesyCushionJobAssignment.ts`

A focused integration test that verifies the complete courtesy cushion flow with `DuplicateMostRecentScanRequest`, specifically checking that `currentJobId` is set on the line item.

### Test Steps:
1. **Setup:** Get admin account, clean test data, find test bigscreen account by email
2. **Step 1 - Create first order with Beyond product:** Create a Beyond 2 + Cushion order via `shopify_order_2`, then complete the full scan workflow (send scan request, verify topology, verify scan, set IPD)
3. **Step 2 - Create courtesy cushion order:** Create a second order with ONLY a replacement cushion via `POST /admin/shop/shopify_order` using `DuplicateMostRecentScanRequest`
4. **Step 3 - Verify job assignment:** Fetch the second BigOrder and assert that:
   - The cushion line item exists (type `ReplacementBeyondCushionV1`)
   - The line item has a non-empty `currentJobId`
   - The line item has a `jobIds` array containing the `currentJobId`
5. **Cleanup:** Delete test shopify orders

### Key test assertions:
```typescript
const cushionLineItem = res.body.currentLineItems.find(
    (item: any) => item.type === FabricatorSchemas.BigProductType.ReplacementBeyondCushionV1
);
should.exist(cushionLineItem);
cushionLineItem.should.have.property("currentJobId");
cushionLineItem.currentJobId.should.not.be.empty;
cushionLineItem.should.have.property("jobIds").be.an("array");
cushionLineItem.jobIds.should.include(cushionLineItem.currentJobId);
```

### Test structure modeled after:
- `tests/fabricator/061.ReplacementCushionDuplicateScan.ts` (same setup flow, same constants)
- Uses same imports, admin account setup, and shopify email constant

## Files to Modify
1. `api/src/fabricator/FabricatorAdminApi.ts` — Add job creation after scan duplication in 3 locations
2. `tests/fabricator/146.CourtesyCushionJobAssignment.ts` — New test file

## Verification
Run the new test from the `tests` directory:
```
ts-mocha --bail --exit --timeout=500000 fabricator/146.CourtesyCushionJobAssignment.ts
```
Also re-run the existing test to ensure no regressions:
```
ts-mocha --bail --exit --timeout=500000 fabricator/061.ReplacementCushionDuplicateScan.ts
```
