# Vadesiz Hesap Acma
[toc]
Bu, kullanıcının yeni bir vadesiz hesap açma işlemi için yapılan akışın implementasyonudur.
## Akis
Workflow Nane : **opening-checking-account**
```mermaid
stateDiagram-v2
classDef ss fill:white
classDef fs fill:orange
class s ss
class f,c fs
s: opening-checking-account-start
f: opening-checking-account-finish
c: opening-checking-account-cancel
approval: opening-checking-account-approval
s --> approval: open-checking-account
approval --> f : open-checking-account-approve
approval --> s : back-to-open-checking-account-submit
approval --> c : cancel-open-checking-account
s --> c : cancel-open-checking-account-fs
```
* Transition Views
* **open-checking-account:** open-checking-account-submit-form
* **open-checking-account-approve:** open-checking-account-approve-form
* State Views
* **open-checking-account-completed:** open-checking-account-completed-view
## Süreç
Bir menü öğesi (düğme, kenar, bağlam vb.) ile iş akışı başlatılır. İş akışını başlatmak için gereken tek şey workflow adı olacaktır.
### 1. İlk Olarak Hangi Formun Gösterileceği Tespiti
İş akışını başlatmak için gereken bilgileri almak için "init" servisi çağrılır. Bu servis genellikle iş akışının başlangıç durumu, geçiş bilgileri ve görünüm bilgileri gibi temel bilgileri içerir. İlgili servis çağrısı, iş akışının başlatılması sırasında kullanıcıdan alınacak verileri, geçişleri ve görünümleri belirlemek için kullanılır.
> GET /workflow/**opening-account**/init
```json
{
"state": "opening-checking-account-start",
"view-source": "transition",
"transition": [
{
"transition": "open-checking-account",
"require-data": true,
"has-view-variant": false
}
]
}
```
İş akışı henüz başlamadığı için "init" servisi çağrısı sırasında "back" ve "cancel" gibi durumu geri almak veya iptal etmek için kullanılan geçiş bilgileri gelmez. İş akışının başlangıç durumundan önce bu tür geri dönüş veya iptal işlemleri mevcut olmaz çünkü iş akışı daha başlamamıştır.
**state** bilgisi her zaman iş akışını başlatan "start" tipinde bir durumu (state) temsil eder
**view-source** bilgisi iş akışının başlatılması sırasında kullanıcı arabirimi üzerinden bilgi alınarak iş akışının başlatılacağı görünümün kaynağını belirtir. Örneğin, tek bir geçiş (transition) olduğu durumda, *view-source* değeri *transition* olarak belirlenmiş ve bu durumda ilgili görünüm, bu belirli geçiş ile ilişkilidir. Bu, kullanıcının bu geçişi tetiklemesi durumunda görülecek olan görünümü belirtir. Eğer birden fazla geçiş seçeneği olsaydı ve her bir geçiş için farklı görünümler tasarlanmış olsaydı, o zaman *view-source* değeri *state* olacaktı ve *state* için tasarlanmış olan görünüm gösterilecekti. Bu durumda, iş akışının belirli bir aşamasına göre farklı görünümler sunulabilir.
**require-data** alanı kullanıcıdan veri gerektirip gerektirmediği belirler. Eğer require-data değeri true ise, kullanıcıdan bilgi alınarak bu geçiş tetiklenecek; eğer false ise, geçiş payload olmadan tetiklenecek.
**has-view-variant** alanı geçişin birden fazla görünüme (view) sahip olup olmadığı biglisidir. Eğer bu değer **true** ise, bu geçiş için birden fazla görünüm tanımlandığı anlaşılır. Bu durumda, iş akışı örneği (workflow instance) bağlamında özel bir görünüm erişimi sağlanacak ve görünüm talebi, iş akışı anahtarı ile sorgulanarak alınacaktır. Bu durumda görünümü dönen servis ek olarak görünüm form adını akış verileri içinde "**target-view@{transition or state name}**" değişkenine bakarak dönecektir. birden fazla görünüm olmasında durumunda target view akış içerisinde bir değişkene eşitlenir.
:::info
Örnek: open-checking-account birden fazla görünüm içerseydi, yani **has-view-variant** değeri **true** olsaydı o zaman aşağıdaki gibi görünüm istenecekti.
Servis ise akış örneği içindeki verilerde **target-view@open-checking-account** değişkenine tanımlı görünümü dönecekti.
> GET amorphie/transition/**open-checking-account**/view?type=dynamic-flutter&instance-id=*8be5d8b6-edb2-4906-ba80-7573960c5ba9* gibi.
:::
:::warning
Access Token ile Erişim Kontrolü:
İstemci (client), kapsam (scope), rol (role) gibi bilgiler "access token" ile gelen bilgiler aracılığıyla kullanılarak transition ve görünümün görünürlüğü filtrelenir. Bu sayede hangi kullanıcının hangi geçişi veya görünümü görebileceği belirlenir, güvenlik ve erişim kontrolü sağlanır.
:::
### 2. İlk Formun Tanım Bilgisi Çekilir
"init" servisi sonucunda bu akışın transition view ile ilerleyeceğini anlıyoruz. Bu amaçla akışı başlatacak geçiş view almak için servis çağrısı yapıyoruz.
> GET amorphie/transition/**open-checking-account**/view?type=dynamic-flutter
```json
{
"name": "open-checking-account-submit-form",
"type": "dynamic-flutter",
"language": "tr",
"navigation": "push",
"data": "latest",
"body": {
...
}
}
```
**type** alanı bir uygulamanın kullanıcı arayüzünü farklı teknolojilerle oluşturduğu durumları ayırmak için kullanılır. İlgili teknolojilere örnek olarak HTML, Flutter, Dynamic-Flutter ve Angular gibi önyüz teknolojileri verilebilir.
Bu tip bir belirleyici, uygulama içinde farklı teknolojilerin kullanıldığı veya farklı görünümlerin yüklendiği durumları işaretlemek için kullanılabilir. Örneğin, bu belirleyici ile filtreleme yaparak sadece belirli bir önyüz teknolojisine ait olan görünümleri alabilir veya işleyebilirsiniz.
**language** alanı bir görünümün dilini belirler. Bu alandaki değer, ilgili görünümün dilini belirleme amacıyla gönderilen HTTP taleplerinin başlık bölümünde bulunan "accept-language" ile uyumludur. Yani, kullanıcı tarafından tarayıcı veya istemci uygulaması üzerinden gönderilen "accept-language" talebi ile belirlenen dil ile uyumlu görünüm döner. Bu sayede ilgili görünüm, kullanıcının tercih ettiği dilde sunulabilir.
**navigation** kullanıcı arayüzü (UI) içinde sayfalar arasında geçiş yapma veya farklı görünümleri açma işlemlerini açıklar. Olası değerler:
* **pop-until:** Belirli bir sayfaya gitmek için, mevcut sayfadan başlayarak belirtilen sayfaya kadar olan tüm geçişleri geri alır.
* **push:** Belirtilen sayfayı açar ve eğer bu sayfa zaten geçmişte varsa, bu sayfayı tekrar açar.
* **push-replacement:** Belirtilen sayfayı açar ve mevcut sayfayı bu yeni sayfa ile değiştirir.
* **push-as-root:** Belirtilen sayfayı açar ve geçmişteki tüm sayfaları temizleyerek yeni sayfayı temel sayfa olarak ekler.
* **popup:** Belirtilen sayfayı bir popup (açılır pencere) olarak görüntüler.
* **bottom-sheet:** Belirtilen sayfayı bir alt tabaka modal penceresinde (bottom sheet) görüntüler.
**data** alanı henüz bir akış oluşmadığı için dikkate alınmayacaktır.
### 3. Gelen Form Bilgisi ile Form Örneği Oluşturulur
Form oluşturulurken durumu new (yeni) olarak belirlenir. Bu durum, iş akışının henüz bir örneğinin oluşturulmadığı ve kullanıcıya sunulmadığı bir aşamayı temsil eder. Ayrıca, bu durumda form içinde bir instance-id(form içerisinde bir guid oluşturarak verilir. Örneğimizde *8be5d8b6-edb2-4906-ba80-7573960c5ba9* form içinde oluşturulmuş örnek anahtarıdır) oluşturulur.
### 4. Kullanıcı Açılan Formu Doldurarak Akışa İletir
> POST amorphie/instance/**8be5d8b6-edb2-4906-ba80-7573960c5ba9**/transaction/**open-checking-account**
```json
{
"name": "Ece's allowance",
"currency": "TRL"
}
```
Bu adımda, kullanıcı açılan formu doldurarak iş akışına bir talepte bulunur. Talep, belirli örnek anahtarı (8be5d8b6-edb2-4906-ba80-7573960c5ba9) ve geçiş (open-checking-account) ile yapılmıştır. İletilen JSON verisi, formun içerdiği bilgileri temsil eder (örneğin, "Ece's allowance" adlı hesap adı ve "TRL" para birimi).
### 5. İstemci, Sonraki Adıma Geçebilmek İçin Örneğin Durumunu ve Geçişlerini Dinler (Sorgular)
İstemci, genellikle SignalR kanalı üzerinden örneğin durumunu ve sonraki adıma geçebilmek için kullanabileceği geçişleri dinler. Ancak, SignalR kanalının kurulamadığı istemciler veya mevcut bağlantının kopması durumunda, istemci durum bilgisini sorgulama işlemi HTTP GET ile yapılır.
> GET amorphie/instance/**8be5d8b6-edb2-4906-ba80-7573960c5ba9**/transition
```json
{
"state": "opening-checking-account-approval",
"base-state": "in-progress",
"view-source": "transition",
"transition": [
{
"transition": "open-checking-account-approve",
"type": "forward",
"has-view-variant": false,
"require-data": true
},
{
"transition": "back-to-open-checking-account-submit",
"type": "back",
"require-data": false
},
{
"transition": "cancel-open-checking-account",
"type": "cancel",
"require-data": false
}
]
}
```
Bu adımda, istemci örneğin durumunu ve sonraki adıma geçebilmek için kullanabileceği geçişleri sorgular. Gelen sonuç, örneğin durumu (opening-checking-account-approval) ve geçiş bilgilerini içerir. Bu geçişler arasında ileri gitme (open-checking-account-approve), geri dönme (back-to-open-checking-account-submit), ve işlemi iptal etme (cancel-open-checking-account) seçenekleri bulunmaktadır. Her bir geçişin tipi, görünüm varyantı olup olmadığı, ve gereken veri olup olmadığı gibi bilgiler de sağlanmıştır.
### 6. Gelen Form Bilgisi ile Onay Formu Örneği Oluşturulur
Gelen *forward* tipindeli geçiş (*transition*) bilgisi kullanılarak, varsayılan form örneği çekilir ve oluşturulur.
> **GET amorphie/transition/open-checking-account-approve/view?type=dynamic-flutter**
```json
{
"name": "open-checking-account-approve-form",
"type": "dynamic-flutter",
"language": "tr",
"navigation": "push",
"data": "latest",
"body": {
// Formun içeriği ve diğer bilgiler...
}
}
```
Bu adımda, "open-checking-account-approve" geçişi ile ilişkilendirilmiş olan varsayılan form örneği çekilir. Gelen bilgiler arasında formun adı (*open-checking-account-approve-form*), tipi (*dynamic-flutter*), dil seçeneği (*tr*), navigasyon türü (*push*), ve formun içeriği gibi detaylar yer alır.
Ek olarak arayüze veri bağlamaları için **data** seçeneği **latest** bilgisi dönmüştür.
**data** seçeneği içim olası değerler aşağıda listelenmiştir.
* **latest**: İlgili akış örneği içerisinde verinin son durumunu verir.Formlar ile gönderilen veriler(payload) ile akış içerisinde yapıllan güncellemeler ile değişkenlerin son halleri döner.
> **GET amorphie/instance/{instance-id}/data** veya
**GET amorphie/instance/{instance-id}/data?latest** veya
* **latest-payload**: İlgili geçişde son gönderilen verileri döner.
> **GET amorphie/instance/{instance-id}/data?latest-payload**
* **first-payload**: İlgili geçişde ilk gönderilen verileri döner.
> **GET amorphie/instance/{instance-id}/data?first-payload**
Forma, önceki adımda alınan örneğin benzersiz kimliği olan **instance id** parametresi gönderilir.
Form aktif bir akış ile ilişkilendirildiğinden, olası bağlamalar (bindings) için akışın verilerini sorgular. Bu durumda, formun içinde kullanılacak olan veriler alınır.
> **GET amorphie/instance/8be5d8b6-edb2-4906-ba80-7573960c5ba9/data**
```json
{
"name": "Ece's allowance",
"currency": "TRL"
}
```
**Back** (*geri*) geçişi geldiği için işletim sistemi seviyesinde geri dönüş eylemine bağlanır. *require-view* değeri false olduğu için bu geçiş, form görüntülenmeden tetiklenir.
**Cancel** (*iptal*) geçişi geldiği için işletim sistemi seviyesinde iptal eylemine bağlanır. *require-view* değeri false olduğu için bu geçiş, form görüntülenmeden tetiklenir.
Bu adımlarda, formun oluşturulması, ilgili verilerin çekilmesi ve geri dönüş/iptal olaylarına bağlanması gerçekleştirilir.
### 7. Kullanıcı Form Üzerinden Onay Verir
Kullanıcı, form üzerinden onay verdiğinde, iş akışının tamamlanabilmesi için bir POST talebi gönderilir. İlgili talep şu şekildedir:
> **POST amorphie/instance/8be5d8b6-edb2-4906-ba80-7573960c5ba9/transaction/open-account-approve**
Bu adımda, kullanıcı tarafından yapılan onay işlemi sonucunda belirtilen iş akışının tamamlanması beklenir.
### 8. Özet Sayfa Gösterilir
Bu noktada akış örneğinin **opening-checking-account-finish** durumuna gelmiş olması beklenir. Akış otomatik olarak sorgulandığında "view-source" olarak "state" değeri verilmiş ve herhangi bir geçişin olmadığı anlaşılır.
> GET amorphie/instance/**8be5d8b6-edb2-4906-ba80-7573960c5ba9**/transition
```jsonld=
{
"state": "opening-checking-account-finish",
"base-state": "finish",
"view-source": "state",
"transition": []
}
```
Bu yanıttan anladığımız, iş akışının tamamlandığıdır.
Direkt olarak state formu istenerek gösterim sağlanır. Özet sayfaların State (opening-checking-account-finish) üzerine tanımlı olması beklenir.
> GET amorphie/state/**opening-checking-account-finish**/view?type=flutter
```json
{
"name": "opening-checking-account-finish-flutter-form",
"type": "dynamic-flutter",
"language": "tr",
"navigation": "popup",
"data": "latest",
"body": {
// Form içeriği ve diğer bilgiler...
}
}
```
Form içerisindeki alanların bağlanabilmesi için gerekli olan veriler, data servisi üzerinden çekilerek forma entegre edilir. Hesap açıldığı için ek veriler bu aşamada alınabilecektir.
> GET amorphie/instance/**8be5d8b6-edb2-4906-ba80-7573960c5ba9**/data
```json
{
"name": "Ece's allowance",
"currency": "TRL",
"iban": "TR76 0009 9012 3456 7800 1000 01",
"branch": {
"code": "1910",
"title": "Merkez Sube"
}
}
```
### A. Back Implementasyonu
**Open-checking-account-approve** durumuna geçildiğinde, **back** ve **cancel** transition'ları bulunmaktadır.
Cihazda veya tarayıcıda "back" fonksiyonu tetiklendiğinde, **back-to-open-checking-account-submit** geçişinin aktive edilmesi beklenir. Form görüntüsü olmadan, direkt olarak geçiş tetiklenir.
POST amorphie/instance/8be5d8b6-edb2-4906-ba80-7573960c5ba9/transaction/back-to-open-account-submit
Bu tetikleme sonrasında akışın önceki adıma dönmesi beklenir.
İş akışı örmegi sorgulandığında ise örneğin başa döndüğü ve ek olarak geçişlerde cancel geçişinin de bulunduğu görülür. Çünkü akış örneği aktif bir akıştır.
> GET amorphie/instance/**8be5d8b6-edb2-4906-ba80-7573960c5ba9**/transition
```json
{
"state": "opening-checking-account-start",
"base-state": "start",
"transition": [
{
"transition": "open-checking-account",
"type": "forward",
"require-data": true,
"has-view-variant": false
},
{
"transition": "cancel-open-checking-account-fs",
"type": "cancel",
"require-data": false,
"has-view-variant": false
}
]
}
```
Bu aşamadan sonra, 2. adımdaki gibi formun çekilmesi beklenir. Bu sefer form akış devam ettiği için binding için gerekli olan veriler de çekilir.
Form oluşturulurken, form artık bir akış için oluşturulduğundan cancel implementasyonu yapılır.