當變體價格變更時,自動同步套裝價格

當您使用「Shopify 的**「Bundles」**應用程式 來建立產品組合時,若變更組成產品的變體價格,組合產品的變體價格並不會自動更新。來自 Workflow Trigger Extensions 的「產品變體價格變更」觸發器,可透過偵測價格變更,並自動重新計算及更新組合的變體價格,來解決此問題。


為了了解如何利用「**產品變體價格變更」**觸發器來保持套裝價格的同步,我們將假設以下情境。

情境:當元件變體價格變更時,自動更新套裝價格

假設您使用「Shopify」套裝應用程式建立了一個套裝商品(例如 T 恤套裝)。該套裝包含三項組成商品:黑色 T 恤、灰色 T 恤和白色 T 恤,每種變體的價格皆為 10.00 歐元。 此組合變體的價格為 30.00 歐元(即所有組成產品價格的總和)。當您變更某項組成產品的變體價格時,此流程將自動更新對應的組合變體價格。

請從應用程式設定 → 產品變體 → 變體價格變更 中啟用此觸發器

產品變體價格已變更

取得父級組合商品,計算更新後的變體價格,並透過管理員 API 批次更新組合變體價格

影片指南

您也可以透過這段影片直觀地了解各個步驟(影片無聲音,您可以根據需要調整影片播放速度)

我們將如何讓這一切順利進行

了解設定方式

  • 我們有一項組件產品(例如:灰色 T 恤),其變體包括 S、M、L、XL、2XL,每種尺寸的價格均為 10.00 歐元
  • 我們使用「Shopify Bundles」應用程式建立了一個組合商品。該組合包含 3 項商品(黑色 T 恤、灰色 T 恤、白色 T 恤),每項各有 5 種變體。此組合變體的價格為 30.00 歐元(各組成商品價格之和:3 × 10.00 歐元)。

您可以在這裡直觀地看到所遵循的步驟:

  • Workflow Trigger Extensions 中,開啟**「觸發器**」,搜尋「價格」,並啟用「產品變體價格變更」功能。此功能需要「產品」、「變體」及「系列」資料存取權限;若缺少相關權限,應用程式會主動提示您授予權限。
  • 在「Shopify Flow」應用程式中建立一個新的空白工作流程,並從「Workflow Trigger Extensions應用程式中選取「產品變體價格變更」觸發器
  • 新增一個「取得產品資料」動作,透過進階查詢擷取已變更的產品,並依**「建立時間」**升序排序。此步驟會透過「productParents」欄位擷取該產品的父級套裝資訊。查詢語句如下:id:{{productVariant.product.id | split: "gid://shopify/Product/" | last}}
  • 新增一個**「執行程式碼」**步驟,從「getProductData」的結果中擷取父級套件的產品 ID。該程式碼會從「productParents」中擷取父級產品 ID,並建立一個用於查詢的「idsCondition」字串。

執行程式碼」步驟使用以下 GraphQL 輸入、JavaScript 程式碼及輸出結果來取得父產品 ID:

執行「執行程式碼」步驟,顯示 GraphQL 輸入、JavaScript 程式碼及預覽輸出

在「觸發器」頁面中搜尋「價格」,並開啟「產品變體價格變更」選項
在應用程式中:前往「觸發器」,搜尋「價格」,並開啟「產品變體價格變更」。
Flow 用於「產品變體價格變更」的變數選擇器,包含 oldPrice、newPrice、delta、percentChange 及 direction 等參數
「哪個產品變體的價格有所變動」會顯示以下工作流程:價格變動前與變動後的數值、價差、百分比以及變動方向。
bash
{
  getProductData {
    productParents {
      id
    }
  }
}
javascript
export default function main(input) {
  const productIds = input.getProductData[0]?.productParents?.map(p => p.id) ?? [];
  const productId = productIds[0] ?? null;

  const idsCondition = productIds
    .map(gid => "id:" + gid.split("gid://shopify/Product/").pop())
    .join(" OR ");

  return {
    productId: productId,
    productIds: productIds,
    idsCondition: idsCondition,
  };
}
typescript
type Output {
  productId: String
  productIds: [String!]!
  idsCondition: String!
}
  • 新增一個**「條件」**步驟,用以檢查「執行程式碼」的輸出「productId」是否不為空且確實存在。這可確保我們僅在「已變更的產品」確實屬於某個套裝時,才會繼續執行後續步驟。
  • → 繼續更新套裝價格
  • → 停止(該產品並非捆綁套裝的組成部分)
  • 若條件為 True,請新增另一個「**取得產品資料 (1)」**動作,並透過「執行程式碼」步驟中的「idsCondition」,擷取父套裝產品的變體與定價資料。
  • 新增第二個「**執行程式碼 (1)」**步驟,以根據更新後的元件價格計算新的套裝變體價格。此步驟會輸出一個名為 variantPrices 的陣列,其中包含各套裝變體的新價格。

此「執行程式碼 (1)」步驟會根據更新的元件價格,重新計算套裝變體的價格。其運作方式如下:首先,它會從觸發器中擷取兩項關鍵資訊:

  • changedVariantId 剛才修改過的變體(...158920
  • newPrice 該變體的新價格(11.00)**。接著,程式會遍歷每個組合變體,並重新計算其總價。**每個組合變體包含 3 種組成變體(黑色 T 恤、灰色 T 恤、白色 T 恤)。 對於每個組成商品,系統會檢查:這是否就是剛才變更的變體?如果是,則使用 newPrice (11.00) 取代仍儲存在 Shopify (10.00) 中的過時價格;如果不是,則使用現有的 component.productVariant.price.It,並將各組成商品價格相加以得出新的組合變體價格。您可以在輸出資料中看到其運作情況。 請查看變體 ...088840,其組件包含 ...158920(已變更的變體)。因此其價格為 11 + 10 + 10 = 31,而所有其他套裝變體的總價仍為 30,因為它們的組件均未變更。這是此步驟的關鍵要點:Shopify 尚未更新組合資料中的組件價格,因此程式碼不能僅是將現有價格相加,而必須即時將已變更變體的價格替換為新價格。 若未進行此處理,所有變體仍會顯示 30。輸出陣列 variantPrices 隨後傳入 **For each** 迴圈,該迴圈會呼叫 productVariantsBulkUpdate 來將這些重新計算的價格實際寫回組合商品中。
bash
{
  productVariant {
    id
  }
  priceChange {
    oldPrice { amount }
    newPrice { amount }
  }
  getProductData1 {
    id
    variants {
      id
      productVariantComponents {
        productVariant {
          id
          price
        }
      }
    }
  }
}
javascript
export default function main(input) {
  const changedVariantId = input.productVariant.id;
  const newPrice = parseFloat(input.priceChange.newPrice.amount);

  const variantPrices = input.getProductData1.flatMap(product =>
    product.variants.map(variant => ({
      productId: product.id,
      id: variant.id,
      price: variant.productVariantComponents.reduce((sum, component) => {
        const p = component.productVariant.id === changedVariantId
          ? newPrice
          : parseFloat(component.productVariant.price);
        return sum + p;
      }, 0)
    }))
  );

  return { variantPrices };
}
yaml
type VariantPrice {
  productId: String!
  id: String!
  price: Float!
}
type Output {
  variantPrices: [VariantPrice!]!
}
  • 新增一個 For each 迴圈(迭代),用以遍歷 runCode1.variantPrices 中的每個項目。針對每個變體價格,系統會透過 **productVariantsBulkUpdate** 變異操作來執行「傳送管理員 API 請求」動作,以更新套裝商品變體的價格。 您可以將此輸入用於「突變」功能:
json
{
  "variants": [
    {
      "id": "{{variantPricesForeachitem.id}}",
      "price": "{{variantPricesForeachitem.price}}"
    }
  ],
  "productId": "{{variantPricesForeachitem.productId}}",
  "allowPartialUpdates": true
}

整體運作原理為何

當某項組件產品的變體價格發生變更時(例如,您將「灰色 T 恤 S 號」變體的價格從 10.00 歐元更新為 15.00 歐元):

  1. 產品變體價格變更」觸發器被觸發
  2. 此流程透過 productParents 取得該產品的父級套件
  3. 「執行程式碼」步驟會擷取套裝商品 ID
  4. 此條件用來檢查該產品是否屬於某個套裝組合
  5. 如果是,則會擷取該組合商品的資料
  6. 第二次「執行程式碼」步驟會重新計算捆綁方案的價格
  7. 此迴圈會遍歷每個變體,並透過 productVariantsBulkUpdate 管理員 API 變異操作來更新套裝價格

「套裝 S」變體的價格現將從 30.00 歐元更新為 35.00 歐元(15.00 歐元 + 10.00 歐元 + 10.00 歐元)。