web
Está desconectado. Se trata de una versión de solo lectura de la página.
close
  • Massive Close of Tasks in error

    Good morning, I’d like to share a small Node.js script that bulk-closes all the error tasks in a workflow. This saves you from having to open each individual task, close it, and confirm manually. Hope it comes in handy. Have a great day! 


    const axios = require("axios");
    const { wrapper } = require("axios-cookiejar-support");
    const { CookieJar } = require("tough-cookie");
    const qs = require("qs");

    const DOCUWARE_BASE = "https://yourdocuwareurl/DocuWare/Platform";
    const USERNAME = "whatever";
    const PASSWORD = "whatever";
    const HOST_ID = "5e2aff28-c837-4484-acb8-e13fabca410c"; //just any valid guid 
    const workflowGuid= "7aedfb48-8ae5-4f41-aadd-c07724c93d77"; //workflow guid

    axios.defaults.timeout = 30000; // aumenta la tolleranza

    const jar = new CookieJar();

    const client = wrapper(
      axios.create({
        baseURL: DOCUWARE_BASE,
        jar,
        withCredentials: true,
        headers: {
          "Accept": "application/json"
        }
      })
    );

    // ------------------------------------------------------------
    // RETRY AUTOMATICO con attesa progressiva
    // ------------------------------------------------------------
    async function safeRequest(requestFn, maxRetries = 5, delayMs = 2000) {
      for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
          return await requestFn();
        } catch (err) {
          const code = err.code;
          const status = err.response?.status;

          const isNetworkError =
            code === "ETIMEDOUT" ||
            code === "ECONNRESET" ||
            code === "EAI_AGAIN";

          const isServerError =
            status === 500 ||
            status === 502 ||
            status === 503 ||
            status === 504;

          if (isNetworkError || isServerError) {
            console.log(
              `⚠️ attempt ${attempt}/${maxRetries} failed (${code || status}).`
            );
            console.log(`⏳ wait ${delayMs}ms and retry...`);

            await new Promise((resolve) => setTimeout(resolve, delayMs));

            delayMs = Math.floor(delayMs * 1.5);
            continue;
          }
          throw err;
        }
      }

      throw new Error("❌ Too many attempts failed.");
    }

    // ------------------------------------------------------------
    // LOGIN
    // ------------------------------------------------------------
    async function docuwareLogin() {
      const formBody = qs.stringify({
        UserName: USERNAME,
        Password: PASSWORD,
        Organization: "",
        RedirectToMyselfInCaseOfError: false,
        RememberMe: false,
        HostID: HOST_ID,
        LicenseType: "PlatformService"
      });

      try {
        await safeRequest(() =>
          client.post("/Account/Logon", formBody, {
            headers: {
              "Content-Type": "application/x-www-form-urlencoded",
              "Accept": "application/json"
            }
          })
        );

        console.log("🔐 Login OK");
      } catch (err) {
        console.log("❌ Login failed:", err.response?.data || err.message);
        process.exit(1);
      }
    }

    // ------------------------------------------------------------
    // LOGOUT
    // ------------------------------------------------------------
    async function logout() {
      try {
        await safeRequest(() => client.get("/Account/Logoff"));
        console.log("🚪 Logout OK");
      } catch (err) {
        console.log("⚠️ Logout failed:", err.response?.data || err.message);
      }
    }

    // ------------------------------------------------------------
    // get 200 TASK
    // ------------------------------------------------------------
    async function getNextTasksPage(url) {
      const res = await safeRequest(() => client.get(url));

      const tasks = res.data.Task || [];
      const nextLink = res.data.Links?.find((l) => l.rel === "next");

      let nextUrl = null;
      if (nextLink) {
        nextUrl = nextLink.href
          .replace("/DocuWare/Platform", "")
          .replace("count=50", "count=200");
      }

      return { tasks, nextUrl };
    }

    // ------------------------------------------------------------
    // PROCESS TASK
    // ------------------------------------------------------------
    async function processTask(task, workflowGuid) {
      console.log(`\n➡️ Task: ${task.Id} — ${task.DisplayName}`);

      const instanceRes = await safeRequest(() =>
        client.get(
          `/Workflow/Workflows/${workflowGuid}/Instances/${task.InstanceId}/Tasks/${task.Id}`
        )
      );

      //console.log("   Stato:", instanceRes.data.State);
      console.log("   ⛔ close task…");

      let linkCloseAction =
        instanceRes.data.Decisions[2].DecisionOperations.BaseDecisionOperations
          .Links[0].href;

      linkCloseAction = linkCloseAction.replace("/DocuWare/Platform", "");

      const confirmscreen = await safeRequest(() => client.get(linkCloseAction));

      let confirmAction =
        confirmscreen.data.DecisionOperations.ExtendedDecisionOperations.Links[0]
          .href;

      confirmAction = confirmAction.replace("/DocuWare/Platform", "");

      const jsonBody = { ConfirmedFields: [] };

      await safeRequest(() =>
        client.post(confirmAction, jsonBody, {
          headers: {
            "Content-Type": "application/json",
            "Accept": "application/json",
            "X-Requested-With": "XMLHttpRequest"
          }
        })
      );

      console.log("   ✅ Task chiusa");
    }

    async function processAllTasks(workflowGuid) {
      let nextUrl = `/Workflow/Workflows/${workflowGuid}/Tasks?count=200`;
      let page = 1;

      while (nextUrl) {
        console.log(`\n📦 Pagina ${page}: load tasks block…`);

        const { tasks, nextUrl: newNextUrl } = await getNextTasksPage(nextUrl);

        console.log(`➡️ ${tasks.length} task trovate`);

        for (const task of tasks) {
          await processTask(task, workflowGuid);
        }

        nextUrl = newNextUrl;
        page++;
      }

      console.log("\n🎉 Task completed!");
    }

    // ------------------------------------------------------------
    // MAIN
    // ------------------------------------------------------------
    async function main() {
      await docuwareLogin();

      try {
        await processAllTasks(workflowGuid);
      } catch (err) {
        console.error("\n❌ ERRORE GENERALE:", err.response?.data || err.message);
      } finally {
        await logout();
      }
    }

    main();
  • External web form - Task Id

    Hi,
    I find very poor that there is no way to use a form in the steps of a workflow and user has to fill the information in the decision area that give very limited possibility to show information , rich fields etc. but hopefully this is something that will come soon with a new version.
    In the while I would like to use external customer web page as a workaround, at least for some activity where the answer require full screen , list of values and a nice form to fill relying on the docuware workflow engine.

    My idea is to have a link in the decision area that call my page so the user open the external link , fill the form and via api I can interact with Docuware decision send data and even save document .
    What I need in my external link is the Instance ID of the workflow which I cannot see as an available System Field in the workflow designer, am I missing something ? 
    How can I know , without looping on all the active instances , what is the workflow and activity the user has to work on ?

    I can assign via api a unique custom GuiId to the workflow and I can use this as a key field for the workflow, but is there any way to query the workflow engine via api and filter based on the value of a variable to get the instance reference ?

    Thanks
    Alberto