Review Submitted TYFCB Entries

Site bniconnectglobal.comTask review-submitted-tyfcf-entriesVersion v1Updated Jul 30, 2026Category browser-automation

Find and verify submitted TYFCB entries for a member and amount in BNI Connect Global. This skill was captured from a live agent session on bniconnectglobal.com and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Purpose

Inspect the authenticated BNI Connect Global submitted TYFCB/referral tracking list and locate entries matching a specified member and amount, such as {member-name} and {amount}.

When to Use

Use when the caller needs to review, verify, or identify a potentially erroneous submitted TYFCB entry. This is a read-only workflow and does not submit or modify slips.

Workflow

  1. Navigate directly to https://www.bniconnectglobal.com/login and authenticate with runtime-provided credentials using input[name="username"], input[name="password"], and button[type="submit"]. Wait for the authenticated /web/ portal to load. Never retain or expose credentials or the transient session identifier.
  2. Prefer the direct authenticated route https://www.bniconnectglobal.com/web/secure/referralTrackingSheet for the submitted-entry list. In installations where the review list is exposed only from the dashboard, run the dashboard review opener below on the loaded /web/ page. It finds the visible 審查 control whose surrounding context contains Submit TYFCB or 收到的業務交易金額, clicks it, and waits for the review dialog/list to render.
  3. On the loaded referral-tracking page or review dialog/list, run the extractor below with {member-name} and {amount} substituted in the matching predicates. Report every returned match and flag it for review when both predicates match.
  4. If the caller specifically needs to inspect the dashboard control markup rather than open the review list, run the markup inspector below on the authenticated /web/ page. It returns each visible 審查 control's tag, classes, attributes, truncated outer HTML, and nearby context without clicking or modifying the page.

Dashboard review opener (fallback when no direct list route is available):

(() => {
  const visible = (el) =>
    !!el && !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
  const clean = (s) => (s || "").replace(/\\s+/g, " ").trim();
  const buttons = [...document.querySelectorAll('button,[role="button"]')].filter(
    visible,
  );
  const review = buttons.find((button) => {
    if (clean(button.innerText || button.textContent) !== "審查") return false;
    let p = button;
    for (let depth = 0; depth < 8 && p; depth++, p = p.parentElement) {
      const context = clean(p.innerText || p.textContent);
      if (/Submit TYFCB|收到的業務交易金額/i.test(context)) return true;
    }
    return false;
  });
  if (!review) return { opened: false, reason: "TYFCB review control not found" };
  review.click();
  return { opened: true, label: clean(review.innerText || review.textContent) };
})();

After the opener, wait for a visible div[role="dialog"], the referral-tracking route, or the rendered review rows before extracting. The review dialog can be inspected with the same extractor; it deliberately searches the current DOM rather than assuming a fixed container.

Dashboard review markup inspector (read-only):

(() => {
  const visible = (el) =>
    !!el && !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
  const clean = (s) => (s || "").replace(/\\s+/g, " ").trim();
  const attrs = (el) =>
    Object.fromEntries([...el.attributes].map((a) => [a.name, a.value]));
  const controls = [...document.querySelectorAll('button,[role="button"],a')]
    .filter(visible)
    .filter((el) => clean(el.innerText || el.textContent) === "審查")
    .map((el, index) => {
      let context = clean(el.innerText || el.textContent),
        p = el;
      for (let depth = 0; depth < 8 && p; depth++, p = p.parentElement) {
        const text = clean(p.innerText || p.textContent);
        if (text.length > context.length && text.length <= 500) context = text;
      }
      return {
        index,
        tag: el.tagName.toLowerCase(),
        className: typeof el.className === "string" ? el.className : "",
        attributes: attrs(el),
        outerHTML: el.outerHTML.slice(0, 1200),
        context,
        tyfcbContext: /Submit TYFCB|收到的業務交易金額/i.test(context),
        href: el.getAttribute("href") || null,
      };
    });
  return { count: controls.length, controls };
})();

Extractor (run on the loaded referral tracking sheet or review dialog):

((memberName, amount) => {
  const visible = (el) =>
    !!el && !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
  const clean = (s) => (s || "").replace(/\\s+/g, " ").trim();
  const member = clean(memberName).toLocaleLowerCase();
  const wantedAmount = String(amount).replace(/[^0-9.]/g, "");
  const selectors = [
    "table tbody tr",
    '[role="row"]',
    ".MuiDataGrid-row",
    "li",
    ".card",
    '[class*="card"]',
    '[class*="list-item"]',
  ];
  const nodes = [
    ...new Set(selectors.flatMap((s) => [...document.querySelectorAll(s)])),
  ]
    .filter(visible)
    .map((el, index) => {
      const text = clean(el.innerText || el.textContent);
      const amounts = [
        ...text.matchAll(
          /(?:NT\\s*[$$]|TWD\\s*|\\$)\\s*[0-9][0-9,]*(?:\\.[0-9]+)?/gi,
        ),
      ].map((m) => m[0]);
      const normalizedAmounts = amounts.map((v) => v.replace(/[^0-9.]/g, ""));
      return {
        index,
        text,
        amounts,
        memberMatch: member ? text.toLocaleLowerCase().includes(member) : true,
        amountMatch: wantedAmount ? normalizedAmounts.includes(wantedAmount) : true,
        tag: el.tagName.toLowerCase(),
        className: typeof el.className === "string" ? el.className : "",
      };
    })
    .filter((x) => x.text && x.memberMatch && x.amountMatch);
  const matches = nodes.filter(
    (x, i) => !nodes.some((y, j) => j !== i && y.text === x.text),
  );
  return { query: { memberName, amount }, matchCount: matches.length, matches };
})("{member-name}", "{amount}");

Site-Specific Gotchas

  • The submitted TYFCB list is reachable at the authenticated route /web/secure/referralTrackingSheet; the run reached the review UI from the dashboard instead, using a 審查 control associated with Submit TYFCB and 收到的業務交易金額.
  • The dashboard review control is context-qualified: do not click an arbitrary 審查 button when multiple review controls exist. Require nearby text matching Submit TYFCB or 收到的業務交易金額.
  • The dashboard may expose multiple 審查 elements; the markup inspector reports all visible candidates and identifies those with TYFCB context. Class names and generated component markup may vary, so use the surrounding text qualification rather than a fixed class or DOM index.
  • The review UI may render as a modal (div[role="dialog"]) after a delay; wait for it or the rows to appear before extraction.
  • Authentication redirects to /web/ and may append a transient ;jsessionid=... segment. Preserve the authenticated browser session, but never hard-code or expose the session identifier.
  • The referral tracking page or review dialog may contain mixed table, role-row, Material UI grid, list, or card markup. The extractor checks all of these and returns complete matching row text rather than assuming a fixed column position.
  • Amount formatting can appear as NT$, full-width NT$, TWD, or $, with optional spaces and thousands separators; the extractor normalizes numeric values before comparison.
  • Match by visible member text and normalized amount, not by row ordinal or link position. Names and submitted-entry ordering can change between sessions.
  • Keep usernames, passwords, cookies, and session URLs runtime-only.

Expected Output

A read-only result containing matchCount and each matching submitted-entry row's complete visible text, detected amount strings, member/amount match flags, and DOM context. Use the returned row text to confirm whether the {member-name} entry for {amount} is erroneous. If the dashboard fallback was used, also report that the context-qualified 審查 TYFCB review control was opened and whether a dialog/list rendered. When markup inspection is requested, return the inspector's count and controls array, including exact attributes, truncated markup, nearby context, TYFCB-context qualification, and any link target.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=bniconnectglobal.com&task=review-submitted-tyfcf-entries