0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GASで確認チェックの型と入力規則を検査する:AI返信前に保留へ戻す

0
Posted at

GoogleスプレッドシートでAI返信案を確認する時、チェックボックスを1つ置くだけで運用を始められます。しかし、GASが表示文字列のTRUEを見て「確認済み」と判定すると、文字列・数式・別の入力規則が混ざった行まで通ることがあります。

この記事では、チェック欄を承認の証明ではなく、形式を検査する入口として扱います。GASで実値の型、数式の有無、標準チェックボックスの入力規則を読み取り、条件外なら送信処理へ渡さず保留へ戻します。

AI API、メール送信、CRM更新、チェック欄への書き込みは実装しません。架空の値とテスト用シートだけを対象にします。

AI返信案を人間確認へ戻すレビュー境界

この記事で作る検査

対象は、問い合わせレビュー台帳の1セルです。合格条件を次の3つに固定します。

  1. getValue()の結果がbooleanである
  2. 数式が入っていない
  3. 標準のチェックボックス入力規則である

結果は次のいずれかです。

結果 意味 後続処理
REVIEW_MARKED 標準形式でtrue 確認者・本文版を別記録と照合
REVIEW_UNMARKED 標準形式でfalse 人間レビューへ戻す
HOLD_FORMULA 数式がある 数式の意図を確認
HOLD_RULE 入力規則が標準でない 入力規則の変更を確認
HOLD_VALUE_TYPE 実値がbooleanでない 転記・空欄・文字列を確認

REVIEW_MARKEDでも、送信可能・承認済み・確認者本人である、とは判定しません。

1. 表示文字列と実値を分ける

getDisplayValue()は画面に表示された文字列を返します。一方、getValue()はセルの実値を返します。JavaScriptでは、空でない文字列はBoolean()でtrueになるため、次の変換は危険です。

Boolean('TRUE');  // true
Boolean('FALSE'); // true
Boolean('');      // false

表示が同じでも、標準チェックボックスのboolean、手入力した文字列、数式の計算結果は意味が違います。まず値をbooleanへ変換せず、型を検査します。

2. 外部接続のない判定関数を作る

Apps ScriptのV8ランタイムで、次の関数を作ります。シートやAIへ接続せず、引数の契約だけを判定します。

function inspectReviewMark(value, formula, isStandardCheckbox) {
  if (typeof formula !== 'string' ||
      typeof isStandardCheckbox !== 'boolean') {
    throw new Error('CHECKBOX_METADATA_INVALID');
  }

  if (formula !== '') return { status: 'HOLD_FORMULA' };
  if (!isStandardCheckbox) return { status: 'HOLD_RULE' };
  if (typeof value !== 'boolean') return { status: 'HOLD_VALUE_TYPE' };

  // 形式だけを返す。承認・送信可否は返さない。
  return {
    status: value === true ? 'REVIEW_MARKED' : 'REVIEW_UNMARKED',
  };
}

不正なメタデータはfalseへ丸めません。通信・権限・取得処理の異常と、未チェックを混ぜないためです。判定の優先順位は、数式、入力規則、実値の順にしています。

3. テスト用セルのメタデータを読む

本番台帳ではなく、テスト用スプレッドシートにReviewSandboxシートを作ります。B2へ標準のチェックボックスを挿入し、A2には架空のINQ-001を置きます。

function readReviewMarkCell(cell) {
  if (cell.getNumRows() !== 1 || cell.getNumColumns() !== 1) {
    throw new Error('ONE_CELL_REQUIRED');
  }

  // 同じ実行環境で標準規則を作り、引数も含めて比較する。
  const standard = SpreadsheetApp.newDataValidation()
    .requireCheckbox()
    .build();
  const rule = cell.getDataValidation();
  const isStandardCheckbox = rule !== null &&
    rule.getCriteriaType() === SpreadsheetApp.DataValidationCriteria.CHECKBOX &&
    JSON.stringify(rule.getCriteriaValues()) ===
      JSON.stringify(standard.getCriteriaValues());

  return inspectReviewMark(
    cell.getValue(), cell.getFormula(), isStandardCheckbox
  );
}

requireCheckbox()に引数を渡すと、yes/noなどのカスタム値を作れます。今回はカスタム値を無条件にbooleanへ読み替えません。標準規則と違えばHOLD_RULEにし、運用仕様を決めてから別の契約として実装します。

なお、値・数式・入力規則の読み取りは複数の呼び出しです。同時編集を止めるトランザクションではありません。送信直前に、案件ID・本文の版・宛先を別の確認記録と照合してください。

4. 架空の入力で境界を固定する

Googleサービスを呼ばないテストを先に実行します。

function testReviewMark() {
  const cases = [
    [true, '', true, 'REVIEW_MARKED'],
    [false, '', true, 'REVIEW_UNMARKED'],
    ['TRUE', '', true, 'HOLD_VALUE_TYPE'],
    ['FALSE', '', true, 'HOLD_VALUE_TYPE'],
    ['', '', true, 'HOLD_VALUE_TYPE'],
    [1, '', true, 'HOLD_VALUE_TYPE'],
    [true, '=TRUE()', true, 'HOLD_FORMULA'],
    [true, '', false, 'HOLD_RULE'],
  ];

  cases.forEach(([value, formula, rule, expected], index) => {
    const actual = inspectReviewMark(value, formula, rule).status;
    if (actual !== expected) {
      throw new Error('TEST_FAILED_' + index);
    }
  });
  console.log('PASS_' + cases.length);
}

最低限、次のケースを確認します。

  • チェックを付ける・外す:REVIEW_MARKED / REVIEW_UNMARKED
  • 文字列のTRUE・FALSE・空欄・数値:HOLD_VALUE_TYPE
  • =TRUE():HOLD_FORMULA
  • 入力規則を外す、またはカスタム値に変える:HOLD_RULE
  • 複数セルを渡す:ONE_CELL_REQUIRED
  • シート読み取り例外:例外を未チェックへ置き換えない

本番データや顧客本文をテスト値にコピーしないでください。

5. チェック印と承認記録を分ける

形式検査に合格しても、次の事実は分かりません。

  • 誰がチェックを付けたか
  • どの案件ID・本文版・宛先を見たか
  • FAQや料金、納期が確認後に変わっていないか
  • その人に送信権限があるか

そのため、レビュー台帳では少なくとも次の列を分けます。

inquiry_id, reply_version, review_mark, reviewer, reviewed_at,
evidence_version, approval_state, hold_reason

review_markがREVIEW_MARKEDになっても、approval_stateを自動でAPPROVEDにしません。確認者・本文版・根拠版を照合した人が、別途、送信判断を記録します。

運用チェックリスト

  • 表示文字列ではなくgetValue()の型を検査している
  • 文字列FALSEや空欄を未チェックへ自動変換していない
  • 数式・入力規則変更・読み取り例外の戻し先がある
  • 標準チェックボックスとカスタム値の契約を分けている
  • 形式合格を承認・送信権限の証明にしていない
  • 案件ID・本文版・確認者をチェック印と別に記録している
  • AIや転記処理がチェック欄を書き換えない経路を確認している
  • テスト用シートで正常系と失敗系を再現している

まとめ

チェックボックスは便利ですが、表示されたTRUEだけでは、人が対象の返信案を確認したことを表せません。GASでは、実値・数式・入力規則を検査し、形式外の行を保留へ戻すところまでを自動化します。

その先の承認は、案件ID、本文の版、根拠、確認者、送信権限を照合する別の業務ルールです。Miraigentでは、AIの下書きを増やす前に、確認できない時に誰へ戻るか、どの記録を正本にするかを一つの業務で整理します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?