whenDone = async (
  viewname,
  table_id,
  fields,
  pk,
  {
    view_when_done,
    formula_destinations,
    destination_type,
    dest_url_formula,
    page_when_done,
    page_group_when_done,
    redirect,
  },
  req,
  res,
  body,
  row0,
  trigger_return,
  check_ajax,
  originalID,
  table
) => {
  const res_redirect = (url) => {
    if (check_ajax && req.xhr && !req.smr)
      res.json({
        view_when_done,
        url_when_done: url,
        ...(trigger_return || {}),
      });
    else res.redirect(url);
  };

  if (redirect) {
    res_redirect(redirect);
    return;
  }
  if (check_ajax && req.xhr && !req.smr && trigger_return?.error) {
    res.json({
      view_when_done,
      ...(trigger_return || {}),
    });
    return;
  }
  let use_view_when_done = view_when_done;
  let row;
  if (
    table &&
    ((originalID && destination_type === "URL formula") ||
      (use_view_when_done || "").includes("."))
  ) {
    // Refetch row as there can be fields not included in form
    const db_row = await table.getRow({ [table.pk_name]: originalID });
    row = { ...db_row, ...row0 };
  } else row = row0;
  if (destination_type === "Back to referer" && body._referer) {
    res_redirect(body._referer);
    return;
  } else if (destination_type === "Page" && page_when_done) {
    res_redirect(`/page/${page_when_done}`);
    return;
  } else if (destination_type === "PageGroup" && page_group_when_done) {
    res_redirect(`/page/${page_group_when_done}`);
    return;
  } else if (destination_type === "URL formula" && dest_url_formula) {
    const url = eval_expression(
      dest_url_formula,
      row,
      "Destination URL formula"
    );
    res_redirect(url);
    return;
  } else if (destination_type !== "View")
    for (const { view, expression } of formula_destinations || []) {
      if (expression) {
        const f = get_expression_function(expression, fields);
        if (f(row)) {
          use_view_when_done = view;
          continue;
        }
      }
    }
  if (!use_view_when_done) {
    res_redirect(`/`);
    return;
  }
  const [viewname_when_done, relation] = use_view_when_done.split(".");
  const nxview = View.findOne({ name: viewname_when_done });
  if (!nxview) {
    req.flash(
      "warning",
      `View "${use_view_when_done}" not found - change "View when done" in "${viewname}" view`
    );
    res_redirect(`/`);
  } else {
    const state_fields = await nxview.get_state_fields();
    let target = `/view/${text(viewname_when_done)}`;
    let query = "";
    if (
      (nxview.table_id === table_id || relation) &&
      state_fields.some((sf) => sf.name === pk.name) &&
      viewname_when_done !== viewname
    ) {
      const get_query = get_view_link_query(fields, nxview);
      query = relation ? `?${pk.name}=${text(row[relation])}` : get_query(row);
    }
    const redirectPath = `${target}${query}`;
    if (!isWeb(req)) {
      res.json({ redirect: `get${redirectPath}` });
    } else {
      res_redirect(redirectPath);
    }
  }
}
take care of final redirect
@param {*} viewname
@param {*} table_id id of the table of the view
@param {*} fields all fields in table
@param {*} pk private key field
@param {*} param4 view_when_done, formula_destinations, destination_type, dest_url_formula, page_when_done, page_group_when_done, redirect
@param {*} req
@param {*} res
@param {*} body reuqest body
@param {*} row row of the form
@returns