15. Hizmet Görevleri (Otomasyon)

Hizmet görevleri (Service Tasks), sistem mantığını otomatik olarak yürütmenize olanak tanır. flowable:delegateExpression niteliğini kullanarak belirli bir işleme başvurursunuz.

📋 Mevcut Temsilciler (Delegates) Özeti

Temsilci Adı Bean Adı (${...}) Açıklama Gerekli Alanlar (<flowable:field>)
Hatırlatıcı Gönder sendReminder E-posta bildirimi gönderir. to (e-posta), subject (konu), body (içerik)
Görevi Yeniden Ata reassignTask Aktif görevlerin atamasını değiştirir (örneğin yükseltme/escalation için). targetAssignee (veya targetCandidateGroups), clearExisting
Role Göre Ata assignUsersByRole Belirli bir role sahip tüm kullanıcıları bulur ve bir e-posta listesi döndürür. roleName, outputVariable (sonuç değişkeni adı)
PDF Oluştur generatePdf Satır içi (inline) bir HTML şablonundan bir PDF belgesi oluşturur. template (HTML), outputVariable (sonuç değişkeni adı)

Mevcut İşlemler

1. Role Göre Kullanıcıları Getir (assignUsersByRole)

Belirli bir role sahip tüm kullanıcıları getirir ve e-postalarını bir liste değişkeninde saklar. Bu öncelikle Paralel Çoklu Örnek (Parallel Multi-Instance) görevleri (bir görevi roldeki herkese atamak) için kullanılır.

Girdiler (Alanlar):

  • roleName: Rol anahtarı (ör. ROLE_MANAGER).
  • outputVariable: Listenin saklanacağı değişkenin adı (varsayılan: targetUsers).

Örnek: Anketi Tüm Yöneticilere Ata

<!-- Step 1: Fetch list of managers -->
<serviceTask id="fetchMgrs" flowable:delegateExpression="${assignUsersByRole}">
    <extensionElements>
        <flowable:field name="roleName" stringValue="ROLE_MANAGER"/>
        <flowable:field name="outputVariable" stringValue="managerList"/>
    </extensionElements>
</serviceTask>

<!-- Step 2: Create a task for EACH manager in the list -->
<userTask id="survey" name="Manager Survey" flowable:assignee="${assignee}">
    <multiInstanceLoopCharacteristics isSequential="false"
         flowable:collection="managerList"
         flowable:elementVariable="assignee"/>
</userTask>

2. PDF Belgesi Oluştur (generatePdf)

İçerisinde ${variable} yer tutucuları bulunan satır içi (inline) bir HTML şablonundan PDF belgesi oluşturur. Şablon doğrudan BPMN Hizmet Görevinin içine bir <flowable:field> olarak yazılır — harici dosyalara veya şablon yönetimine gerek yoktur.

Girdiler (Alanlar):

Alan Gerekli Açıklama
template ✅ Evet ${variable} yer tutucuları içeren satır içi HTML içeriği. Bir <flowable:string><![CDATA[...]]></flowable:string> bloğunun içine yazılır.
outputVariable ✅ Evet Oluşturulan dosya adını tutacak süreç değişkeninin adı. PDF'e sonraki görevlerde başvurmak için kullanılır.
outputFileName ❌ İsteğe Bağlı PDF dosya adının okunabilir kısmı. Varsayılan olarak document'tır. Çakışmaları önlemek için her zaman başa bir UUID öneki eklenir (ör. a8f3b2c1_invoice.pdf).

Nasıl Çalışır:

  1. İş akışı tasarımcısı flowable:delegateExpression="${generatePdf}" içeren bir Hizmet Görevi yerleştirir ve HTML şablonunu satır içi (inline) yazar.
  2. Çalışma zamanında (runtime) temsilci, template alanını okur ve süreç değişkenlerini kullanarak basit bir ${var} regex (düzenli ifade) değişimi gerçekleştirir.
  3. Flying Saucer, işlenmiş HTML+CSS'i bir PDF bayt akışına (byte stream) dönüştürür.
  4. PDF, mevcut StorageService aracılığıyla uploads/{processInstanceId}/{uuid}_{outputFileName}.pdf yoluna kaydedilir.
  5. Oluşturulan dosya adı, outputVariable tarafından belirtilen isimle bir süreç değişkeni olarak saklanır.
  6. Bir ProcessAttachment kaydı oluşturulur, böylece PDF sonraki tüm Kullanıcı Görevleri için otomatik olarak "Süreç Belgeleri" (Process Documents) kartında görünür — form alanına gerek yoktur.

Örnek: Fatura PDF'i Oluşturma

<!-- Step 1: Employee enters invoice data -->
<userTask id="fillData" name="Enter Invoice Details" flowable:assignee="${initiator}">
    <extensionElements>
        <activiti:formProperty id="itemName" name="Item Name" type="string" required="true"/>
        <activiti:formProperty id="price" name="Price" type="double" required="true"/>
        <activiti:formProperty id="buyDate" name="Purchase Date" type="date" required="true"/>
    </extensionElements>
</userTask>

<!-- Step 2: Generate PDF (automatic, no human interaction) -->
<serviceTask id="genInvoice" flowable:delegateExpression="${generatePdf}">
    <extensionElements>
        <flowable:field name="outputVariable" stringValue="generatedInvoice"/>
        <flowable:field name="outputFileName" stringValue="invoice"/>
        <flowable:field name="template">
            <flowable:string><![CDATA[
                <html><body>
                <h1>Invoice</h1>
                <p>Item: ${itemName}</p>
                <p>Price: ${price} USD</p>
                <p>Date: ${buyDate}</p>
                </body></html>
            ]]></flowable:string>
        </flowable:field>
    </extensionElements>
</serviceTask>

<!-- Step 3: Manager reviews — PDF is automatically visible in the "Process Documents" card -->
<userTask id="reviewInvoice" name="Review Invoice" flowable:candidateGroups="ROLE_MANAGER">
    <extensionElements>
        <activiti:formProperty id="decision" name="Decision" type="enum" required="true">
            <activiti:value id="approve" name="Approve"/>
            <activiti:value id="reject" name="Reject"/>
        </activiti:formProperty>
    </extensionElements>
</userTask>

Otomatik görünürlük: Oluşturulan PDF, generatePdf Hizmet Görevinden sonraki her Kullanıcı Görevinde "Süreç Belgeleri" kartında görünür — herhangi bir form alanına gerek yoktur. Bu, kullanıcı tarafından yüklenen dosyalar için kullanılan desenin aynısıdır.

Şablon formatı: Şablonlar HTML + CSS 2.1'i destekler (Flying Saucer sınırlaması). Görsel eklemek için (örneğin şirket logosu), base64 veri URI'si olarak gömün (<img src="data:image/png;base64,..." />).

Doğrulama: Bir BPMN, template alanı olmadan ${generatePdf} kullanırsa, bu bir Hata olarak kabul edilir ve dağıtımı (deployment) engeller.