xFlow
  • Overview
    • Introduction
    • Core Features
    • Architecture
      • High Level Architecture
      • Tech Stack
      • Deployment Flexibility
      • Performance and Scalability
      • Security Compliance
  • Getting Started
    • Installation
    • Quick Start
    • Configuration
  • Core Concepts
    • Serverless Workflow Specification
    • Workflow data handling
    • Workflow Expressions
    • Error handling
    • Input and Output schema definition
    • User Task
    • User Forms
      • Lowcode Form
      • Advanced User Form
    • AI Agents in Enterprise Business Processes
    • Comparisons
      • BPMN2
  • Developer Guide
    • Architecture
    • API Reference
    • Workflow States Reference
      • Event State
      • Operation State
      • Switch State
      • Parallel State
      • Inject State
      • ForEach State
      • Callback State
      • UserTask State
      • AIAgent State
      • AIAgentProxy State
      • UserProxyAgent State
      • AI Outbound Agent State
    • Workflow Functions
      • REST
      • GraphQL
      • Custom
        • Built-in Functions
        • Lowcoder Query Function
      • Function Auth
    • Workflow Secrets
    • Integrations
    • Workflow Modeler
    • Frontend Development
      • Forms
        • Lowcode Form
        • Advanced User Form
    • Serverless Workflow Development
      • Operation State
      • Switch State
      • Parallel State
      • ForEach State
      • Callback State
      • User Task State
    • AI Agent Development
      • AI Agent
        • Predefined LLM
        • LLM Configuration
        • Multi LLM Configuration
        • Chat Memory
        • Tools
        • Data Output
        • Agent Outcomes
      • AI Agent Proxy
        • AI Agents Integration
      • User Proxy Agent
      • xChatBot Integration
  • Examples
    • Basic Examples
    • Advanced Examples
      • Loan Approval Workflow
      • QMS AP Workflow
  • Administration
    • Monitoring and Logging
    • Security
    • Performance Tuning
  • Extensions and Customizations
    • Plugins and Add-ons
  • Troubleshooting
    • Common Issues
    • FAQs
  • Release Notes
    • Version History
    • Upcoming Features
  • Support
    • Contact Information
    • Community
Powered by GitBook
On this page
  • Main Workflow
  • Sub Workflow
  • Adjustment Sub Workflow
  1. Examples
  2. Advanced Examples

Loan Approval Workflow

Main Workflow

id: XBANK_LOAN_APPROVAL
name: XBANK_LOAN_APPROVAL Workflow
version: '1.0'
dataInputSchema:
  schema: |-
    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "type": "object",
      "properties": {
        "request": {
          "type": "object",
          "properties": {
    "inputmataisan": {
      "type": "string"
    },
    "inputphantichkhac": {
      "type": "string"
    },
    "inputsothuadat": {
      "type": "string"
    },
    "inputhoten": {
      "type": "string"
    },
    "datengaysinh": {
      "type": "integer"
    },
    "selectgioitinh": {
      "type": "string"
    },
    "inputnoithuongtru": {
      "type": "string"
    },
    "selecttinhtranghonnhan": {
      "type": "string"
    },
    "datengayvaolam": {
      "type": "integer"
    },
    "datengaydinhgia": {
      "type": "integer"
    },
    "datengaycapgcn": {
      "type": "integer"
    },
    "selectphannhomkh": {
      "type": "string"
    },
    "inputnghenghiep": {
      "type": "string"
    },
    "selectdoituongcbnv": {
      "type": "string"
    },
    "inputmanv": {
      "type": "string"
    },
    "inputthoigianlamviec": {
      "type": "string"
    },
    "selecthinhthucnhanluong": {
      "type": "string"
    },
    "inputmota": {
      "type": "string"
    },
    "selecttrangthaitaisan": {
      "type": "string"
    },
    "selectnguongochinhthanh": {
      "type": "string"
    },
    "inputsochungthudinhgia": {
      "type": "string"
    },
    "numbergiatridinhgia": {
      "type": "integer"
    },
    "numbergiatribaodamtoida": {
      "type": "integer"
    },
    "numbergiatridadambao": {
      "type": "integer"
    },
    "numbergiatriconduocdambao": {
      "type": "integer"
    },
    "numbergiatridambaochophuongan": {
      "type": "integer"
    },
    "selectloaitaisan": {
      "type": "string"
    },
    "inputsogiaychungnhan": {
      "type": "string"
    },
    "inputsotobando": {
      "type": "string"
    },
    "inputdiachitinhthanh": {
      "type": "string"
    },
    "inputhuyenquan": {
      "type": "string"
    },
    "inputxaphuong": {
      "type": "string"
    },
    "inputthonxomto": {
      "type": "string"
    },
    "inputsonha": {
      "type": "string"
    },
    "inputnoicapgcn": {
      "type": "string"
    },
    "inputsovaosocapgcn": {
      "type": "string"
    },
    "numberdientich": {
      "type": "integer"
    },
    "selectnguongocdat": {
      "type": "string"
    },
    "numberIdorongngo": {
      "type": "integer"
    },
    "numberdorongmattien": {
      "type": "integer"
    },
    "listgttt": {
      "type": "array",
      "items": [
        {
          "type": "object",
          "properties": {
    "aggId": {
      "type": "string"
    },
    "phanloaigttt": {
      "type": "string"
    },
    "phanloaigtttlabel": {
      "type": "string"
    },
    "loaigttt": {
      "type": "string"
    },
    "loaigtttlabel": {
      "type": "string"
    },
    "sogttt": {
      "type": "string"
    },
    "ngaycap": {
      "type": "integer"
    },
    "ngaycaplabel": {
      "type": "string"
    },
    "noicap": {
      "type": "string"
    }
          },
          "required": [
    "aggId",
    "phanloaigttt",
    "phanloaigtttlabel",
    "loaigttt",
    "loaigtttlabel",
    "sogttt",
    "ngaycap",
    "ngaycaplabel",
    "noicap"
          ]
        }
      ]
    },
    "listchutaisan": {
      "type": "array",
      "items": [
        {
          "type": "object",
          "properties": {
    "aggId": {
      "type": "string"
    },
    "tenchutaisan": {
      "type": "string"
    },
    "sogttt": {
      "type": "integer"
    },
    "namsinh": {
      "type": "integer"
    },
    "diachi": {
      "type": "string"
    },
    "quanhe": {
      "type": "string"
    },
    "quanhelabel": {
      "type": "string"
    }
          },
          "required": [
    "aggId",
    "tenchutaisan",
    "sogttt",
    "namsinh",
    "diachi",
    "quanhe",
    "quanhelabel"
          ]
        }
      ]
    },
    "listqsdd": {
      "type": "array",
      "items": {}
    },
    "listctxd": {
      "type": "array",
      "items": {}
    }
          },
          "required": [
    "inputmataisan",
    "inputphantichkhac",
    "inputsothuadat",
    "inputhoten",
    "datengaysinh",
    "selectgioitinh",
    "inputnoithuongtru",
    "selecttinhtranghonnhan",
    "datengayvaolam",
    "datengaydinhgia",
    "datengaycapgcn",
    "selectphannhomkh",
    "inputnghenghiep",
    "selectdoituongcbnv",
    "inputmanv",
    "inputthoigianlamviec",
    "selecthinhthucnhanluong",
    "inputmota",
    "selecttrangthaitaisan",
    "selectnguongochinhthanh",
    "inputsochungthudinhgia",
    "numbergiatridinhgia",
    "numbergiatribaodamtoida",
    "numbergiatridadambao",
    "numbergiatriconduocdambao",
    "numbergiatridambaochophuongan",
    "selectloaitaisan",
    "inputsogiaychungnhan",
    "inputsotobando",
    "inputdiachitinhthanh",
    "inputhuyenquan",
    "inputxaphuong",
    "inputthonxomto",
    "inputsonha",
    "inputnoicapgcn",
    "inputsovaosocapgcn",
    "numberdientich",
    "selectnguongocdat",
    "numberIdorongngo",
    "numberdorongmattien",
    "listgttt",
    "listchutaisan",
    "listqsdd",
    "listctxd"
          ]
        }
      },
      "required": [
        "request"
      ]
    }
  failOnValidationErrors: true
metadata:
  startFormKey: 'LCD#661f784162f95774145bdf9f'
timeouts:
  workflowExecTimeout:
    duration: P1D
  actionExecTimeout: PT1M
retries:
  - name: WorkflowRetries
    delay: PT3S
    maxAttempts: 10
start:
  stateName: Khởi tạo phương án
states:
  - name: Khởi tạo phương án
    type: operation
    actions:
      - name: Generate Loan Request Code
        functionRef:
          refName: GenLoanRequestCode
          arguments: {}
        actionDataFilter:
          results: '${ {"code": .data[0].code} }'
          toStateData: '${ .request }'
      - name: Update Proc Inst Info
        functionRef:
          refName: UpdateProcInstInfo
          arguments:
            procInst: '${ { "businessKey": .request.code } }'
        actionDataFilter:
          useResults: false
    transition: Kiểm soát đề xuất cấp 1 (KSRM1)
  - name: Cung cấp hồ sơ và đề nghị vay vốn
    taskKey: taskCungCapHoSoVaDeNghiVayVon
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: cvqhkh@xbank.com
    taskOutcomes:
      - code: Complete
        name: Gửi đề xuất
        outcomeDecision: COMPLETED
        transition: Kiểm soát đề xuất cấp 1 (KSRM1)
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Kiểm soát đề xuất cấp 1 (KSRM1)
  - name: Kiểm soát đề xuất cấp 1 (KSRM1)
    taskKey: taskKSRM1
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: gdm@xbank.com
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Kiểm soát đề xuất cấp 2 (KSRM2)
      - code: Reject
        name: Trả đề xuất
        outcomeDecision: REJECTED
        transition: Cung cấp hồ sơ và đề nghị vay vốn
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Kiểm soát đề xuất cấp 2 (KSRM2)
  - name: Kiểm soát đề xuất cấp 2 (KSRM2)
    taskKey: taskKSRM2
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: gdv@xbank.com
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Thực hiện Thẩm định
      - code: Reject
        name: Trả đề xuất
        outcomeDecision: REJECTED
        transition: Cung cấp hồ sơ và đề nghị vay vốn
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Thực hiện Thẩm định
  - name: Thực hiện Thẩm định
    taskKey: taskThucHienThamDinh
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: tdv01@xbank.com
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Thẩm định điện thoại
      - code: Reject
        name: Trả Khâu đề xuất
        outcomeDecision: REJECTED
        transition: Cung cấp hồ sơ và đề nghị vay vốn
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Thẩm định điện thoại
  - name: Thẩm định điện thoại
    taskKey: taskThamDinhDienThoai
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: tdv02@xbank.com
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Thẩm định thực địa
      - code: Reject
        name: Trả Khâu đề xuất
        outcomeDecision: REJECTED
        transition: Cung cấp hồ sơ và đề nghị vay vốn
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Thẩm định thực địa
  - name: Thẩm định thực địa
    taskKey: taskThamDinhThucDia
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: tdv03@xbank.com
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Kiểm soát thẩm định
      - code: Reject
        name: Trả Khâu đề xuất
        outcomeDecision: REJECTED
        transition: Cung cấp hồ sơ và đề nghị vay vốn
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Kiểm soát thẩm định
  - name: Kiểm soát thẩm định
    taskKey: taskKiemSoatThamDinh
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: ksvtd@xbank.com
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Xác định thành viên BTD
      - code: RejectTDTD
        name: Trả Thẩm định thực địa
        outcomeDecision: TDTD_REJECTED
        transition: Thẩm định thực địa
      - code: RejectTTDT
        name: Trả Thẩm định điện thoại
        outcomeDecision: TTDT_REJECTED
        transition: Thẩm định điện thoại
      - code: RejectTD
        name: Trả Thẩm định
        outcomeDecision: TD_REJECTED
        transition: Thực hiện Thẩm định
      - code: Reject
        name: Trả Khâu đề xuất
        outcomeDecision: REJECTED
        transition: Cung cấp hồ sơ và đề nghị vay vốn
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Xác định thành viên BTD
  - name: Xác định thành viên BTD
    taskKey: taskXacDinhThanhVienBTD
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: thuky@xbank.com
    taskOutcomes:
      - code: Complete
        name: Gửi BTD phê duyệt
        outcomeDecision: COMPLETED
        transition: Ban TD phê duyệt
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Ban TD phê duyệt
  - name: Ban TD phê duyệt
    type: foreach
    inputCollection: '${ .request.tvbtds }'
    iterationParam: tvbtd
    outputCollection: '${ .request.tvbtdResults }'
    actions:
      - subFlowRef:
          workflowId: XBANK_LOAN_SUB
        actionDataFilter:
          fromStateData: '${ {"request": .request, "subRequest": { "tvbtd": $tvbtd.email }} }'
    transition: Sys-Collect-Final-Result
  - name: Sys-Collect-Final-Result
    type: operation
    actionMode: sequential
    actions:
      - functionRef:
          refName: CollectFinalResultJsCode
          arguments:
            tvbtdResults: '${ .request.tvbtdResults }'
        actionDataFilter:
          results: '${ .data }'
          toStateData: '${ .request.finalResult }'
      - functionRef:
          refName: MergeEditedRequestData
          arguments:
            tvbtdResults: '${ .request.tvbtdResults }'
        actionDataFilter:
          results: '${ .jqResult }'
          toStateData: '${ .request }'
    transition: Sys-Check-Final-Result
  - name: Sys-Check-Final-Result
    type: switch
    dataConditions:
      - name: Cannot Decide Final Result
        condition: '${ .request.finalResult == null or .request.finalResult == "" }'
        transition: Tổng hợp kết quả phê duyệt
      - name: Final Result Is Decided
        condition: >-
          ${ .request.finalResult == "APPROVED" or .request.finalResult ==
          "REJECTED" }
        transition: Sys-Generate-Request-Form
    defaultCondition:
      transition: Tổng hợp kết quả phê duyệt
  - name: Tổng hợp kết quả phê duyệt
    taskKey: taskTongHopKetQuaPheDuyet
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: thuky@xbank.com
    taskOutcomes:
      - code: Complete
        name: Gửi KQ tổng hợp
        outcomeDecision: COMPLETED
        transition: Xác nhận kết quả phê duyệt
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request }'
    transition: Xác nhận kết quả phê duyệt
  - name: Xác nhận kết quả phê duyệt
    taskKey: taskXacNhanKetQuaPheDuyet
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: truongbtd@xbank.com
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Sys-Generate-Request-Form
      - code: Reject
        name: Từ chối
        outcomeDecision: REJECTED
        transition: Sys-Generate-Request-Form
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: SetFinalResult
              arguments:
                finalResult: '${ $userTask.outcome }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .request.finalResult }'
    transition: Sys-Generate-Request-Form
  - name: Sys-Generate-Request-Form
    type: operation
    actionMode: sequential
    actions:
      - functionRef:
          refName: GenerateRequestForm
          arguments:
            cmd: >-
              ${ {"storeToDms": false,"templateCode":
              "XBANK/XBANK_LOAN_REQUEST.docx", "params": { "code": .request.code,
              "CU1": .request.inputhoten, "CU2": (.request.datengaysinh |
              strftime("dd-MM-yyyy")), "CU3": (.request.selectgioitinh | if . ==
              "1" then "Nam" elif . == "2" then "Nữ" else "Khác" end), "CU4":
              .request.inputnoithuongtru, "CU5":
              (.request.selecttinhtranghonnhan  | if . == "1" then "Độc thân"
              elif . == "2" then "Đã có gia đình" elif . == "3" then "Ly dị"
              elif . == "4" then "Góa" else "Khác" end), "CU6": "", "CU7":
              first(.request.listgttt[] | select(.phanloaigttt == "1") |
              .loaigtttlabel), "CU8": first(.request.listgttt[] |
              select(.phanloaigttt == "1") | .sogttt), "CU9":
              first(.request.listgttt[] | select(.phanloaigttt == "1") |
              .ngaycaplabel), "CU10": "", "CU11": "", "CU12":
              .request.inputnghenghiep, "CU13": (.request.selectdoituongcbnv |
              if . == "1" then "Thông thường" elif . == "2" then "Thâm niên"
              elif . == "3" then "Chủ chốt" else "Khác" end), "CU14":
              .request.inputmanv, "CU15": "", "CU16":
              .request.inputthoigianlamviec, "CO7": .request.numbergiatridinhgia
              | money(), "CO11": .request.numbergiatridambaochophuongan |
              money(), "CO12": first(.request.listchutaisan[] |  .tenchutaisan),
              "CO16": first(.request.listchutaisan[] |  .quanhelabel), "CO18":
              .request.inputphantichkhac, "CO20": .request.inputsogiaychungnhan,
              "CO21": .request.inputsothuadat, "CO22": .request.inputsotobando,
              "CO23": .request.inputdiachitinhthanh, "CO24":
              .request.inputhuyenquan, "CO25": .request.inputxaphuong, "CO26":
              .request.inputthonxomto, "CO27": .request.inputsonha, "CO28":
              (.request.datengaycapgcn | strftime("dd-MM-yyyy")), "CO29":
              .request.inputnoicapgcn, "CO35": first(.request.listqsdd[] |
              .mucdichsudungqsddlabel), "CO38": first(.request.listqsdd[] |
              .giatridinhgiaqsdd) | money(), "CO39": first(.request.listqsdd[] |
              .ltvtoidaqsdd) | money(), "CO40": first(.request.listqsdd[] |
              .ltvdexuatqsdd) | money(), "CO42": first(.request.listctxd[] |
              .mucdichsudungctxdlabel), "CO49": first(.request.listctxd[] |
              .giatridinhgiactxd) | money(), "CO50": first(.request.listctxd[] |
              .ltvtoidactxd) | money(), "CO51": first(.request.listctxd[] |
              .ltvdexuatctxd) | money() }, "tables":{}} }
        actionDataFilter:
          results: '${ .data }'
          toStateData: '${ .request.formUUID }'
    transition: Sys-Digital-Sign-Request-Form
  - name: Sys-Digital-Sign-Request-Form
    type: operation
    actionMode: sequential
    actions:
      - functionRef:
          refName: DigitalSignRequestForm
          arguments:
            docUri: '${ .request.formUUID }'
            cmd: >-
              ${ {"alias": "5404fffeb7033fb316d672201b9530f4", "refNo": "uuid4",
              "account": "034067004207", "ackInfo": null, "appCode": "BPM",
              "makerId": "truongbtd@xbank.com", "signerName": "Trưởng BTD",
              "signerType": "O", "ackResponse": false, "companyCode": "POC",
              "signingHints": {"x": 0.0, "y": 0.0, "page": 0, "width": 0.0,
              "height": 0.0, "marginX": 0.0, "marginY": 0.0, "location":
              "SPECIFIC_PAGE", "textContent": null, "signatureImage": null,
              "signatureFields": [], "signaturePosition": "XY",
              "showSignatureImage": true, "signatureImageGenerate": false},
              "signerLocation": "XBANKank", "signatureReason": "Sign document"} }
        actionDataFilter:
          results: '${ .data }'
          toStateData: '${ .request.formUUID }'
    transition: Tiếp nhận kết quả PD
  - name: Tiếp nhận kết quả PD
    taskKey: taskTiepNhanKetQuaPD
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: cvqhkh@xbank.com
    taskOutcomes:
      - code: Complete
        name: Kết thúc
        outcomeDecision: COMPLETED
        transition: Kết thúc
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions: []
    transition: Kết thúc
  - name: Kết thúc
    type: operation
    actions: []
    end: true
functions:
  - name: GenLoanRequestCode
    type: custom
    operation: ExecuteQueryAction
    metadata:
      libraryQueryName: cmd.gen.xbank_loan_request_code
      libraryQueryRecordId: latest
      params: '[]'
  - name: MergeEditedRequestData
    type: custom
    operation: JqQueryExecute
    metadata:
      jq: '${ .tvbtdResults | map(.editedRequest) | add }'
  - name: MergeLoanRequestData
    type: custom
    operation: JqQueryExecute
    metadata:
      jq: '${ .editedRequest }'
  - name: CollectFinalResultJsCode
    type: custom
    operation: RunJs
    metadata:
      jsCode: |-
        function checkOutcomes(arr) {
            let approvedCount = 0;
            let rejectedCount = 0;

            for (let i = 0; i < arr.length; i++) {
                if (arr[i].outcome === 'APPROVED') {
                    approvedCount++;
                } else if (arr[i].outcome === 'REJECTED') {
                    rejectedCount++;
                }
            }

            if (approvedCount === arr.length) {
                return 'APPROVED';
            } else if (rejectedCount === arr.length) {
                return 'REJECTED';
            } else {
                return "";
            }
        }
        return checkOutcomes(tvbtdResults);
      params: '["tvbtdResults"]'
  - name: SetFinalResult
    type: custom
    operation: JqQueryExecute
    metadata:
      jq: '${ .finalResult }'
  - name: NotifyWhenUserTaskCreated
    type: custom
    operation: ExecuteQueryAction
    metadata:
      libraryQueryName: cmd.mail.send_task_created
      libraryQueryRecordId: latest
      params: '["taskName","requestCode","custName"]'
  - name: StampForm
    type: custom
    operation: ExecuteQueryAction
    metadata:
      libraryQueryName: cmd.notif.log
      libraryQueryRecordId: latest
      params: '["custName"]'
  - name: GenerateRequestForm
    type: custom
    operation: RenderDocTemplate
    metadata: {}
  - name: DigitalSignRequestForm
    type: custom
    operation: DigitalSignDoc
    metadata: {}
  - name: UpdateProcInstInfo
    type: custom
    operation: UpdateProcInst
    metadata: {}
events:
  - name: NewApplicationEvent
    type: com.a4b.xflow.engine.StateData
    source: xflowengine
  - name: UserTaskCreated
    type: com.a4b.xptask.event.post.user_task.UserTaskCreatedEvent
  - name: UserTaskCompleted
    type: com.a4b.xptask.event.post.user_task.UserTaskCompletedEvent
errors:
  - name: Not allowed to transfer money
    code: (.+) not allowed to transfer money
    description: User was not allowed to transfer money
  - name: Underage denied
    code: Transferring money is denied for underage
    description: Transferring money is denied for underage individuals.

Sub Workflow

id: XBANK_LOAN_SUB
name: XBANK_LOAN_SUB Workflow
version: '1.0'
metadata:
  startFormKey: 'LCD#661f784162f95774145bdf9f'
timeouts:
  workflowExecTimeout:
    duration: P1D
  actionExecTimeout: PT1M
retries:
  - name: WorkflowRetries
    delay: PT3S
    maxAttempts: 10
start:
  stateName: Khởi tạo
states:
  - name: Khởi tạo
    type: operation
    actions: []
    transition: TVBTD Cho ý kiến phê duyệt
  - name: TVBTD Cho ý kiến phê duyệt
    taskKey: taskYKienPheDuyet
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: '${ .subRequest.tvbtd }'
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Kết thúc
      - code: Reject
        name: Từ chối
        outcomeDecision: REJECTED
        transition: Kết thúc
      - code: RequestAdjustment
        name: Yêu cầu điều chỉnh
        outcomeDecision: ADJUSTMENT_REQUESTED
        transition: Thực hiện điều chỉnh
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                tvbtd: '${ .subRequest.tvbtd }'
                outcome: '${ $userTask.outcome }'
                editing: '${ $userTask.data.editedRequest.editing }'
                comment: '${ $userTask.data.comment }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .tvbtdResult }'
          - functionRef:
              refName: SetEditorInfo
              arguments:
                editor: '${ "cvqhkh@xbank.com" }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .subRequest }'
            condition: '${ $userTask.outcome == "ADJUSTMENT_REQUESTED" }'
          - functionRef:
              refName: ExtractEditedValuesJsCode
              arguments:
                request: '${ .request }'
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .data }'
              toStateData: '${ .editedRequest }'
          - functionRef:
              refName: ExtractEditedValuesJsCode
              arguments:
                request: '${ .request }'
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .data }'
              toStateData: '${ .request }'
    transition: Kết thúc
  - name: Thực hiện điều chỉnh
    type: parallel
    completionType: allOf
    branches:
      - name: S1
        actions:
          - subFlowRef:
              workflowId: XBANK_LOAN_ADJUSTMENT
            actionDataFilter:
              fromStateData: '${ {"request": .request, "adjRequest": { "editing": "S1" }} }'
              results: '${ .editedRequest }'
              toStateData: '${ .editedRequest }'
            condition: '${ .tvbtdResult.editing | index( "S1" ) >= 0 }'
      - name: S2
        actions:
          - subFlowRef:
              workflowId: XBANK_LOAN_ADJUSTMENT
            actionDataFilter:
              fromStateData: '${ {"request": .request, "adjRequest": { "editing": "S2" }} }'
              results: '${ .editedRequest }'
              toStateData: '${ .editedRequest }'
            condition: '${ .tvbtdResult.editing | index( "S2" ) >= 0 }'
    transition: Merge-Ajustment-Data
  - name: Merge-Ajustment-Data
    type: operation
    actionMode: sequential
    actions:
      - functionRef:
          refName: MergeAdjustmentData
          arguments:
            editedRequest: '${ .editedRequest }'
        actionDataFilter:
          results: '${ .jqResult }'
          toStateData: '${ .request }'
    transition: TVBTD Phê duyệt điều chỉnh
  - name: TVBTD Phê duyệt điều chỉnh
    taskKey: taskPheDuyetDieuchinh
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: '${ .subRequest.tvbtd }'
    taskOutcomes:
      - code: Approve
        name: Đồng ý
        outcomeDecision: APPROVED
        transition: Kết thúc
      - code: Reject
        name: Từ chối
        outcomeDecision: REJECTED
        transition: Kết thúc
      - code: RequestAdjustment
        name: Yêu cầu điều chỉnh
        outcomeDecision: ADJUSTMENT_REQUESTED
        transition: Thực hiện điều chỉnh
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: MergeLoanRequestData
              arguments:
                tvbtd: '${ .subRequest.tvbtd }'
                outcome: '${ $userTask.outcome }'
                editing: '${ $userTask.data.editedRequest.editing }'
                comment: '${ $userTask.data.comment }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .tvbtdResult }'
          - functionRef:
              refName: SetEditorInfo
              arguments:
                editor: '${ "cvqhkh@xbank.com" }'
            actionDataFilter:
              results: '${ .jqResult }'
              toStateData: '${ .subRequest }'
            condition: '${ $userTask.outcome == "ADJUSTMENT_REQUESTED" }'
          - functionRef:
              refName: ExtractEditedValuesJsCode
              arguments:
                request: '${ .request }'
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .data }'
              toStateData: '${ .editedRequest }'
    transition: Kết thúc
  - name: Kết thúc
    type: operation
    actions: []
    stateDataFilter:
      output: >-
        ${ { "tvbtd": .subRequest.tvbtd, "outcome": .tvbtdResult.outcome,
        "comment": .tvbtdResult.comment, "editedRequest": .editedRequest } }
    end: true
functions:
  - name: MergeLoanRequestData
    type: custom
    operation: JqQueryExecute
    metadata:
      jq: >-
        ${ { "tvbtd": .tvbtd, "outcome": .outcome, "editing": .editing,
        "comment": .comment } }
  - name: MergeAdjustmentData
    type: custom
    operation: JqQueryExecute
    metadata:
      jq: '${ .editedRequest }'
  - name: SetEditorInfo
    type: custom
    operation: JqQueryExecute
    metadata:
      jq: '${ { "editor": .editor } }'
  - name: ExtractEditedValuesJsCode
    type: custom
    operation: RunJs
    metadata:
      jsCode: |-
        function getChangedProperties(request, editedRequest) {
          let changedProperties = {};

          for (let key in editedRequest) {
            if (request.hasOwnProperty(key) && editedRequest[key] !== request[key]) {
              changedProperties[key] = editedRequest[key];
            }
          }

          return changedProperties;
        }

        let changedProperties = getChangedProperties(request, editedRequest);
        return changedProperties;
      params: '["request","editedRequest"]'
  - name: NotifyWhenUserTaskCreated
    type: custom
    operation: ExecuteQueryAction
    metadata:
      libraryQueryName: cmd.mail.send_task_created
      libraryQueryRecordId: latest
      params: '["taskName","requestCode","custName"]'
events:
  - name: NewApplicationEvent
    type: com.a4b.xflow.engine.StateData
    source: xflowengine
  - name: UserTaskCreated
    type: com.a4b.xptask.event.post.user_task.UserTaskCreatedEvent
  - name: UserTaskCompleted
    type: com.a4b.xptask.event.post.user_task.UserTaskCompletedEvent
errors:
  - name: Not allowed to transfer money
    code: (.+) not allowed to transfer money
    description: User was not allowed to transfer money
  - name: Underage denied
    code: Transferring money is denied for underage
    description: Transferring money is denied for underage individuals.

Adjustment Sub Workflow

id: XBANK_LOAN_ADJUSTMENT
name: XBANK_LOAN_ADJUSTMENT Workflow
version: '1.0'
metadata:
  startFormKey: 'LCD#661f784162f95774145bdf9f'
timeouts:
  workflowExecTimeout:
    duration: P1D
  actionExecTimeout: PT1M
retries:
  - name: WorkflowRetries
    delay: PT3S
    maxAttempts: 10
start:
  stateName: Khởi tạo
states:
  - name: Khởi tạo
    type: operation
    actions: []
    transition: Check-Adjustment-Request
  - name: Check-Adjustment-Request
    type: switch
    dataConditions:
      - name: S1Option
        condition: '${ .adjRequest.editing == "S1" }'
        transition: Điều chỉnh hồ sơ và đề nghị vay vốn
      - name: S2Option
        condition: '${ .adjRequest.editing == "S2" }'
        transition: Điều chỉnh thẩm định hồ sơ
    defaultCondition:
      transition: Kết thúc
  - name: Điều chỉnh hồ sơ và đề nghị vay vốn
    taskKey: taskCungCapHoSoVaDeNghiVayVon
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: cvqhkh@xbank.com
    taskOutcomes:
      - code: Complete
        name: Gửi duyệt điều chỉnh
        outcomeDecision: COMPLETED
        transition: Kết thúc
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: ExtractEditedValuesJsCode
              arguments:
                request: '${ .request }'
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .data }'
              toStateData: '${ .editedRequest }'
    transition: Kết thúc
  - name: Điều chỉnh thẩm định hồ sơ
    taskKey: taskThucHienThamDinh
    type: usertask
    formKey: 'LCD#661f784162f95774145bdf9f'
    assignee: tdv01@xbank.com
    taskOutcomes:
      - code: Complete
        name: Gửi duyệt điều chỉnh
        outcomeDecision: COMPLETED
        transition: Kết thúc
    taskListeners:
      - taskEvent: created
        actionMode: sequential
        actions:
          - functionRef:
              refName: NotifyWhenUserTaskCreated
              arguments:
                taskName: '${ $state.name }'
                requestCode: '${ .request.code }'
                custName: '${ .request.inputhoten }'
            actionDataFilter:
              useResults: false
      - taskEvent: completed
        actionMode: sequential
        actions:
          - functionRef:
              refName: ExtractEditedValuesJsCode
              arguments:
                request: '${ .request }'
                editedRequest: '${ $userTask.data.editedRequest }'
            actionDataFilter:
              results: '${ .data }'
              toStateData: '${ .editedRequest }'
    transition: Kết thúc
  - name: Kết thúc
    type: operation
    actions: []
    stateDataFilter:
      output: '${ { "editedRequest": .editedRequest } }'
    end: true
functions:
  - name: GetEditedRequest
    type: custom
    operation: JqQueryExecute
    metadata:
      jq: '${ .editedRequest }'
  - name: NotifyWhenUserTaskCreated
    type: custom
    operation: ExecuteQueryAction
    metadata:
      libraryQueryName: cmd.mail.send_task_created
      libraryQueryRecordId: latest
      params: '["taskName","requestCode","custName"]'
  - name: ExtractEditedValuesJsCode
    type: custom
    operation: RunJs
    metadata:
      jsCode: |-
        function getChangedProperties(request, editedRequest) {
          let changedProperties = {};

          for (let key in editedRequest) {
            if (request.hasOwnProperty(key) && editedRequest[key] !== request[key]) {
              changedProperties[key] = editedRequest[key];
            }
          }

          return changedProperties;
        }

        let changedProperties = getChangedProperties(request, editedRequest);
        return changedProperties;
      params: '["request","editedRequest"]'
events:
  - name: NewApplicationEvent
    type: com.a4b.xflow.engine.StateData
    source: xflowengine
  - name: UserTaskCreated
    type: com.a4b.xptask.event.post.user_task.UserTaskCreatedEvent
  - name: UserTaskCompleted
    type: com.a4b.xptask.event.post.user_task.UserTaskCompletedEvent
errors:
  - name: Not allowed to transfer money
    code: (.+) not allowed to transfer money
    description: User was not allowed to transfer money
  - name: Underage denied
    code: Transferring money is denied for underage
    description: Transferring money is denied for underage individuals.
PreviousAdvanced ExamplesNextQMS AP Workflow

Last updated 11 months ago