# Paketi bileşenlerine ayırma

> Standart bileşen metafield’larını kullanarak sepetteki bir paket ürünü bileşen varyantlarına ayıran Shopify cart transform Function’ı.

Sayfa: https://lintelagency.com/tr/kaynaklar/shopify-functions/paketi-bilesenlerine-ayirma

## Kısaca

Bu cart transform Function’ı, sepette ve checkout’ta bir paket varyantını bileşen ürünlerine ayırır; böylece stok ve gönderim gerçek ürünler üzerinden yürür. Bileşenler custom.component_reference ve custom.component_quantities varyant metafield’larından gelir. Cart Transform API’nin cart.transform.run hedefindeki lineExpand işlemini kullanır (2026-10); herkese açık uygulamada her planda çalışır.

## Bilgiler

- **Function API:** Cart Transform
- **Hedef (target):** cart.transform.run
- **İşlem (operation):** lineExpand
- **Plan:** Herkese açık uygulamada her plan; özel uygulamada Shopify Plus
- **Uygulama yetkisi:** write_cart_transforms
- **API sürümü:** 2026-10
- **Son kontrol:** 2 Kasım 2026

## Nasıl kullanılır

1. custom.component_reference (ürün varyantı listesi) ve custom.component_quantities (tam sayı listesi) varyant metafield tanımlarını oluşturun.
2. Her paket varyantında bileşen varyantlarını ve adetlerini aynı sırayla girin.
3. Shopify CLI ile bir uygulama oluşturun, uzantıyı ekleyin (shopify app generate extension --template cart_transform) ve dosyalarını aşağıdakilerle değiştirin.
4. Testleri shopify app function run ile çalıştırın, deploy edin ve Function’ı cartTransformCreate ile etkinleştirin.

## Kod

### shopify.extension.toml

```toml
api_version = "2026-10"

[[extensions]]
name = "Expand a bundle into its components"
handle = "expand-bundle-components"
type = "function"

  [[extensions.targeting]]
  target = "cart.transform.run"
  input_query = "src/cart_transform_run.graphql"
  export = "cart-transform-run"

  [extensions.build]
  command = ""
  path = "dist/function.wasm"
```

### src/cart_transform_run.graphql

```graphql
query CartTransformRunInput {
  cart {
    lines {
      id
      merchandise {
        __typename
        ... on ProductVariant {
          componentReference: metafield(namespace: "custom", key: "component_reference") {
            jsonValue
          }
          componentQuantities: metafield(namespace: "custom", key: "component_quantities") {
            jsonValue
          }
        }
      }
    }
  }
}
```

### src/cart_transform_run.js

```js
// @ts-check

/**
 * @typedef {import("../generated/api").CartTransformRunInput} CartTransformRunInput
 * @typedef {import("../generated/api").CartTransformRunResult} CartTransformRunResult
 */

/**
 * The bundle variant lists its components in two variant metafields, the
 * definitions Shopify's bundle guide uses: custom.component_reference (list of
 * variants) and custom.component_quantities (list of integers, same order).
 * Quantities are for one bundle.
 */

/**
 * @param {CartTransformRunInput["cart"]["lines"][number]} line
 * @returns {CartTransformRunResult["operations"][number] | null}
 */
function expandOperation(line) {
  if (line.merchandise.__typename !== "ProductVariant") return null;
  const variantIds = line.merchandise.componentReference?.jsonValue;
  const quantities = line.merchandise.componentQuantities?.jsonValue;
  if (!Array.isArray(variantIds) || variantIds.length === 0) return null;
  // Mismatched lists mean a half-edited bundle; leave the line as it is
  // rather than expand it into the wrong items.
  if (!Array.isArray(quantities) || quantities.length !== variantIds.length) return null;

  // No price on the items: Shopify splits the bundle price across the
  // components by their own prices (its weight price algorithm).
  return {
    lineExpand: {
      cartLineId: line.id,
      expandedCartItems: variantIds.map((merchandiseId, index) => ({ merchandiseId, quantity: quantities[index] })),
    },
  };
}

/**
 * @param {CartTransformRunInput} input
 * @returns {CartTransformRunResult}
 */
export function cartTransformRun(input) {
  const operations = input.cart.lines.map(expandOperation).filter((operation) => operation !== null);
  return { operations };
}
```

## Test girdisi ve beklenen çıktı

### tests/bundle-line.input.json

```json
{
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/1",
        "merchandise": {
          "__typename": "ProductVariant",
          "componentReference": {
            "jsonValue": ["gid://shopify/ProductVariant/1111111111", "gid://shopify/ProductVariant/2222222222"]
          },
          "componentQuantities": { "jsonValue": [2, 1] }
        }
      },
      {
        "id": "gid://shopify/CartLine/2",
        "merchandise": { "__typename": "ProductVariant", "componentReference": null, "componentQuantities": null }
      }
    ]
  }
}
```

### tests/bundle-line.output.json

```json
{
  "operations": [
    {
      "lineExpand": {
        "cartLineId": "gid://shopify/CartLine/1",
        "expandedCartItems": [
          { "merchandiseId": "gid://shopify/ProductVariant/1111111111", "quantity": 2 },
          { "merchandiseId": "gid://shopify/ProductVariant/2222222222", "quantity": 1 }
        ]
      }
    }
  ]
}
```

### tests/mismatched-lists.input.json

```json
{
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/1",
        "merchandise": {
          "__typename": "ProductVariant",
          "componentReference": {
            "jsonValue": ["gid://shopify/ProductVariant/1111111111", "gid://shopify/ProductVariant/2222222222"]
          },
          "componentQuantities": { "jsonValue": [2] }
        }
      }
    ]
  }
}
```

### tests/mismatched-lists.output.json

```json
{ "operations": [] }
```

### tests/no-bundles.input.json

```json
{
  "cart": {
    "lines": [
      { "id": "gid://shopify/CartLine/1", "merchandise": { "__typename": "ProductVariant", "componentReference": null, "componentQuantities": null } }
    ]
  }
}
```

### tests/no-bundles.output.json

```json
{ "operations": [] }
```

## Sınırlar ve özel durumlar

- Bileşen fiyatı gönderilmediği için Shopify paket fiyatını bileşenlere kendi fiyatları oranında dağıtır.
- Satırda bir satış planı (abonelik, ön sipariş) varsa Shopify cart transform işlemlerini reddeder.
- Ayrılan bir satır en fazla 150 bileşene sahip olabilir.
- Mağaza başına uygulama başına bir cart transform Function’ı olur; iki işlem aynı satırı hedeflerse lineExpand kazanır.

## Sorular

### Ürün paketleri Shopify Functions ile nasıl çalışır?

Bir cart transform Function’ı sepet satırlarının nasıl sunulacağını değiştirir: lineExpand bir paket satırını bileşenlere ayırır, linesMerge bileşenleri tek bir paket satırında birleştirir. Siparişler, paket ana ürününe referansla bileşen satırlarını tutar.

### Paketler için Shopify Plus gerekir mi?

Herkese açık bir uygulamada lineExpand ve linesMerge için gerekmez. Yalnızca lineUpdate (bir satırın fiyatını, adını ya da görselini değiştirme) Shopify Plus ya da geliştirme mağazası ister.

### Cart transform neden etkinleşmiyor?

cartTransformCreate, write_cart_transforms yetkisi ister ve mağazanın Checkout Extensibility’ye geçmiş olması gerekir.

## Shopify belgeleri

- [Cart Transform Function API](https://shopify.dev/docs/api/functions/latest/cart-transform)
- [Create a bundle app](https://shopify.dev/docs/apps/build/product-merchandising/bundles/create-bundle-app)

## İlgili içerikler

- [Shopify’da Cart Transform ile ürün paketleri: Plus ne zaman gerekir?](https://lintelagency.com/tr/blog/shopify-paketleri-ve-cart-transform)
- [Sepet satırlarını pakette birleştirme](https://lintelagency.com/tr/kaynaklar/shopify-functions/sepet-satirlarini-pakette-birlestirme)
- [Shopify’da ürün yapılandırıcılar: uygulama, tema ya da özel çözüm](https://lintelagency.com/tr/blog/shopify-urun-yapilandirici)

Lisans: MIT. Kendi mağazanızda da müşteri işlerinizde de ücretsiz kullanabilirsiniz.
