# Konfigüratör nasıl çalışır

Yapılandırılabilir ürünler, bir satıcının sabit fiyat yerine boyutlara ve seçeneklere göre fiyatlanan ürünler satmasını sağlar: genişlik ve derinliğe göre fiyatlanan verandalar, ölçüye göre kesilen paneller, malzeme ve aksesuar seçenekleriyle sipariş üzerine üretilen mobilyalar. Storefront akışı şöyledir:

1. Ürünü `GET /v1/api/commerce/products/{id}` ile alın. Yapılandırılabilir bir ürün `"capability": "made_to_measure"` taşır. Konfigüratörü yalnızca `capability_active` `true` olduğu sürece sunun.
2. Yapılandırma şemasını `GET /v1/api/commerce/configurator/products/{id}/schema` ile alın ve bu şemadan bir konfigüratör arayüzü oluşturun.
3. Alıcının seçimindeki her değişiklikte, güncel seçimi `POST /v1/api/commerce/configurator/products/{id}/quote` endpoint'ine gönderin ve satır bazında dökümüyle birlikte canlı fiyatı alın.

Her iki konfigüratör endpoint'i de katalog endpoint'leriyle aynı kimlik doğrulamayı kullanır: `Authorization: Bearer {api_key}` olarak gönderilen bir tenant API anahtarı. `catalog:read` veya `commerce:read` scope'larından birini taşıyan bir anahtar kabul edilir. Kapı configurator modülüdür: mağazada etkin değilse her iki endpoint de `403 {"error":"Module not enabled: configurator"}` döndürür ve made-to-measure ürünler `capability_active: false` bildirir. Quote endpoint'i saf bir hesaplamadır; sepet veya sipariş oluşturmaz ve bu nedenle yazma scope'u gerektirmez.

## Yapı taşları

Yapılandırılabilir bir ürün dört tür varlıkla tanımlanır. Tüm ID'ler UUID'dir.

### Boyutlar

Boyut, alıcının girmesi gereken sayısal bir değerdir; örneğin genişlik ve derinlik. Her boyutun bir `key` (quote çağrılarında kullanılan request anahtarı), bir görüntüleme `label` değeri, bir görüntüleme `unit` metni (örneğin `"cm"`) ve tamsayı `min` ile `max` değerleri vardır. Boyut değerleri tam sayıdır. Boyutlar pozisyona göre sıralanır; bu sıra, boyut değerlerinin fiyat matrisi eksenlerine nasıl eşleneceğini belirler (ilk boyut `dim1`, ikinci boyut `dim2` olur).

Bir boyut kısıtlar (constraints) taşıyabilir: izin verilen aralığın seçim bazında daraltılmasıdır. Alıcı, bir boyut üzerinde kısıtı olan bir seçimi yaptığında, boyutun geçerli `min` değeri kısıtın `min` değerine yükseltilir (daha yüksekse) ve geçerli `max` değeri kısıtın `max` değerine düşürülür (daha düşükse). Kısıtlar aralığı yalnızca daraltır, asla genişletmez.

### Seçenek grupları ve seçimler

Seçenekler gruplar halinde düzenlenir. Bir grubun `type` değeri `single` (alıcı gruptan en fazla bir seçim yapabilir) veya `multi` (istenildiği kadar) olabilir; ayrıca bir `required` bayrağı vardır (gruptan en az bir seçim yapılması zorunludur). Gruplar ve seçimler pozisyona göre sıralanır.

Her seçim, bir delta aracılığıyla fiyatı etkileyebilir:

| delta_type | delta_value'nun anlamı |
| --- | --- |
| `fixed` | Küçük birim (kuruş/cent) cinsinden tutar, bir kez eklenir. |
| `per_area` | Metrekare başına küçük birim cinsinden oran. Delta, `delta_value` çarpı alandır; alan `dim1 * dim2 / 10000` metrekaredir (boyutlar cm cinsinden girilir). Ürünün tam olarak iki boyutu olmasını gerektirir; aksi halde quote 422 ile başarısız olur. |
| `percent` | Taban fiyatın yüzdesi, 100 ile çarpılmış olarak saklanır: `1050` değerindeki bir `delta_value`, yüzde 10,50 anlamına gelir. Delta `base * delta_value / 10000` olarak hesaplanır. |
| `percent_of_total` | Aynı kodlama, ancak diğer tüm deltalardan sonraki ara toplama uygulanır (aşağıdaki fiyatlandırma adımlarına bakın). |

Seçimler ayrıca `is_default` (ilk seçim için bir arayüz ipucu), bir `images` dizisi ve bir `requires_quote` bayrağı taşır. `requires_quote` değeri `true` olduğunda storefront, alıcıyı ödeme (checkout) yerine manuel teklif talebine yönlendirmelidir; quote endpoint'i yapılandırmayı yine de fiyatlar, bayrak bilgilendirme amaçlıdır.

### Seçim kuralları

Kurallar, gruplar arasındaki seçimleri ilişkilendirir:

- `requires`: seçim, yalnızca gerekli hedeflerinden en az biri seçili olduğunda geçerlidir. Hedefler, hedefin seçenek grubuna göre gruplanır: tek bir hedef grubu içinde ilişki OR'dur (herhangi bir hedef yeterlidir), hedef grupları arasında ise AND'dir (her grubun gereksinimi karşılanmalıdır).
- `excludes`: seçim, hedef seçimle birleştirilemez.

Şema, arayüzün geçersiz kombinasyonları baştan devre dışı bırakabilmesi için her seçimin `requires` ve `excludes` dizilerini seçim ID listeleri olarak sunar. Quote endpoint'i aynı kuralları sunucu tarafında da uygular ve ihlal durumunda okunabilir bir mesajla 422 döndürür. Şema ile quote, hangi seçimlerin var olduğu konusunda asla ayrışmaz: `requires` koşulu yayınlanan diğer seçimlerle karşılanamayan bir seçim hiç yayınlanmaz, dolayısıyla şema quote endpoint'inin reddedeceği bir seçimi asla sunmaz. Aşağıdaki görünürlük garantilerine bakın.

### Fiyat matrisleri

Bir ürünün boyutları olduğunda taban fiyatı bir fiyat matrisinden gelir: boyut aralıklarını fiyatlara eşleyen, adlandırılmış 2 boyutlu bir arama tablosu. Her matrisin bir `conditions` kümesi vardır: matrisin uygun sayılması için tümünün seçili olması gereken seçim ID'leri. Koşulu olmayan bir matris her zaman uygundur.

Matris seçimi: uygun tüm matrisler arasında (koşul kümesinin tamamı alıcının seçiminde bulunanlar), en fazla koşula sahip olan kazanır. Beraberlik, oluşturulma sırasına göre çözülür (en eski kazanır). Kazanan matrisin içinde, `dim1` ve `dim2` aralıkları alıcının boyut değerlerini kapsayan satır taban fiyatı sağlar. Boyut değerleri, boyut pozisyon sırasına göre `dim1` ve `dim2` eksenlerine eşlenir.

Hiçbir matris uygun değilse veya kazanan matriste boyut değerlerini kapsayan bir satır yoksa, quote 422 `not_priceable` hatasıyla başarısız olur. Boyutu olmayan bir ürün matrisleri tamamen atlar ve taban olarak kendi `price_amount` değerini kullanır; bu değer `null` ise quote yine `not_priceable` olur.

## Fiyatlandırma adımları

Geçerli bir seçim verildiğinde toplam, tümü tamsayı küçük birimler üzerinde, her yüzde veya alan adımında `PHP_ROUND_HALF_UP` ile tam küçük birime yuvarlanarak iki geçişte hesaplanır:

1. Taban fiyat çözülür (matris satırı veya ürün fiyatı). Döküm, `Base` etiketli bir satırla başlar.
2. Geçiş 1, grup ve seçim pozisyon sırasına göre: `percent_of_total` olmayan her seçili seçim deltasını ekler (`fixed`, `per_area` veya tabanın `percent` değeri). Her seçim, `{Group name}: {Choice name}` etiketli bir döküm satırı ekler; delta değeri sıfır olan seçimler de 0 tutarıyla görünür.
3. Geçiş 2: her seçili `percent_of_total` seçimi, aynı ara toplama karşı bağımsız olarak hesaplanan `pass-1 subtotal * delta_value / 10000` değerini ekler; böylece birden fazla `percent_of_total` seçimi birbirini bileşik olarak etkilemez. Her biri kendi döküm satırını ekler.

Response'taki `total`, taban artı tüm deltalara eşittir. Para birimi ürünün para birimidir.

## Para ve birim özeti

- Tüm tutarlar, ürünün ISO para birimi koduyla birlikte küçük birim (kuruş/cent) cinsinden tamsayıdır.
- Yüzde değerleri 100 ile çarpılmış olarak saklanır: kesri elde etmek için `delta_value` değerini 10000'e bölün.
- `per_area` oranları metrekare başına küçük birimdir; boyutlar santimetre cinsinden girilir ve alan `dim1 * dim2 / 10000` metrekaredir.
- Quote request'lerindeki ve sepet satırlarındaki boyut değerleri, boyutun biriminde tam sayı olmalıdır. `120` ve `120.0` kabul edilir; `120.5` reddedilir.

## Görünürlük garantileri

Şema yalnızca kullanılabilir seçimleri sunar. Yumuşak silinmiş (soft-deleted) ve devre dışı bırakılmış seçimler filtrelenir; geriye kalan seçimlerle `requires` kuralı artık karşılanamayan her seçim de filtrelenir. Bu filtreleme yayılır: bir seçimin sunulmaması, başka bir seçimin gereksinimini karşılanamaz hale getirebilir ve şema döndürülmeden önce durulur. Boyut kısıtları ile `requires` ve `excludes` listeleri, o an kullanılabilir olan seçim ID'lerine göre budanır; kullanılabilir olmayan bir seçime koşullanmış fiyat matrisi ise kısaltılmış bir koşul listesiyle yayımlanmak yerine `price_matrices` içinden bütünüyle çıkarılır, çünkü böyle bir matris hiçbir zaman uygun hâle gelemez. Böylece şemada herhangi bir yerde görünen her seçim ID'si aynı şema içinde çözülebilir ve şemanın sunduğu her seçim seçilebilir ve fiyatlandırılabilir.
