Gelen İş Emirleri¶
Uç nokta¶
text
POST /api/v1/inbound/work-orders
POST /api/v1/inbound/work-orders/test
POST /api/v1/inbound/work-orders ERP iş emri sarmalayıcı payload'larını kabul eder, doğrular ve kabul edilen veriyi MongoDB'ye yazar. Ürün upsert, proje/üretim/aşama birleştirme, makine ve çalışan çözümleme ile proje düzeyinde kısmi işleme uygulanır. Yalnızca doğrulama değildir.
POST /api/v1/inbound/work-orders/test halka açık format doğrulama endpointidir. Yalnızca JSON/XML sözdizimini ve istek sözleşmesini kontrol eder. Bearer Token istemez, Idempotency-Key kullanmaz, MongoDB okuma/yazma yapmaz ve request archive kaydı oluşturmaz.
Canlı endpointin kimlik doğrulama, idempotency, archive ve kalıcılık davranışı değişmemiştir.
Birleştirme ve çözümleme kuralları için bkz. İş Emri Kalıcılığı.
Kimlik doğrulama¶
Canlı endpoint¶
AUTH_ENABLED=true iken canlı istekler JWT Bearer access token içermelidir:
http
Authorization: Bearer <access_token>
Token POST /api/v1/auth/token üzerinden alınır. Bkz. Kimlik Doğrulama.
AUTH_ENABLED=false iken canlı endpoint yerel geliştirme için Bearer token olmadan açık kalır; kalıcılık yine MongoDB’ye yazar.
Eksik token 401 AUTHENTICATION_REQUIRED, geçersiz/süresi dolmuş token 401 INVALID_TOKEN döner. Kimlik doğrulama hataları JSON ve XML Accept pazarlığını destekler.
Test endpoint¶
POST /api/v1/inbound/work-orders/test halka açıktır. AUTH_ENABLED=true olsa bile kimlik doğrulama gerekmez. Token gönderilirse yetkilendirme için yok sayılır.
Canlı endpointte tenant alanları (company_id, organization_id) istek kökünden veya ortam varsayılanlarından alınır; token claim’lerinden türetilmez. Test endpointi ortam tenant fallback’i veya veritabanı tenant kontrolü yapmaz; alanlar gönderilmişse yalnızca sözleşme (ObjectID hex) olarak doğrulanır.
Sözleşme referansları (depo içi):
- OpenAPI:
api/openapi.yaml - XML Schema (XSD):
api/schemas/inbound-work-orders.xsd - GitHub OpenAPI: api/openapi.yaml
- GitHub XSD: api/schemas/inbound-work-orders.xsd
İçerik türleri¶
İstek Content-Type¶
| Değer | Açıklama |
|---|---|
application/json |
JSON payload |
application/xml |
XML payload |
text/xml |
XML payload |
charset=utf-8 gibi parametreler desteklenir.
Desteklenmeyen istek Content-Type değerleri 415 Unsupported Media Type döner.
Yanıt Accept¶
| Değer | Açıklama |
|---|---|
application/json |
JSON yanıt |
application/xml |
XML yanıt |
text/xml |
XML yanıt |
*/* |
İstek formatıyla eşleş |
Accept gönderilmezse yanıt, istek Content-Type ile aynı formatta döner.
Desteklenmeyen Accept değerleri 406 Not Acceptable döner.
Kiracı alanları¶
Kök alanlar company_id ve organization_id istek gövdesinde isteğe bağlı bir çifttir.
| Durum | Sonuç |
|---|---|
| Her iki istek değeri mevcut | İstek çifti kullanılır |
| Hiç istek değeri yok | Her iki ortam değeri yapılandırılmışsa DEFAULT_COMPANY_ID ve DEFAULT_ORGANIZATION_ID kullanılır |
| Tam olarak bir istek değeri | 400 TENANT_CONTEXT_INCOMPLETE (ortam varsayılanları uygulanmaz) |
| Ne istek ne yapılandırılmış varsayılan | 400 TENANT_CONTEXT_REQUIRED |
| Sağlanan değerde geçersiz ObjectID | 400 INVALID_TENANT_CONTEXT |
İstekte her iki alan da mevcut olduğunda, her biri 24 karakter hexadecimal MongoDB ObjectID dizesi olmalıdır (^[A-Fa-f0-9]{24}$).
XML payload'ları aynı kuralları izler. XSD her iki elementi isteğe bağlı (minOccurs="0") işaretler; her ikisi de atlandığında kiracı çözümlemesi ortam varsayılanlarını kullanabilir.
DEFAULT_* başlangıç doğrulaması için bkz. Yapılandırma.
İstek örnekleri¶
JSON¶
json
{
"company_id": "507f1f77bcf86cd799439011",
"organization_id": "507f191e810c19729de860ea",
"projects": [
{
"project_name": "Proje Adı",
"project_code": "PROJE-001",
"start_date": "2026-08-06T08:00:00Z",
"estimated_end_date": "2026-08-30T17:00:00Z",
"description": "Proje açıklaması",
"productions": [
{
"production_name": "Üretim Emri Adı",
"production_code": "URETIM-001",
"planned_start_datetime": "2026-08-06T08:00:00Z",
"planned_finish_datetime": "2026-08-10T17:00:00Z",
"remarks": "Üretim emri açıklaması",
"production_stages": [
{
"production_stage_name": "Kesim",
"production_stage_code": "ASAMA-001",
"stage_number": 1,
"stage_type": "yeni",
"planning_start_time": "2026-08-06T08:00:00Z",
"planning_end_time": "2026-08-07T17:00:00Z",
"machines": [
{
"machine_code": "MACHINE-001",
"machine_name": "CNC Makinesi",
"output_products": [
{
"product_name": "Makine Çıktı Ürünü",
"product_code": "URUN-001",
"category": "Yarı Mamul",
"unit": "adet",
"quantity": 30,
"ideal_cycle_time": 1700
}
]
}
],
"employees": [
{
"username": "operator.user"
}
],
"input_products": [
{
"product_name": "Aşama Girdi Ürünü",
"product_code": "HAM-001",
"category": "Hammadde",
"unit": "adet",
"quantity": 30,
"ideal_cycle_time": 0
}
],
"output_products": [
{
"product_name": "Aşama Çıktı Ürünü",
"product_code": "YARI-001",
"category": "Yarı Mamul",
"unit": "adet",
"quantity": 30,
"ideal_cycle_time": 1700
}
]
}
],
"input_products": [
{
"product_name": "Üretim Girdi Ürünü",
"product_code": "HAM-001",
"category": "Hammadde",
"unit": "adet",
"quantity": 30,
"ideal_cycle_time": 0
}
],
"final_products": [
{
"product_name": "Nihai Ürün",
"product_code": "NIHAI-001",
"category": "Nihai Mamul",
"unit": "adet",
"quantity": 30,
"ideal_cycle_time": 1700
}
]
}
]
}
]
}
XML¶
```xml
Yanıt durumları¶
| HTTP | data.status / hata kodu |
Ne zaman |
|---|---|---|
| 200 | success |
Alınan tüm projeler işlendi |
| 200 | partial_success |
En az bir proje işlendi; bir veya daha fazla proje, üretim veya aşama atlandı |
| 409 | NO_PROJECT_PROCESSED |
İstek yapısal olarak geçerli ancak hiçbir proje yazılamadı |
| 409 | INTEGRATION_ACTOR_USER_NOT_FOUND |
Yapılandırılmış entegrasyon aktörü kullanıcı belgesi yok |
| 409 | INTEGRATION_ACTOR_USER_INACTIVE |
Yapılandırılmış entegrasyon aktörü aktif değil |
| 409 | INTEGRATION_ACTOR_TENANT_MISMATCH |
Aktör, isteğin kiracısına ait değil |
| 503 | DATABASE_UNAVAILABLE |
MongoDB bağlantı, server selection veya zaman aşımı hatası |
JSON başarı / kısmi başarı¶
json
{
"success": true,
"request_id": "uuid",
"data": {
"message": "Work-order payload processed.",
"status": "partial_success",
"summary": {
"received_projects": 3,
"processed_projects": 2,
"skipped_projects": 1,
"created_projects": 1,
"updated_projects": 1,
"received_productions": 4,
"processed_productions": 3,
"skipped_productions": 1,
"received_stages": 6,
"processed_stages": 5,
"skipped_stages": 1,
"product_occurrences": 20,
"created_products": 2,
"updated_products": 4,
"resolved_machines": 3,
"resolved_employees": 2,
"unresolved_employees": 1
},
"results": [
{
"project_code": "PRJ-001",
"status": "processed",
"action": "created",
"warnings": []
},
{
"project_code": "PRJ-002",
"status": "skipped",
"action": "none",
"warnings": [
{
"code": "PROJECT_NAME_CONFLICT",
"project_code": "PRJ-002",
"message": "The project_code exists with a different project_name."
}
]
}
]
},
"error": null
}
Proje sonucu alanları¶
| Alan | Değerler |
|---|---|
status |
processed, processed_with_warnings, skipped |
action |
created, updated, none |
warnings |
Uyarı nesneleri dizisi (code, isteğe bağlı bağlam alanları, message) |
Kalıcılık davranışı (özet)¶
| Alan | Davranış |
|---|---|
| Ürünler | company_id + organization_id + product_code ile upsert |
| Projeler | Kiracı + project_code ile oluştur veya birleştir; ad uyuşmazlığında proje atlanır |
| Üretimler / aşamalar | Üst kayıt içinde kod ile birleştir; gönderilmeyen mevcut çocuklar korunur |
| Makineler | Salt okunur katalog çözümlemesi; eksik makine tüm aşamayı atlar |
| Çalışanlar | Salt okunur kullanıcı çözümlemesi; eksik username yalnızca o atamayı atlar |
| Kısmi işleme | Projeler bağımsızdır; bir atlama diğerlerini durdurmaz |
production_stage_operation, aşama dosyaları ve üretim dosyaları gibi operasyonel alanlar güncellemede korunur.
Collection kiracı tip farklılıkları¶
Mevcut MongoDB şemaları collection'a göre farklıdır ve korunur:
| Collection | company_id / organization_id tipi |
|---|---|
projects, machines |
ObjectID |
products, users |
string |
Integration actor¶
Denetim alanları INTEGRATION_ACTOR_USER_ID kullanır (mevcut aktif kullanıcının 24 karakter ObjectID hex değeri). Rastgele üretilmiş ObjectID olamaz; MongoDB’de gerçek bir kullanıcıyı göstermelidir. Config yükleme yalnızca zorunluluk + biçimi kontrol eder. Canlı POST ayrıca varlık, aktiflik ve kiracı eşleşmesini doğrular. Yanıtta aktör ObjectID yoktur. Bkz. Yapılandırma ve Hata Kodları.
Idempotency ve arşiv¶
Live endpoint, idempotency etkin/zorunlu iken Idempotency-Key ister. Aynı key + aynı canonical payload, ApplyPlan çalıştırmadan saklanan logical response’u replay eder. Aynı key + farklı payload 409 IDEMPOTENCY_KEY_CONFLICT döner.
Archive etkinken her canlı attempt api_request_archive içine yazılır. Test endpointi business: 0, archive: 0 yazar; api_idempotency_records yazmaz.
Bkz.:
Standalone MongoDB¶
Kalıcılık standalone MongoDB ile uyumludur. Çok belgeli transaction zorunlu değildir. Ürün master yazıları proje belgesi yazısından bağımsızdır; ürünler upsert edildikten sonra proje yazısı başarısız olursa ürün kayıtları kalabilir.
Zorunlu alanlar¶
| Seviye | Zorunlu alanlar |
|---|---|
| İstek | company_id, organization_id, projects (en az 1 kayıt) |
| Proje | project_name, project_code, start_date, estimated_end_date, productions |
| Üretim | production_name, production_code, planned_start_datetime, planned_finish_datetime, production_stages, input_products, final_products |
| Üretim aşaması | production_stage_name, production_stage_code, stage_number, stage_type, planning_start_time, planning_end_time, input_products, output_products |
| Ürün | product_name, product_code, category, unit, quantity, ideal_cycle_time |
| Makine (varsa) | machine_code, output_products (en az 1 kayıt) |
| Çalışan (varsa) | username |
Opsiyonel alanlar¶
| Alan | Not |
|---|---|
project.description |
Opsiyonel string |
production.remarks |
Opsiyonel string |
production_stage.description |
Opsiyonel string |
machine.machine_name |
Opsiyonel string (bilgilendirme; kanonik ad MongoDB'den gelir) |
production_stage.machines |
Opsiyonel dizi; gönderilmeyebilir veya boş olabilir |
production_stage.employees |
Opsiyonel dizi; gönderilmeyebilir veya boş olabilir |
Dizi kuralları¶
Zorunlu diziler en az bir kayıt içermelidir:
projects,productions,production_stagesproduction.input_products,production.final_productsproduction_stage.input_products,production_stage.output_products- Makine kaydı varsa
machine.output_products
machines ve employees gönderilmeyebilir veya boş dizi olabilir.
Tek nesneler diziye otomatik çevrilmez; eksik veya boş zorunlu diziler doğrulama hatası üretir.
Aynı istek içinde yapısal kod tekrarları reddedilir (DUPLICATE_PROJECT_CODE, DUPLICATE_PRODUCTION_CODE, DUPLICATE_PRODUCTION_STAGE_CODE, DUPLICATE_MACHINE_CODE, DUPLICATE_EMPLOYEE_USERNAME). Occurrence'lar arasında tekrarlayan product_code izinlidir.
UTC Z tarih kuralı¶
Tüm tarih-saat alanları Z ile biten RFC 3339 UTC değerleri olmalıdır.
Kabul edilen örnekler:
2026-08-06T08:30:00Z2026-08-06T08:30:00.123Z
Reddedilen örnekler:
2026-08-06T11:30:00+03:002026-08-06T08:30:00+00:002026-08-06 08:30:00
Tarih sıralama kontrolleri:
estimated_end_date,start_datedeğerinden önce olamazplanned_finish_datetime,planned_start_datetimedeğerinden önce olamazplanning_end_time,planning_start_timedeğerinden önce olamaz
Eşit başlangıç/bitiş değerleri kabul edilir.
Tamsayı kuralları¶
| Alan | Kural |
|---|---|
stage_number |
Tamsayı, > 0 |
quantity |
Tamsayı, >= 0 |
ideal_cycle_time |
Tamsayı, >= 0 |
JSON float, string, boolean ve null değerleri tamsayı alanları için reddedilir.
stage_type normalizasyonu¶
Normalizasyon sonrası kabul edilen değerler:
yenirevize
YENİ veya Revize gibi büyük/küçük harf varyantları Türkçe kurallarla normalize edilir. Diğer değerler reddedilir.
Katı bilinmeyen alan davranışı¶
- JSON: bilinmeyen alanlar reddedilir (
DisallowUnknownFields). - XML: bilinmeyen elementler alan yolu ile reddedilir.
- XML DOCTYPE/DTD bildirimleri reddedilir.
İş emri test endpointi¶
text
POST /api/v1/inbound/work-orders/test
Canlı endpoint ile aynı JSON/XML istek sözleşmesi için halka açık format doğrulama endpointidir.
| Davranış | Ayrıntı |
|---|---|
| Kimlik doğrulama | Gerekmez (AUTH_ENABLED=true olsa bile public) |
| Idempotency-Key | Gerekmez; gönderilirse yok sayılır |
| MongoDB | Okuma ve yazma yok |
| Request archive | Kayıt oluşturulmaz |
| İş kontrolleri | Makine/çalışan/proje varlık kontrolü yok |
| Formatlar | Aynı Content-Type / Accept / gövde sınırı / bilinmeyen alan kuralları |
| Yanıt | status: valid, write_performed: false, database_accessed: false, archive_written: false |
Format hataları için HTTP durumları: 200 / 400 / 406 / 413 / 415. Bu endpoint UNAUTHORIZED, idempotency/archive store kodları, REQUEST_ARCHIVE_UNAVAILABLE, MACHINE_NOT_FOUND, EMPLOYEE_NOT_FOUND veya PROJECT_CONFLICT dönmez.
200 yanıtı payload formatının ve sözleşmesinin geçerli olduğu anlamına gelir; sonraki canlı yazmanın başarılı olacağını garanti etmez.
Postman / curl JSON örneği¶
http
POST /api/v1/inbound/work-orders/test
Content-Type: application/json
Accept: application/json
Authorization veya Idempotency-Key gerekmez. Canlı istek örneklerindeki aynı JSON gövde şeklini kullanın.
Postman / curl XML örneği¶
http
POST /api/v1/inbound/work-orders/test
Content-Type: application/xml
Accept: application/xml
JSON test başarı örneği¶
json
{
"success": true,
"request_id": "uuid",
"data": {
"message": "Work-order payload format is valid.",
"status": "valid",
"content_type": "application/json",
"write_performed": false,
"database_accessed": false,
"archive_written": false
},
"error": null
}
Gövde sınırı¶
INBOUND_MAX_BODY_BYTES ile yapılandırılır (varsayılan: 10 MiB / 10485760 bayt). Sınır aşımında 413 Payload Too Large döner.
Sözleşme doğrulama hata detayları¶
JSON/XML sözdizimi hataları ile sözleşme hataları ayrı sınıflandırılır. Sözleşme detaylarında dizi indeksleri dahil tam nested path bulunur; ERP yetkilisi hatalı alanı doğrudan bulabilir:
projects[0].productions[0].production_stages[0].machines[0].output_products[0].ideal_cycle_time
Geçersiz integer tipi (malformed JSON değildir)¶
json
{
"success": false,
"request_id": "uuid",
"data": null,
"error": {
"code": "INVALID_FIELD_TYPE",
"message": "Request contains a field with an invalid type.",
"details": [
{
"field": "projects[0].productions[0].production_stages[0].machines[0].output_products[0].ideal_cycle_time",
"code": "INVALID_TYPE",
"message": "Field 'ideal_cycle_time' must be an integer.",
"expected_type": "integer",
"actual_type": "string",
"received_value": "asd"
}
]
}
}
"ideal_cycle_time": "asd" gönderildiğinde yanıt asla MALFORMED_JSON olmamalıdır.
Diğer sözleşme örnekleri¶
| Senaryo | Üst kod | Detail kodu |
|---|---|---|
| Gerçek JSON syntax bozukluğu | MALFORMED_JSON |
JSON_SYNTAX_ERROR (+ line/column/byte_offset) |
| Bilinmeyen nested alan | UNKNOWN_FIELD |
UNKNOWN_FIELD |
| Eksik zorunlu alan | REQUIRED_FIELD_MISSING |
REQUIRED |
Geçersiz stage_type |
VALIDATION_ERROR |
INVALID_ENUM_VALUE |
| Geçersiz RFC3339 tarih | VALIDATION_ERROR |
INVALID_DATETIME |
Negatif quantity |
VALIDATION_ERROR |
VALUE_OUT_OF_RANGE |
Aynı geçerli JSON gövdesindeki birden fazla sözleşme hatası VALIDATION_ERROR altında toplanır (en fazla 100 detail). received_value yalnız güvenli primitive değerler içerir; uzun stringler kesilir.
Hata ve uyarı kodları¶
| Kod | HTTP | Anlam |
|---|---|---|
MALFORMED_JSON |
400 | JSON sözdizimi ayrıştırılamadı |
MALFORMED_XML |
400 | XML sözdizimi ayrıştırılamadı veya DOCTYPE reddedildi |
INVALID_FIELD_TYPE |
400 | Alan tipi uyuşmazlığı (ör. string yerine integer beklenirken) |
REQUIRED_FIELD_MISSING |
400 | Bir veya daha fazla zorunlu alan eksik |
UNKNOWN_FIELD |
400 | Bilinmeyen JSON alanı veya XML elementi |
VALIDATION_ERROR |
400 | Bir veya daha fazla sözleşme doğrulama hatası |
VALIDATION_FAILED |
400 | Bazı doğrulama hataları için legacy alias |
DUPLICATE_* |
400 | Aynı istek içinde yapısal kod tekrarı (bkz. Hata Kodları) |
AUTHENTICATION_REQUIRED / INVALID_TOKEN |
401 | Canlı endpoint auth hataları |
NOT_ACCEPTABLE |
406 | Desteklenmeyen Accept başlığı |
NO_PROJECT_PROCESSED |
409 | Hiçbir proje yazılamadı (canlı) |
INTEGRATION_ACTOR_USER_NOT_FOUND |
409 | Yapılandırılmış aktör kullanıcı belgesi yok (canlı) |
INTEGRATION_ACTOR_USER_INACTIVE |
409 | Yapılandırılmış aktör aktif değil (canlı) |
INTEGRATION_ACTOR_TENANT_MISMATCH |
409 | Aktör istek kiracısına ait değil (canlı) |
PAYLOAD_TOO_LARGE |
413 | Gövde inbound sınırını aştı |
UNSUPPORTED_MEDIA_TYPE |
415 | Desteklenmeyen Content-Type |
INTERNAL_ERROR |
500 | Beklenmeyen sunucu hatası |
DATABASE_UNAVAILABLE |
503 | MongoDB kullanılamıyor (canlı) |
Sonuç/uyarı kodları (canlı results[].warnings veya 409 details): PROJECT_NAME_CONFLICT, MACHINE_NOT_FOUND, EMPLOYEE_NOT_FOUND, ALL_STAGES_SKIPPED, ALL_PRODUCTIONS_SKIPPED.
Tam liste için bkz. Hata Kodları.