1 Genel Mimari
1.1 Adapter Kalıbı (Factory Pattern)
Xpensio, tüm ERP/HR entegrasyonlarını Adapter Factory kalıbıyla yönetir. Ortam değişkenine (SAP_TYPE, IDENTITY_PROVIDER) göre uygun adapter otomatik seçilir:
┌─────────────────────── Xpensio Backend (NestJS) ───────────────────────┐
│ │
│ SapAdapterFactory IdentityAdapterFactory │
│ ├─ ECC → SapEccAdapter ├─ SAP_HCM → SapHcmAdapter │
│ ├─ S4_ONPREM → SapS4OnPremAdapter ├─ SAP_S4_ONPREM → S4OnPrem… │
│ ├─ S4_CLOUD → SapS4CloudAdapter ├─ SAP_S4_CLOUD → S4Cloud… │
│ └─ MOCK → SapMockAdapter ├─ AZURE_AD → AzureAdAdapter │
│ ├─ LDAP → LdapAdapter │
│ └─ MOCK → MockAdapter │
└─────────────────────────────────────────────────────────────────────────┘
1.2 FI Posting (Masraf Muhasebeleştirme) Adapterleri
| SAP_TYPE | Adapter | Bağlantı Yöntemi | Auth |
ECC | SapEccAdapter | SICF REST → BAPI_ACC_DOCUMENT_POST | HTTP Basic |
S4_ONPREM | SapS4OnPremAdapter | OData v4 → API_JOURNALENTRY_POST | Basic / OAuth2 |
S4_CLOUD | SapS4CloudAdapter | REST → Journal Entry API | OAuth2 (XSUAA) |
MOCK | SapMockAdapter | Simülasyon (%5 hata oranı) | — |
1.3 HR / Kimlik Sync Adapterleri
| IDENTITY_PROVIDER | Adapter | Kaynak | Sync Periyodu |
SAP_HCM | SapHcmAdapter | ABAP SICF /sap/bc/xpensio/user_list | Her gece 01:00 |
SAP_S4_ONPREM | SapS4OnPremAdapter | OData API_BUSINESS_PARTNER | Her gece 01:00 |
SAP_S4_CLOUD | SapS4CloudAdapter | SuccessFactors OData v4 | Her gece 01:00 |
AZURE_AD | AzureAdAdapter | Microsoft Graph API | Her gece 01:00 |
LDAP | LdapAdapter | LDAP/AD LDAPS | Her gece 01:00 |
1.4 Platform Karşılaştırma Matrisi
| Özellik | SAP ECC 6.0 | S/4 On-Prem | S/4 Cloud |
| FI Posting | BAPI_ACC_DOCUMENT_POST | BAPI compat / OData | REST Journal Entry |
| HR Sync | ABAP SICF endpoint | OData EmployeeEntity | SuccessFactors OData v4 |
| Auth | HTTP Basic | OAuth2 / Basic | OAuth2 (XSUAA) |
| ABAP Gereksinimi | Evet (7.0+) | Opsiyonel (7.50+) | Hayır |
| Kurulum Zorluğu | Orta | Orta | Düşük |
| ENV: SAP_TYPE | ECC | S4_ONPREM | S4_CLOUD |
2 Ortak Referanslar
2.1 Kullanıcı / HR Alan Eşleşmesi
| Xpensio DB | HR Sistemi Karşılığı | Açıklama |
email | E-posta | Birincil anahtar |
name | Ad + Soyad | Birleştirilmiş |
externalId | PERNR / EmployeeId | Personel No |
sapEmployeeId | PERNR | FI kalemlerinde kullanılır |
departmentCode | DEPARTMENTNO / OrgUnit | → departmentId FK |
positionCode | TITLENO / PositionId | → positionId FK |
grade | GRADE / PayGrade | 7–19 arası, onay limiti belirler |
managerEmail | MANAGEREMAIL | Yönetici → managerId FK |
isActive | '1' / 'X' = aktif | Aktiflik durumu |
2.2 Masraf → FI Mapping
| Xpensio | FI Karşılığı | Örnek |
netAmount | Net Tutar (vergi hariç) | 100.00 TRY |
taxAmount | KDV Tutarı | 20.00 TRY |
grossAmount | Brüt Tutar | 120.00 TRY |
expenseTypeCode | Masraf Türü → GL Hesap | 21 → Ulaşım GL |
taxPercentageCode | Vergi Kodu | V5 → %20 |
costCenter | Masraf Yeri (KOSTL) | 10 hane |
projectCode | WBS Elementi | Opsiyonel |
2.3 Grade → Rol Eşleştirmesi
| Grade | Unvan Tipi | Atanan Rol |
| 17–19 | VP / GM / CTO | MANAGER |
| 14–16 | Division Head | MANAGER |
| 13 | Unit Head | MANAGER |
| 7–12 | Engineer / Analyst | EMPLOYEE |
⚠️ FINANCE ve ADMIN rolleri grade ile asla değiştirilmez. Eşik: MANAGER_GRADE_THRESHOLD = 13
2.4 Çok Seviyeli Onay Zinciri
| Adım | Onaylayan | Koşul |
| 1 | MANAGER | Her zaman zorunlu |
| 2 | UPPER_MANAGER | Tutar > çalışanın grade limiti |
| 3 | CFO / ADMIN | Tutar > 50.000 TRY |
| 4 | FINANCE | Her zaman zorunlu (son adım) |
Grade Limit Örnekleri: G7–12 → 10.000 TRY | G13–15 → 25.000 TRY | G16–18 → 50.000 TRY
2.5 Vergi & Ödeme Kodları
| Vergi Kodu | Oran | Ödeme Tipi | Açıklama |
V0 | %0 | 0 | Nakit |
V1 | %1 | 1 | Kişisel Kart |
V4 | %10 | 2 | Şirket Kartı |
V5 | %20 | 3 | Kurumsal Kart |
3 SAP ECC 6.0 Entegrasyonu
IDENTITY_PROVIDER=SAP_HCM SAP_TYPE=ECC ABAP 7.0+
3.1 Kurulum Sırası
| # | Adım | SAP Tx | Açıklama |
| 1 | DDIC Nesneleri | SE11 | Tablo ve yapıları oluştur + aktive et |
| 2 | ABAP Sınıfları | SE24 | ZCL_EXPENSE_POSTING + ZCL_EXPENSE_USER_LIST |
| 3 | SICF Servisleri | SICF | Handler ata + aktive et |
| 4 | SAP Kullanıcısı | SU01 | API sistem kullanıcısı oluştur |
| 5 | Yetkilendirme | PFCG | Rol + izin nesneleri ata |
| 6 | İlk Veriler | SM30 | ZEXP_AUTH + ZEXP_CFG tabloları doldur |
| 7 | FI Uyarlama | OBA7 / FS00 / KS01 / FTXP | Belge tipi, GL, masraf yeri, vergi kodları |
3.2 DDIC Nesneleri (SE11)
ZEXP_AUTH — Kimlik Doğrulama
| Alan | Tip | Key | Açıklama |
| MANDT | CLNT 3 | ✓ | Mandant |
| TYPE | CHAR 5 | ✓ | 04=HTTP Basic, 05=Form |
| USERNAME | CHAR 100 | | API kullanıcı adı |
| PASSWORD | CHAR 100 | | API şifresi |
ZEXP_POST_LOG — FI Posting Log
| Alan | Tip | Açıklama |
| LOGID | CHAR 36 | UUID (expense ID) |
| BUKRS | BUKRS 4 | Şirket kodu |
| BELNR | BELNR 10 | SAP FI belge no |
| STATUS | CHAR 1 | S=Başarı, E=Hata |
| MESSAGE | CHAR 255 | SAP mesajı |
| RETRY_CNT | INT1 | Deneme sayısı |
ZEXP_CFG — Genel Yapılandırma
| CFGKEY | Örnek Değer | Açıklama |
| EXPENSE_GL | <GIDER_GL> | Gider GL Hesabı |
| COUNTER_GL | <KARSI_GL> | Karşı Hesap |
| KDV_GL | <KDV_GL> | İndirilecek KDV |
| DOC_TYPE | SA | Belge Tipi |
ZEXP_CFG_GL — Masraf Türü → GL Hesap Eşleşme
| Alan | Key | Açıklama |
| BUKRS | ✓ | Şirket kodu |
| SUBCOMPCODE | ✓ | Alt şirket kodu |
| EXPENSETYPECODE | ✓ | Masraf türü (21/22/23…) |
| GLACCOUNT | | GL hesap numarası |
| TAXCODE | | Vergi kodu (V0/V1/V4/V5) |
ZEXP_USERS — Kullanıcı Tablosu
| Alan | Xpensio Karşılığı | Açıklama |
| EMAIL | email (PK) | E-posta adresi |
| NAME / SURNAME | name | Ad + soyad birleştirilir |
| DEPARTMENTNO | departmentCode | Departman kodu |
| TITLENO | positionCode | Pozisyon kodu |
| GRADE | grade | Seviye (7–19), rol ataması |
| MANAGEREMAIL | managerEmail | Yönetici e-posta |
| PERSONNELCODE | externalId, sapEmployeeId | Personel numarası |
| ISACTIVE | isActive | 1=aktif, 0=pasif |
ZEXP_GRADE_POLICIES — Grade / Politika Tablosu
| Alan | Key | Açıklama |
| BUKRS | ✓ | Şirket kodu |
| GRADE | ✓ | Grade seviyesi |
| POLICYCODE | | Masraf politikası kodu |
| LIMIT_AMOUNT | | Harcama limiti (TRY) |
ZEXP_COMPANY — Şirket Yapılandırması
| Alan | Key | Açıklama |
| BUKRS | ✓ | Şirket kodu |
| COMP_NAME | | Şirket adı |
| CURRENCY | | Yerel para birimi |
| TAX_SYSTEM | | Vergi sistemi (TR/EU) |
ZEXP_S_POST_PAYLOAD — POST_EXPENSE Giriş Yapısı
COMPANYCODE (BUKRS), EMPLOYEEID (CHAR 20), EMPLOYEENAME (CHAR 100),
EXPENSEDATE (CHAR 8), POSTINGDATE (CHAR 8), DOCUMENTTYPE (BLART),
NETAMOUNT (DEC 13,2), TAXAMOUNT (DEC 13,2), GROSSAMOUNT (DEC 13,2),
TAXCODE (CHAR 2), TAXGLACCOUNT (SAKNR), CURRENCY (WAERS),
GLACCOUNT (SAKNR), COSTCENTER (KOSTL), PROJECTCODE (PS_POSID),
DESCRIPTION (CHAR 50), REFERENCE (CHAR 16), DEBUGMODE (CHAR 1)
3.3 ABAP — ZCL_EXPENSE_POSTING (FI Belge Oluşturma)
Interface: IF_HTTP_EXTENSION | SICF: /sap/bc/zexpense/post_expense
HANDLE_REQUEST — Ana Giriş Noktası
METHOD if_http_extension~handle_request.
" 1. HTTP metod kontrolü (sadece POST)
" 2. Auth doğrulama: ZEXP_AUTH → username + password
" 3. JSON body → ZEXP_S_POST_PAYLOAD'a parse
" 4. Zorunlu alan kontrolü (companycode, glaccount, netamount…)
" 5. POST_EXPENSE çağır
" 6. JSON response: { STATUS, BELNR, GJAHR, MESSAGE }
" 7. ZEXP_POST_LOG'a loglama
ENDMETHOD.
POST_EXPENSE — BAPI Çağrısı
METHOD post_expense.
" ── HEADER ──
ls_header-comp_code = is_payload-companycode.
ls_header-doc_date = is_payload-expensedate.
ls_header-pstng_date = is_payload-postingdate.
ls_header-doc_type = is_payload-documenttype.
ls_header-ref_doc_no = is_payload-reference.
ls_header-currency = is_payload-currency.
ls_header-bus_act = 'RFBU'.
" ── KALEM 1: Gider GL (Borç) ──
ls_accgl-gl_account = is_payload-glaccount.
ls_accgl-tax_code = is_payload-taxcode.
ls_accgl-costcenter = is_payload-costcenter.
ls_curr-amt_doccur = is_payload-netamount.
" ── KALEM 2: KDV GL (Borç, sadece KDV > 0) ──
IF is_payload-taxamount > 0.
ls_acctax-gl_account = is_payload-taxglaccount.
ls_curr-amt_doccur = is_payload-taxamount.
ENDIF.
" ── KALEM 3: Personel Cari (Alacak) ──
ls_accpay-vendor = is_payload-employeeid.
ls_curr-amt_doccur = - is_payload-grossamount.
" ── BAPI ÇAĞRISI ──
IF is_payload-debugmode = 'X'.
CALL FUNCTION 'BAPI_ACC_DOCUMENT_CHECK' ...
ELSE.
CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST' ...
ENDIF.
" Hata kontrolü
IF RETURN tablosunda E tipi mesaj var.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ev_status = 'E'. ev_message = hata metni.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'.
ev_status = 'S'. ev_belnr = belge no.
ENDIF.
ENDMETHOD.
💡 DEBUGMODE = 'X' ile BAPI_ACC_DOCUMENT_CHECK kullanılarak commit yapılmadan test edilebilir.
3.4 ABAP — ZCL_EXPENSE_USER_LIST (HR Sync)
SICF: /sap/bc/zexpense/user_list
METHOD if_http_extension~handle_request.
" ── Auth kontrolü (ZEXP_AUTH) ──
" GET / → ZEXP_USERS tablosundan JSON döndür
" GET ?action=SYNC → PA0001/PA0002'den çekip ZEXP_USERS güncelle
" - Mevcut kayıt: UPDATE
" - Yeni kayıt: INSERT
" - HR'da yok: ISACTIVE = '0'
" JSON Response: { EMPLOYEE_COUNT, SYNCED, INSERTED, DEACTIVATED }
ENDMETHOD.
⚠️ ABAP 7.0 uyumluluğu: &&, inline DATA(), string templates kullanılmaz.
3.5 SICF Servisleri
Transaction: SICF → /sap/bc/zexpense/
/post_expense → Handler: ZCL_EXPENSE_POSTING
/user_list → Handler: ZCL_EXPENSE_USER_LIST
Authentication: HTTP Basic (SAP standart)
3.6 Kullanıcı & Yetkilendirme
SU01 — Sistem Kullanıcısı
| Parametre | Değer |
| Kullanıcı Adı | ZEXP_API_USER |
| Kullanıcı Tipi | System (Dialog değil) |
| Rol | Z_EXPENSE_API_ROLE |
PFCG — Yetkilendirme Nesneleri
| Nesne | Alan | Değer |
| S_TCODE | TCD | SE16, SM30 |
| S_TABU_DIS | TABLE | ZEXP_* |
| S_ICF | ICFSERVICE | /sap/bc/zexpense/* |
| F_BKPF_BUK | BUKRS | <Şirket Kodu> |
| F_BKPF_KOA | KOART | A, D, G, K, M, S |
3.7 FI Uyarlamalar
| Tx | İşlem | Detay |
| OBA7 | Belge Tipi | SA veya özel ZK |
| FS00 | GL Hesaplar | Gider GL, Karşı Hesap, KDV GL |
| KS01 | Masraf Yeri | En az 1 aktif masraf yeri zorunlu |
| FTXP | Vergi Kodları | V0=%0, V1=%1, V4=%10, V5=%20 |
| MK01/FK01 | Vendor | Personel → Vendor eşleşmesi |
3.8 Bağlantı Yapılandırması (DB Encrypted)
💡 SAP bağlantı bilgileri .env dosyasında tutulmaz. Tüm credential'lar Xpensio Setup Wizard veya Admin Panel üzerinden girilir ve veritabanında AES-256-GCM ile şifrelenerek Organization.erpConfig alanında saklanır. Şifreler API'den okunurken otomatik maskelenir (••••••••).
Admin Panel → ERP Ayarları
| Alan | Örnek Değer | Açıklama |
erpType | ECC | SAP platform tipi |
sapBaseUrl | http://<SAP_HOST>:<PORT> | SICF base URL |
sapUsername | <API_KULLANICI> | SICF kullanıcı adı |
sapPassword | <API_SIFRESI> | 🔒 AES-256-GCM encrypted |
sapClient | <CLIENT_NO> | SAP mandant |
sapCompanyCode | <BUKRS> | Şirket kodu |
Minimal .env (Sadece sistem seviyesi)
# Sadece şifreleme anahtarı .env'de tutulur
ENCRYPTION_KEY=<64_HEX_KARAKTER> # 32-byte AES key
⚠️ ENCRYPTION_KEY production'da Docker Secret veya K8s Secret olarak yönetilmelidir. SAP kullanıcı adı/şifresi kesinlikle .env'de tutulmamalıdır.
3.9 Test Prosedürü
A) SAP Tarafı Test (SE38)
REPORT ZTEST_EXPENSE_POST.
" 1. ZEXP_S_POST_PAYLOAD yapısını doldur
" 2. DEBUGMODE = 'X' ile BAPI_ACC_DOCUMENT_CHECK çağır
" 3. RETURN tablosunu kontrol et → hata yoksa DEBUGMODE = '' ile tekrarla
" 4. BELNR alındı → FB03 ile belgeyi doğrula
B) REST Client Testi
curl -X POST http://<SAP_HOST>:<PORT>/sap/bc/zexpense/post_expense \
-H "Content-Type: application/json" \
-u "<USER>:<PASS>" \
-d '{
"COMPANYCODE":"<BUKRS>","EMPLOYEEID":"<VENDOR_NO>",
"EXPENSEDATE":"20260324","POSTINGDATE":"20260324",
"DOCUMENTTYPE":"SA","NETAMOUNT":100,"TAXAMOUNT":0,
"GROSSAMOUNT":100,"TAXCODE":"V0","CURRENCY":"TRY",
"GLACCOUNT":"<GL>","COSTCENTER":"<KY>",
"DESCRIPTION":"Test","REFERENCE":"TEST-001","DEBUGMODE":"X"
}'
C) Xpensio Uçtan Uca Test
POST /api/v1/identity/sync → Kullanıcılar SAP'den çekildi
- Dashboard → Yeni masraf oluştur → Onayla
- Muhasebe → SAP'ye Gönder → Durum:
POSTED_TO_SAP
- SAP FB03 ile belge numarasını doğrula
3.10 Kurulum Kontrol Listesi
SAP Tarafı
- DDIC nesneleri oluşturuldu ve aktive edildi (SE11)
- ZCL_EXPENSE_POSTING sınıfı oluşturuldu (SE24)
- ZCL_EXPENSE_USER_LIST sınıfı oluşturuldu (SE24)
- SICF servis node'ları aktive edildi
- ZEXP_API_USER sistem kullanıcısı oluşturuldu (SU01)
- Z_EXPENSE_API_ROLE rol atandı (PFCG)
- ZEXP_AUTH tablosu dolduruldu (SM30)
- ZEXP_CFG + ZEXP_CFG_GL tabloları dolduruldu (SM30)
- GL hesaplar, masraf yerleri, vergi kodları tanımlandı
- Personel → Vendor FI eşleşmesi yapıldı
- DEBUGMODE=X ile test postu başarılı
- Gerçek posting ile BELNR alındı ve FB03'te doğrulandı
Xpensio Tarafı
- Admin Panel → ERP Ayarları üzerinden SAP bağlantı bilgileri girildi
- Identity sync başarılı (
POST /api/v1/identity/sync)
- Grade dağılımı ve manager zinciri doğrulandı
- Test masrafı → Onayla → SAP POST →
POSTED_TO_SAP
4 S/4HANA On-Premise
IDENTITY_PROVIDER=SAP_S4_ONPREM SAP_TYPE=S4_ONPREM ABAP 7.50+
4.1 ECC ile Temel Farklar
| Özellik | ECC 6.0 | S/4HANA On-Prem |
| Muhasebe | Klasik FI (BKPF/BSEG) | Universal Journal (ACDOCA) |
| ABAP | 7.0+ (eski syntax) | 7.50+ (inline DATA, string templates) |
| FI Posting | BAPI_ACC_DOCUMENT_POST | BAPI compat veya OData v4 |
| HR Sync | Custom ABAP | OData EmployeeEntity veya HCM compat |
| Silinen Tablolar | BSEG, BSIS, BSAS… | Compatibility view olarak mevcut |
💡 S/4HANA Universal Journal (ACDOCA), tüm FI/CO/ML/AA girişlerini tek tabloda birleştirir. Xpensio BAPI'si bu katmanın üzerinde çalışır.
4.2 FI Posting Yaklaşımları
Yaklaşım A — BAPI Compat (Önerilen, En Hızlı Kurulum)
S/4HANA BAPI_ACC_DOCUMENT_POST'u desteklemeye devam eder. Bölüm 3.2–3.7'deki ECC ABAP kodu ve DDIC nesneleri birebir çalışır. Tek değişiklik:
SAP_TYPE=S4_ONPREM # (ECC yerine)
Yaklaşım B — OData v4 Journal Entry API
ABAP geliştirme yapmadan doğrudan S/4HANA standart OData servisi kullanılır:
POST /sap/opu/odata/sap/API_JOURNALENTRYITEMBASIC_SRV/JournalEntryItem
Authorization: Basic <base64>
Content-Type: application/json
{
"CompanyCode": "<BUKRS>",
"PostingDate": "2026-03-24",
"JournalEntryType": "SA",
"to_JournalEntryItem": {
"results": [
{ "GLAccount": "<GIDER_GL>", "DebitCreditCode": "S",
"AmountInTransactionCurrency": "100.00", "CostCenter": "<KY>" },
{ "GLAccount": "<KARSI_GL>", "DebitCreditCode": "H",
"AmountInTransactionCurrency": "120.00" }
]
}
}
⚠️ OData yaklaşımı için /IWFND/MAINT_SERVICE'de servis aktive edilmeli + x-csrf-token yönetimi gerekli.
4.3 HR / Kimlik Sync
Seçenek A — HCM Compat: HCM modülü mevcutsa → Bölüm 3.4'teki ABAP user_list aynen uygulanır.
Seçenek B — OData EmployeeEntity:
GET /sap/opu/odata/sap/HCMFAB_EMPLOYEE_SRV/EmployeeCollection
?$select=EmployeeId,FirstName,LastName,EmailAddress,
OrganizationalUnit,Position,Grade
&$filter=IsActive eq true
Bu yaklaşımda ABAP geliştirme gerekmez; IDENTITY_PROVIDER=SAP_S4_ONPREM ile otomatik seçilir.
4.4 Bağlantı Yapılandırması (DB Encrypted)
Bölüm 3.8'deki yapı aynen geçerlidir. Admin Panel → ERP Ayarları:
| Alan | Örnek Değer | Açıklama |
erpType | S4_ONPREM | Platform tipi |
sapBaseUrl | https://<S4_HOST>:<PORT> | S/4 base URL |
sapUsername | <API_KULLANICI> | SICF veya OData kullanıcısı |
sapPassword | <API_SIFRESI> | 🔒 AES-256-GCM encrypted |
sapClient | <CLIENT_NO> | SAP mandant |
sapCompanyCode | <BUKRS> | Şirket kodu |
odataServicePath | /sap/opu/odata/sap/API_JOURNAL… | OData yaklaşımında ek path |
4.5 Kontrol Listesi
- BAPI compat: ECC Bölüm 3.10 kontrol listesinin tamamı uygulandı
- OData:
/IWFND/MAINT_SERVICE servisleri aktive edildi
- HTTPS sertifikası SAP ICM'e yüklendi (STRUST)
- Universal Journal (ACDOCA) konfigürasyonu doğrulandı
- ENV
SAP_TYPE=S4_ONPREM olarak ayarlandı
- HR sync (HCM veya OData) testi başarılı
- FI Posting testi başarılı, BELNR alındı
5 S/4HANA Cloud + SuccessFactors
IDENTITY_PROVIDER=SAP_S4_CLOUD SAP_TYPE=S4_CLOUD ABAP Gerekmez
5.1 OAuth 2.0 Kurulumu (XSUAA / BTP)
- BTP Cockpit → Subaccount → Service Marketplace → S/4HANA Cloud aboneliği
- Service Instance oluştur →
clientid ve clientsecret al
- Scope'lara Journal Entry API erişimi ekle
Token Endpoint
POST https://<XSUAA>.authentication.<REGION>.hana.ondemand.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<CLIENT_ID>
&client_secret=<CLIENT_SECRET>
💡 Token süresi genellikle 1800sn (30dk). Xpensio expire öncesi otomatik yeniler.
5.2 FI Posting — Journal Entry API
Adım 1: CSRF Token Al
GET /sap/opu/odata/sap/API_JOURNALENTRYITEMBASIC_SRV/$metadata
Authorization: Bearer <TOKEN>
x-csrf-token: Fetch
→ Response Header: x-csrf-token: <CSRF_VALUE>
Adım 2: Journal Entry Oluştur
POST /sap/opu/odata/sap/API_JOURNALENTRYITEMBASIC_SRV/JournalEntryItem
Authorization: Bearer <TOKEN>
x-csrf-token: <CSRF_VALUE>
Content-Type: application/json
{
"CompanyCode": "<BUKRS>",
"AccountingDocumentType": "SA",
"DocumentReferenceID": "<EXPENSE_ID>",
"PostingDate": "2026-03-24",
"to_JournalEntryItem": {
"results": [
{ "GLAccount": "<GIDER_GL>", "DebitCreditCode": "S",
"AmountInTransactionCurrency": "100.00",
"CostCenter": "<KY>", "TaxCode": "V5" },
{ "GLAccount": "<KARSI_GL>", "DebitCreditCode": "H",
"AmountInTransactionCurrency": "120.00",
"Vendor": "<TEDARIKCI_NO>" }
]
}
}
5.3 HR Sync — SuccessFactors Employee Central API
SuccessFactors OAuth 2.0
POST https://<SF_HOST>/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<SF_CLIENT_ID>
&client_secret=<SF_CLIENT_SECRET>
&company_id=<SF_COMPANY_ID>
Çalışan Listesi
GET https://<SF_HOST>/odata/v4/sfsf/User
?$select=userId,firstName,lastName,email,department,
jobTitle,managerId,payGrade
&$filter=status eq 'active'
&$top=1000
Authorization: Bearer <SF_TOKEN>
Departman Listesi
GET https://<SF_HOST>/odata/v4/sfsf/FODepartment
?$select=departmentId,name,headOfUnit,parentUnit
&$filter=effectiveStatus eq 'A'
Pozisyon Listesi
GET https://<SF_HOST>/odata/v4/sfsf/Position
?$select=positionCode,externalName,payGrade
&$filter=effectiveStatus eq 'A'
5.4 SuccessFactors → Xpensio Alan Eşleşmesi
| SF OData Alanı | Xpensio DB | Not |
userId | externalId | SF kullanıcı ID |
email | email | PK — eşleşme anahtarı |
firstName + lastName | name | Birleştirilir |
department | departmentCode | → departmentId FK |
jobTitle / position | jobTitle | Unvan |
managerId → email resolve | managerEmail | 2. sorgu ile resolve |
payGrade | grade | Sayısal (7–19) |
status='active' | isActive=true | |
5.5 Bağlantı Yapılandırması (DB Encrypted)
Bölüm 3.8'deki yapı aynen geçerlidir. Admin Panel → ERP Ayarları:
| Alan | Örnek Değer | Açıklama |
erpType | S4_CLOUD | Platform tipi |
s4CloudBaseUrl | https://<S4CLOUD_HOST> | S/4 Cloud API base |
s4CloudTokenUrl | https://<XSUAA>.authentication… | XSUAA token endpoint |
s4CloudClientId | <CLIENT_ID> | OAuth2 client |
s4CloudClientSecret | <CLIENT_SECRET> | 🔒 AES-256-GCM encrypted |
sapCompanyCode | <BUKRS> | Şirket kodu |
sfBaseUrl | https://<SF_HOST>/odata/v4/sfsf | SuccessFactors OData |
sfTokenUrl | https://<SF_HOST>/oauth/token | SF OAuth2 token |
sfClientId | <SF_CLIENT_ID> | SF OAuth2 client |
sfClientSecret | <SF_CLIENT_SECRET> | 🔒 AES-256-GCM encrypted |
sfCompanyId | <SF_COMPANY_ID> | SF şirket ID |
5.6 Kontrol Listesi
SAP BTP / S/4HANA Cloud
- BTP Subaccount oluşturuldu
- OAuth2 client oluşturuldu, clientid/secret alındı
- Journal Entry API yetkisi service binding'e eklendi
- Token alınıyor + OData $metadata çekilebiliyor
- Test journal entry başarılı
SuccessFactors
- EC Admin: API User / OAuth2 Client oluşturuldu
- Employee, FODepartment, Position OData erişimi verildi
- API test: User koleksiyonundan aktif çalışanlar listeleniyor
- managerId → email resolve çalışıyor
Xpensio
- Admin Panel → ERP Ayarları üzerinden bağlantı bilgileri girildi (DB encrypted)
- S/4 Cloud token yenileme çalışıyor (expire öncesi otomatik)
- SF token yenileme çalışıyor
- Identity sync başarılı, kullanıcılar + departmanlar + pozisyonlar oluştu
- FI Posting testi → POSTED_TO_SAP durumu OK
6 Güvenlik & Ağ Gereksinimleri
6.1 Ağ & Firewall
| Kaynak | Hedef | Port | Protokol |
| Xpensio Backend | SAP ECC/S4 SICF | 8000/44300 | HTTPS |
| Xpensio Backend | S/4 Cloud API | 443 | HTTPS (OAuth2) |
| Xpensio Backend | SuccessFactors API | 443 | HTTPS (OAuth2) |
| Xpensio Backend | BTP XSUAA Token | 443 | HTTPS |
✅ SAP/ERP sunucusu ile Xpensio backend arasında VPN veya özel ağ (private link) bağlantısı önerilir.
6.2 Kimlik Bilgileri Yönetimi
- SAP kullanıcı adı, şifre, client secret gibi hassas bilgiler
.env dosyasında tutulmaz
- Tüm SAP bağlantı bilgileri veritabanında
Organization.erpConfig alanında AES-256-GCM ile şifrelenerek saklanır
- Şifreleme anahtarı (
ENCRYPTION_KEY) tek .env parametresidir — production'da Docker Secret veya K8s Secret olarak yönetilir
- Setup Wizard veya Admin Panel → ERP Ayarları üzerinden girilen bilgiler otomatik şifrelenir
- API'den config okunurken password/secret alanları otomatik maskelenir (
••••••••)
- Config güncelleme sırasında maskeli alanlar korunur (mevcut değer override edilmez)
- Kaynak koda credential bilgisi asla gömülmez
6.3 SAP Tarafı Güvenlik
- TLS: SICF dahil tüm HTTP çağrıları HTTPS olmalı (SAP ICM SSL sertifikası — STRUST)
- IP Kısıtlaması: SICF servis erişimini sadece Xpensio backend IP'sine kısıtlayın
- Least Privilege: API kullanıcısına yalnızca gerekli yetkilendirme nesneleri verilmeli
- Parola Politikası: API kullanıcısı parolası 90 günde bir rotasyona tabi tutulmalı
- Denetim: SAP SM21 (system log) / ST22 (dump analizi) loglarını periyodik kontrol edin
- API Kullanıcısı: System tipinde oluşturun (Dialog değil), interaktif oturum açmasın