# Ön siparişleri ayrı gönderide tutma

> Etiketli ön sipariş ürünlerini ayrı bir ön sipariş lokasyonundan, stoktaki ürünleri diğer lokasyonlardan gönderen Shopify gönderim kısıtı Function’ı.

Sayfa: https://lintelagency.com/tr/kaynaklar/shopify-functions/on-siparisleri-ayri-gonderide-tutma

## Kısaca

Bu gönderim kısıtı (fulfillment constraints) Function’ı, ön sipariş ürünlerini stoktaki ürünlerden ayırır: ön sipariş etiketli ürünler ayrı bir lokasyondan, diğer her şey öteki lokasyonlarınızdan gönderilir; böylece aynı pakette beklemezler. Fulfillment Constraints API’nin cart.fulfillment-constraints.generate.run hedefini kullanır (sürüm 2026-10) ve herkese açık uygulamada her planda çalışır.

## Bilgiler

- **Function API:** Fulfillment Constraints
- **Hedef (target):** cart.fulfillment-constraints.generate.run
- **Plan:** Herkese açık uygulamada her plan; özel uygulamada Shopify Plus
- **Uygulama yetkisi:** write_fulfillment_constraint_rules
- **API sürümü:** 2026-10
- **Son kontrol:** 2 Kasım 2026

## Nasıl kullanılır

1. Ön sipariş stoku için bir lokasyon oluşturun ve ön sipariş ürünlerini etiketleyin, örneğin pre-order.
2. Shopify CLI 4.9.0 ya da üstüyle bir uygulama oluşturun, uzantıyı ekleyin (shopify app generate extension --template fulfillment_constraints) ve dosyalarını aşağıdakilerle değiştirin.
3. Testleri shopify app function run --input tests/mixed-cart.input.json ile çalıştırın, ardından deploy edin.
4. fulfillmentConstraintRuleCreate ile deliveryMethodTypes: [SHIPPING] vererek etkinleştirin ve metafields içinde {"preorderTags": ["pre-order"], "preorderLocationId": "gid://shopify/Location/1234567890"} gönderin.

## Kod

### shopify.extension.toml

```toml
api_version = "2026-10"

[[extensions]]
name = "Keep pre-orders in a separate shipment"
handle = "pre-orders-separate-shipment"
type = "function"

  [[extensions.targeting]]
  target = "cart.fulfillment-constraints.generate.run"
  input_query = "src/cart_fulfillment_constraints_generate_run.graphql"
  input_variables = { namespace = "$app", key = "function-configuration" }
  export = "cart-fulfillment-constraints-generate-run"

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

### src/cart_fulfillment_constraints_generate_run.graphql

```graphql
query CartFulfillmentConstraintsGenerateRunInput($preorderTags: [String!]) {
  cart {
    deliverableLines {
      id
      merchandise {
        __typename
        ... on ProductVariant {
          product {
            hasAnyTag(tags: $preorderTags)
          }
        }
      }
    }
  }
  locations {
    id
  }
  fulfillmentConstraintRule {
    metafield(namespace: "$app", key: "function-configuration") {
      jsonValue
    }
  }
}
```

### src/cart_fulfillment_constraints_generate_run.js

```js
// @ts-check

/**
 * @typedef {import("../generated/api").CartFulfillmentConstraintsGenerateRunInput} CartFulfillmentConstraintsGenerateRunInput
 * @typedef {import("../generated/api").CartFulfillmentConstraintsGenerateRunResult} CartFulfillmentConstraintsGenerateRunResult
 */

/**
 * Settings stored as JSON in the rule's metafield. `preorderTags` in the same
 * JSON feeds the query variable (see input_variables in the toml), e.g.
 * { "preorderTags": ["pre-order"], "preorderLocationId": "gid://shopify/Location/1234567890" }.
 */
const DEFAULT_CONFIG = {
  // The location that holds (or will receive) pre-order stock.
  preorderLocationId: /** @type {string | null} */ (null),
};

/** @type {CartFulfillmentConstraintsGenerateRunResult} */
const NO_CONSTRAINTS = { operations: [] };

/**
 * @param {CartFulfillmentConstraintsGenerateRunInput} input
 * @returns {CartFulfillmentConstraintsGenerateRunResult}
 */
export function cartFulfillmentConstraintsGenerateRun(input) {
  const config = { ...DEFAULT_CONFIG, ...input.fulfillmentConstraintRule?.metafield?.jsonValue };
  const preorderLocationId = config.preorderLocationId;
  if (!preorderLocationId) return NO_CONSTRAINTS;

  const isPreorder = (/** @type {(typeof input.cart.deliverableLines)[number]} */ line) =>
    line.merchandise.__typename === "ProductVariant" && line.merchandise.product.hasAnyTag;
  const preorderLineIds = input.cart.deliverableLines.filter(isPreorder).map((line) => line.id);
  const inStockLineIds = input.cart.deliverableLines.filter((line) => !isPreorder(line)).map((line) => line.id);
  if (preorderLineIds.length === 0) return NO_CONSTRAINTS;

  const operations = [
    { deliverableLinesMustFulfillFromAdd: { deliverableLineIds: preorderLineIds, locationIds: [preorderLocationId] } },
  ];

  // Keeping the in-stock items away from the pre-order location is what
  // splits the order: they can no longer wait in the same package.
  const otherLocationIds = input.locations.map((location) => location.id).filter((id) => id !== preorderLocationId);
  if (inStockLineIds.length > 0 && otherLocationIds.length > 0) {
    operations.push({
      deliverableLinesMustFulfillFromAdd: { deliverableLineIds: inStockLineIds, locationIds: otherLocationIds },
    });
  }

  return { operations };
}
```

## Test girdisi ve beklenen çıktı

### tests/mixed-cart.input.json

```json
{
  "cart": {
    "deliverableLines": [
      { "id": "gid://shopify/DeliverableCartLine/1", "merchandise": { "__typename": "ProductVariant", "product": { "hasAnyTag": false } } },
      { "id": "gid://shopify/DeliverableCartLine/2", "merchandise": { "__typename": "ProductVariant", "product": { "hasAnyTag": true } } }
    ]
  },
  "locations": [
    { "id": "gid://shopify/Location/1111111111" },
    { "id": "gid://shopify/Location/2222222222" },
    { "id": "gid://shopify/Location/3333333333" }
  ],
  "fulfillmentConstraintRule": {
    "metafield": {
      "jsonValue": { "preorderTags": ["pre-order"], "preorderLocationId": "gid://shopify/Location/3333333333" }
    }
  }
}
```

### tests/mixed-cart.output.json

```json
{
  "operations": [
    {
      "deliverableLinesMustFulfillFromAdd": {
        "deliverableLineIds": ["gid://shopify/DeliverableCartLine/2"],
        "locationIds": ["gid://shopify/Location/3333333333"]
      }
    },
    {
      "deliverableLinesMustFulfillFromAdd": {
        "deliverableLineIds": ["gid://shopify/DeliverableCartLine/1"],
        "locationIds": ["gid://shopify/Location/1111111111", "gid://shopify/Location/2222222222"]
      }
    }
  ]
}
```

### tests/no-location-configured.input.json

```json
{
  "cart": {
    "deliverableLines": [
      { "id": "gid://shopify/DeliverableCartLine/1", "merchandise": { "__typename": "ProductVariant", "product": { "hasAnyTag": true } } }
    ]
  },
  "locations": [{ "id": "gid://shopify/Location/1111111111" }],
  "fulfillmentConstraintRule": { "metafield": null }
}
```

### tests/no-location-configured.output.json

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

### tests/only-in-stock-items.input.json

```json
{
  "cart": {
    "deliverableLines": [
      { "id": "gid://shopify/DeliverableCartLine/1", "merchandise": { "__typename": "ProductVariant", "product": { "hasAnyTag": false } } }
    ]
  },
  "locations": [
    { "id": "gid://shopify/Location/1111111111" },
    { "id": "gid://shopify/Location/2222222222" },
    { "id": "gid://shopify/Location/3333333333" }
  ],
  "fulfillmentConstraintRule": {
    "metafield": {
      "jsonValue": { "preorderTags": ["pre-order"], "preorderLocationId": "gid://shopify/Location/3333333333" }
    }
  }
}
```

### tests/only-in-stock-items.output.json

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

## Sınırlar ve özel durumlar

- Kısıtlı bir ürün izin verilen lokasyonlarda stokta değilse checkout kargo seçeneği göstermez ve tamamlanamaz. Ön sipariş stokunu ön sipariş lokasyonunda tutun.
- Birbirini dışlayan kısıtlar da tüm kargo seçeneklerini kaldırır; her ürün tipini içeren sepetlerle test edin.
- Kural, Function’ın adı ve açıklamasıyla Ayarlar › Kargo ve teslimat › Sipariş yönlendirme (Order routing) altında görünür.
- Bir mağazada en fazla 25 gönderim kısıtı Function’ı etkin olabilir.

## Sorular

### Shopify’da ön siparişleri stoktaki ürünlerden ayrı nasıl gönderirim?

Ön sipariş stokunu ayrı bir lokasyonda tutun ve bu örnekteki gibi ön sipariş satırlarını o lokasyona, diğer satırları geri kalan lokasyonlara bağlayan bir gönderim kısıtı Function’ı kullanın.

### Mağazadan teslim siparişlerine de uygulanır mı?

Yalnızca fulfillmentConstraintRuleCreate’e verdiğiniz teslimat yöntemi tiplerine uygulanır. Bu örnek SHIPPING kullanır; mağazadan teslim siparişleri kısıtlanmaz.

### Ön siparişleri etiket olmadan tespit edebilir miyim?

Teslim edilebilir satırlar (deliverable lines) satış planını göstermediği için bu örnek ürün etiketi kullanır. İsterseniz bir varyant metafield’ı da işinizi görür.

## Shopify belgeleri

- [Fulfillment Constraints Function API](https://shopify.dev/docs/api/functions/latest/fulfillment-constraints)
- [Variables in input queries](https://shopify.dev/docs/apps/build/functions/input-queries/use-variables-input-queries)

## İlgili içerikler

- [Shopify stoğunu başka bir sistemle senkron tutmak](https://lintelagency.com/tr/blog/shopify-stok-senkronizasyonu)
- [Hangi Shopify Functions özellikleri Shopify Plus gerektirir?](https://lintelagency.com/tr/blog/hangi-shopify-functions-ozellikleri-plus-gerektirir)
- [Function’ları metafield (meta alan) ile yapılandırmak: kuralı yeni sürüm yayınlamadan değiştirin](https://lintelagency.com/tr/blog/shopify-functions-metafield-ile-yapilandirma)

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