本開発(Phase-2)提案書:Excel 一元化・統合営業台帳
| 項目 | 内容 |
|---|---|
| 宛先 | メルテックス株式会社 DX推進・営業ご担当者様 |
| 案件 | ReadyCrew 4396751「Excelのシステム化」 |
| 版 | 0.1(2026年9月25日・先方確認前のドラフト) |
| 前提資料 | ReadyCrew 案件詳細(リポジトリ外の資料)、Phase-1 の実在/モック境界、目標アーキテクチャ補足 |
| 公開デモ | https://meltex-excel-phase1.s-sato.workers.dev(架空データ・デモ認証。本番には使わない) |
| 図の編集用ファイル | PHASE2_ARCHITECTURE.drawio(draw.io / diagrams.net で開く) |
金額はすべて税抜の概算です。Cloudflare の料金は本書作成時点で把握している公開価格を元に、1ドル=150円で換算しています。提出前に最新の料金表で再確認します。人日単価は後述の前提によります。
0. 要約
- 主案(A案)は初期 90万円+変動枠上限10万円(最大100万円)、月額 約7万円です。 部長決裁の範囲(初期100万円以内)と月額10万円以内に収めています。
- Phase-1 で作った Workers+D1 の台帳、CSV 取込、同期履歴、SFA 補完、月次出力をそのまま土台にします。作り直しはしません。本開発で足すのは次の4つです。
- デモ認証を撤去し、Cloudflare Access と Entra ID のシングルサインオンに置き換える
- 3系統のモックアダプタを実 API 版に差し替える(Dynamics 365、Teams、Knowledge Suite)
- Excel ファイルを直接取り込み、原本を R2 に保存する
- 閲覧ログと定期実行を追加する
- 外部連携は読み取りを主案にします。Teams への書き戻し、AI、承認フロー、過去データの台帳化の拡大は、100万円を超えるオプション(B案)として分けました。B案は社長決裁になるため可能性は低いと見ています。本番運用の結果を見てから、次年度予算で要否を判断していただく想定です。
- 15年分・2TB の過去データは、原本のまま R2 に保管して目録から検索できるようにします。D1 に台帳化するのは直近3年度だけです。
- 金額が確定するかどうかは、先方の API 仕様にかかっています。Dynamics 365 の製品種別、Teams 上の見通しファイルの形式と置き場所、Knowledge Suite の API 可否の3点です。確認事項は §11 に並べました。
1. 現状整理:Phase-1 で実証できたこと / まだモックのこと
Phase-1 は Cloudflare Workers(Hono)+ D1 の単一 Worker 構成です。自動テストは Vitest と @cloudflare/vitest-pool-workers(Miniflare 上の D1)で動いていて、ユニット6件と API 7件がすべて成功しています。公開デモでは 2026年9月25日に GET / と GET /api/health が 200、閲覧者のログインも 200 を返すことを確認しました。
1.1 実証できたこと(本開発でそのまま使う)
| 実証できたこと | コード根拠 | テスト |
|---|---|---|
| 6領域の統合台帳(顧客、製品、売上計画、月次見通し、案件、前月売上) | migrations/0001_init.sql の customers(L9)、products(L22)、sales_plans(L34)、forecasts(L47)、deals(L62)、prior_month_sales(L84) |
test/api.test.ts の unified dashboard(L44) |
| 顧客の担当者名・エリア・所属部署の一覧と検索 | customers.contact_name / area / department(0001 L9–L20)、src/queries.ts の searchAll |
画面確認済み |
| CSV 取込(列の自動対応と手動変更、必須・型・マスタ存在の検証、重複更新、エラー一覧) | src/templates.ts の TEMPLATES(L18)と autoMap(L99)、src/import-service.ts の commitImport(L137)、import_jobs / import_row_errors(0001 L98 / L112) |
test/api.test.ts の csv import(L65) |
| 月別ファイルの年度統合(11月決算) | src/fiscal.ts の fiscalYearOf(L2)、売上計画のキー「年月+顧客+製品+担当」 |
test/unit.test.ts(L8) |
| 同期履歴、失敗の記録、同じ操作での再実行 | src/adapters.ts の executeSync(L204–L254)、sync_runs(0001 L120) |
test/api.test.ts の mock sync(L103) |
| 外部 ID による冪等な取り込み | prior_month_sales.dynamics_id UNIQUE(0001 L93)、deals.external_id UNIQUE(L64)、forecasts.teams_item_id(L56) |
2回目の取得で新規0件(api.test.ts L103) |
| SFA 未入力・低精度の一覧と補完の記録。補完済みは再取込で上書きしない | src/quality.ts の assessDeal(L13)、src/app.ts の補完 API(L194)、src/adapters.ts の補完済みスキップ(L152) |
test/api.test.ts(L133) |
| 計画と見通しの乖離検知 | src/quality.ts の findAnomalies(L47、閾値30%は L45) |
test/unit.test.ts(L52) |
| 月次まとめの CSV / Excel 出力 | src/queries.ts の buildReport(L144)、src/report.ts の reportToExcelXml(L83)、src/app.ts(L321) |
api.test.ts(L182)、unit.test.ts(L62) |
| 管理者 / 閲覧者の権限分離 | src/auth.ts の requireUser(L68)と requireAdmin(L74)。更新系 API はすべて requireAdmin |
test/api.test.ts の auth and roles(L29) |
| 更新操作の監査記録 | audit_logs(0001 L143)。取込、同期、補完、見通し修正で記録 |
api.test.ts 経由 |
ここで分かったのは、台帳の形と画面の使い方は D1 だけで十分に表現できるということです。連携先の違いは IntegrationAdapter の中に閉じ込められます。本開発で API ルートや画面をほとんど変えずに済むのはこのためです。
1.2 まだモックのこと、本番前に直すこと
| 項目 | 現状(コード根拠) | 本開発での扱い |
|---|---|---|
| Dynamics 365 | dynamics365Adapter(src/adapters.ts L27)が src/demo-data.ts の架空伝票を返す |
実 API アダプタに差し替え(§4.1) |
| Teams | teamsAdapter(L74)の取得は固定データ。書き戻しは mock_external_records(L123、0001 L134)への保存だけ |
読み取りを実装。書き戻しは B案(§4.2) |
| Knowledge Suite | knowledgeSuiteAdapter(L143)が架空案件を返す |
API または CSV 定期取込(§4.3) |
| 障害の再現 | simulateFailure(L210、L222) |
開発環境だけに残す |
| 認証 | 固定ユーザーと平文パスワード(src/demo-data.ts L149–L150、users.password は 0001 L6)。HMAC 署名 Cookie(src/auth.ts L19–L38)。署名鍵は wrangler.toml の [vars](L9)と src/app.ts(L22、L38)に直書き |
撤去して Access+JWT 検証に置き換え(§6) |
| 自動シード | 全 API リクエストで ensureSeed を呼ぶ(src/app.ts L20)。/api/admin/reset-demo(L377)で全消去できる |
本番では撤去 |
| 取込形式 | CSV テキストのみ(README)。1行ごとにマスタを照会する(src/import-service.ts L151–L154) |
.xlsx の直接取込、マスタの一括照会、原本の R2 保存 |
| 定期実行 | 手動の POST /api/sync/:system/:direction(src/app.ts L300)だけ |
Cron Triggers を追加 |
| 自動再試行 | なし。失敗を記録するだけ(src/adapters.ts L249–L252) |
429 / 5xx は再試行し、次の定期実行でも自動で再実行 |
| 閲覧ログ | audit_logs は更新系だけ |
access_logs を追加 |
| 月次 Excel | SpreadsheetML(XML)を .xls 拡張子で出力(src/report.ts L83)。Excel が形式不一致の警告を出す |
本物の .xlsx を生成 |
| 担当者 | owner_name が各テーブルで自由入力の文字列 |
社員マスタと外部 ID の対応表 |
| 前月売上のキー | 伝票単位の ID(demo-data.ts) |
明細行単位のキー(1伝票に複数製品があるため) |
| AI | 語句ルールによる下調べ(src/queries.ts L197、src/app.ts L363) |
任意(§7) |
| デプロイ設定 | wrangler.toml の database_id(L15)はプレースホルダ。公開デモは別環境からデプロイ |
環境ごとに D1 / R2 / Access を分ける |
2. 本開発のゴールとスコープ
2.1 ゴール
要件の「目的」と「達成すべきゴール」を、検収できる形に言い換えました。
- 10〜20個の Excel に散っている6領域のデータを、1つの画面で期間・顧客・製品・担当者から探せる
- 月初の前月売上取込(Dynamics 365)、Teams の見通しの取得、SFA の全案件チェック(月2回)に手作業が要らない。担当者は確認と補完だけをする
- 管理者でなくても、閲覧者として必要な数字と月次資料を自分で見られる
- 個人情報を含むので、誰が何を見たかを後から追える
効果の目安として、SFA まとめ資料の更新(月2回×2日)は「確認のみ・月1日程度」まで減らすことを目標にします。年間では約36人日の削減です。月初の資料作成と Teams からのダウンロード作業は、ヒアリングで現状を測ってから目標に加えます。
2.2 スコープ(主案 A)
| 区分 | 内容 |
|---|---|
| Must(主案に含む) | ① Cloudflare Access+Entra ID の SSO、ロール表、デモ認証の撤去 ② Dynamics 365 の前月売上の取得(日次と月初確定、再実行) ③ Teams 上の月次見通しの読み取り(業務時間中の定期取得) ④ Knowledge Suite の案件取込(API があれば日次、なければ CSV を月2回)と、既存の補完ワークフロー ⑤ .xlsx の直接取込、取込プロファイルの保存、原本の R2 保存 ⑥ 月次資料の定期生成(月初と月2回のまとめ日、R2 保存、.xlsx) ⑦ 直近3年度の台帳化と、過去分(2TB 級)の R2 格納と目録 ⑧ 閲覧ログ、顧客担当者名のマスキング(閲覧者向け)、保持設定 ⑨ 本番・検証の2環境、運用手順書、操作説明会1回 |
| Should(B案、または次年度) | Teams への書き戻し(Microsoft Lists への移行を含む)、Workers AI による月次コメントの下書きと自然言語検索、補完と見通し修正の承認フロー、台帳化の範囲を過去5年度に拡大、取込プロファイル11本目以降の作成代行、過去ファイル目録の全文検索 |
| Won't(本開発ではやらない) | Dynamics 365 / Knowledge Suite への書き戻し(代わりに「SFA 入力依頼リスト」を CSV で出す)、2TB 全量の中身の解析と台帳化、リアルタイム双方向同期、売上予測モデル、BI ツール並みの自由集計、ネイティブアプリ、Excel マクロ互換、Enterprise 契約が要る機能(Data Localization Suite など) |
2.3 受入基準(主案)
- 11月初と12月初の2回、月初処理(前月売上の取得と月次資料の生成)が手作業なしで完了し、Dynamics 365 側の合計と一致する
- Teams の見通しの変更が1時間以内に台帳へ反映される
- Knowledge Suite の案件が、未入力・低精度の一覧と補完記録に反映される。補完済みは次の取込で上書きされない
- 先方の Excel サンプル10本が取込プロファイルで取り込め、エラー行が一覧で確認できる
- Entra ID に登録された利用者以外は画面にも API にも到達できない。閲覧者は更新できない
- 閲覧とダウンロードの記録が管理画面で確認できる
3. 目標アーキテクチャ(Cloudflare 中心)
図と詳細は PHASE2_ARCHITECTURE.md にまとめました。要点は次のとおりです。
| 構成要素 | 役割 | Phase-1 からの変化 |
|---|---|---|
| Workers(1本、Hono) | API と画面の配信、Cron Triggers による定期同期 | src/index.ts に scheduled ハンドラを追加。ルートはそのまま |
| D1 | 台帳の正本(直近3年度)、マスタ、対応表、同期履歴、取込履歴、監査・閲覧ログ(直近13か月) | マイグレーション 0002 で表を追加(§3.2)。容量は1DB最大10GBに対して1GB未満の見込み |
| R2 | Excel 原本、月次資料、過去15年分のアーカイブ、ログの長期保管 | 新規。転送料金がかからないので、原本のダウンロードも費用が増えない |
| Cloudflare Access | Entra ID の SSO、MFA(Entra 側の条件付きアクセス)、利用者の限定 | 新規。Zero Trust Free は50名まで無料なので約20名なら0円 |
| Workers シークレット | Entra のクライアントシークレット、Knowledge Suite の API キー | 新規。wrangler.toml の [vars] にあった署名鍵は廃止 |
| Workers AI | 任意(B案) | /api/ai/ask の入出力は Phase-1 のまま |
D1 を正本に選んだ理由。 利用者は約20名で、書き込みは取込と同期がほとんどです。D1 の上限(1DB 10GB、単一リージョンへの書き込み)で困る量ではありません。Postgres+Hyperdrive は、台帳が数GBを超える、重い集計が常時必要になる、といった要件が出たときに初めて検討します。月額の固定費が増えるため、主案には入れていません。
Power Platform を主案にしない理由。 先方は Microsoft 製品を使っているので、Power Apps と Dataverse は自然な選択肢です。ただ、Premium ライセンスは公開価格で1ユーザー月額20ドル前後で、20名では月6万円程度になり、月額10万円の予算の大半を占めます。Knowledge Suite の標準コネクタも見当たりません。プロトタイプがすでに動いていることも合わせ、Cloudflare を主案にしました。
3.1 環境
| 環境 | 用途 | D1 / R2 | 認証 |
|---|---|---|---|
| ローカル | 開発と自動テスト | Miniflare | テスト用の固定ユーザー(テストコード内だけ) |
| 検証(staging) | 先方の試用、受入試験 | 本番とは別の D1 / R2。架空データか、マスキング済みデータ | Access(先方の検証担当者のみ) |
| 本番 | 約20名の運用 | 本番の D1 / R2(位置ヒントは apac) |
Access+Entra ID |
Cloudflare アカウントは先方名義にし、受託者はメンバーとして参加する形を提案します。公開デモは受託者側のアカウントにあるので、実データを扱う前に停止するか Access で保護します。workers.dev のままでも Access はかけられます。独自ドメインは任意です。
3.2 スキーマの追加(マイグレーション 0002 の方針)
users:password列を削除し、メールアドレスを Access の ID と突き合わせるキーにする。activeとlast_seen_atを追加employees:社員マスタ。owner_nameの自由入力をやめ、Dynamics 365 と Knowledge Suite の担当者 ID を持つmaster_mappings:外部コードと台帳コードの対応表(システム、種別、外部キー、台帳 ID)。対応が付かない行はデータ品質の一覧に出すimport_profiles:ファイルごとの列対応、シート名、見出し行の位置import_jobs:r2_key、sha256、source_type(xlsx / csv)を追加sync_runs:trigger(cron / manual)、attempt、retry_of、error_codeを追加。差分取得の位置はsync_cursorsに持つaccess_logs:閲覧・ダウンロードの記録archive_files:R2 に置いた過去ファイルの目録(年度、種別、元のパス、サイズ、ハッシュ)report_files:定期生成した月次資料の保存先settings:乖離の閾値(現在はsrc/quality.tsL45 の30%固定)や低精度判定の金額(L23 の10万円固定)を管理画面から変えられるようにするmock_external_records:本番では使わない。テスト用のフィクスチャに移す
4. 外部連携の本番化計画
アダプタの形(src/adapters.ts L19–L23 の IntegrationAdapter:pull と任意の push)はそのまま残し、中身だけを実 API 版に差し替えます。環境変数から「実 API 版」と「モック版」を選ぶファクトリを置き、テストと開発ではモックを使い続けます。実 API 版で共通に持つのは次の4つです。
- トークン取得:Entra ID のクライアント資格情報フロー。有効期限内はキャッシュする
- HTTP 再試行:429 と 5xx は
Retry-Afterに従い、1回の実行の中で最大3回まで再試行する - 対応表:
master_mappingsで外部コードを台帳コードに変換する。変換できない行は取り込まずに品質一覧へ出す - 冪等性:外部 ID で upsert する。同じ実行を何度繰り返しても結果が変わらない
失敗した実行は sync_runs に残し、次の定期実行で自動的にやり直します。管理者は外部連携画面の「取得」ボタン(既存の POST /api/sync/:system/:direction)で即時に再実行できます。失敗が2回続いたら管理者に通知します。通知手段は、管理者へのメールか Teams のワークフロー(Webhook 受信)のどちらかで、テナントのポリシーを確認してから決めます。
4.1 Microsoft Dynamics 365(前月売上)
| 項目 | 方針 |
|---|---|
| 接続先 | ユーザー合意の方針どおり Dataverse Web API(https://{組織}.crm7.dynamics.com/api/data/v9.2/、日本リージョン)を主想定にする。先方が Business Central の場合は BC API v2.0 の salesInvoices / salesInvoiceLines、Finance & Operations の場合は OData データエンティティに切り替える。製品種別の確認が最初の作業 |
| 必要な資格情報 | Entra テナント ID、アプリ登録のクライアント ID とシークレット(または証明書)、環境 URL。Dataverse には「アプリケーションユーザー」を作り、売上系テーブルの読み取りだけを許すセキュリティロールを割り当てる |
| 同期頻度 | 毎日 06:00(JST)に前月分と当月分を差分取得する。月初の確定日(先方に確認)に前月分を確定扱いにし、月次資料を生成する。Cron は UTC 指定なので 21:00 UTC に設定する |
| 失敗時 | 401 はシークレット期限切れとして即時通知する。429 と 5xx は再試行する。ページ単位でまとめて書き込み、途中で失敗しても再実行で揃う |
| 対応表 | 必要。取引先番号から顧客コード、品目番号から製品コード、営業担当から社員へ変換する。初回は先方の Excel と照合して作る(§5) |
| Phase-1 からの変更 | prior_month_sales のキーを伝票単位から明細行単位にする(伝票番号+行番号) |
4.2 Microsoft Teams(月次見通し)
Teams のチャネルにあるファイルの実体は SharePoint のドキュメントライブラリに保存されているので、Microsoft Graph から読みます。
| 項目 | 方針 |
|---|---|
| 接続先 | 見通しが Excel の場合は GET /sites/{site-id}/drive/items/{item-id}/content でファイルを取得し、Worker で解析する。eTag が変わっていなければ解析を省略する。Microsoft Lists の場合は GET /sites/{site-id}/lists/{list-id}/items?expand=fields の差分取得を使う |
| 必要な資格情報 | Entra アプリ登録と、アプリケーション権限の Sites.Selected。テナント管理者に対象サイトだけへの権限付与をお願いする(Sites.ReadWrite.All のような全体権限は求めない)。あわせてサイト ID と、ファイル ID またはリスト ID が必要 |
| 同期頻度 | 平日の業務時間中は1時間ごと、ほかに手動取得 |
| 書き戻し | 主案では読み取りだけにする。担当者が同時に編集している Excel をシステムが上書きすると、編集内容を消す恐れがあるため。書き戻しは B案で、行単位で安全に更新できる Microsoft Lists への移行を前提にする。Excel のままで書き戻す場合は、Graph のブック API がアプリ権限で使えるかを検証環境で確かめてから判断する |
| 対応表 | 必要。見通しシートは顧客名や担当者名で書かれていることが多いため、名前からコードへの対応を作る |
| Phase-1 からの変更 | teamsAdapter.push(src/adapters.ts L112–L140)は本番では無効にする。見通しの修正 API(src/app.ts L150)は、台帳側の補正として残す |
確認が要ること。 見通しの正本を Teams に置き続けるのか、台帳に移すのかによって B案の中身が変わります。第1回の打ち合わせで決めたい事項です。
4.3 Knowledge Suite(SFA 案件)
| 項目 | 方針 |
|---|---|
| 接続先 | API が契約プランで使えるなら、API で案件を取得する。使えない場合は、管理者が CSV をエクスポートし、既存の取込画面(src/templates.ts の deals テンプレート)から月2回取り込む。どちらにするかは先方の契約内容で決まる |
| 必要な資格情報 | API キーまたはトークン(読み取り専用が望ましい)。CSV 運用なら不要 |
| 同期頻度 | API なら毎日 02:00(JST)。CSV なら、まとめ資料を更新する月2回 |
| 失敗時 | API の場合は §4 冒頭の共通方針に従う。CSV の場合は、取込エラーを一覧で見て、修正したファイルを再取込する(Phase-1 と同じ) |
| 対応表 | 必要。顧客、担当者、ステージ名を正規化する。ステージの一覧は settings で管理する |
| 補完 | Phase-1 のワークフローをそのまま使う(src/app.ts L194、src/adapters.ts L152)。SFA への書き戻しはせず、「SFA 入力依頼リスト」を CSV で出して担当者に入力を頼む |
5. データ移行
5.1 方針
- 台帳化(D1)するのは直近3年度(FY2025〜FY2027)だけです。月次の計画・見通し・実績で数十万行、容量は1GB未満と見込んでいます。
- 15年分・2TB 級の過去データは原本のまま R2 に置き、目録(
archive_files)から年度・種別・ファイル名で探してダウンロードできるようにします。中身を解析して台帳に入れるのは、必要な年度が決まった時点で B案か個別見積とします。 - 台帳化は、先方と受託者で作業を分担します。
5.2 手順
- 棚卸し(先方):10〜20個のファイルを、こちらが用意する一覧表に記入していただきます。記入項目はファイル名、用途、更新頻度、担当、行数、個人情報の有無です。
- 分類(共同):6領域に入れるファイルと、原本保管だけのファイルに分けます。
- 取込プロファイル(受託者):主案では10本まで作ります。11本目以降は、Phase-1 からある列対応の画面で管理者が自分で対応を付けられます。見出しの別名は
src/templates.tsに追加していけます。 - 月別ファイルの統合:売上計画は「年月+顧客+製品+担当」のキーで upsert し、年度は
fiscalYearOfで付けます。1年分を別の Excel にまとめ直す作業は要らなくなります。 - 名寄せ:「(株)」と「株式会社」のような表記ゆれは
master_mappingsで吸収します。対応が付かない行はimport_row_errorsに残り、先方で直して再取込できます。取込は冪等です。 - 並行稼働:11月と12月の月末をまたいで、Excel と台帳を並行して運用します。そのうえで Excel の更新を止める日を決めます。
5.3 2TB の格納
| 項目 | 内容 |
|---|---|
| 置き場所 | R2 の archive/{年度}/{種別}/{元のファイル名}。元のフォルダ構成は目録に記録する |
| アップロード | S3 互換 API で rclone などを使う。対象バケットだけに使える一時的な資格情報を発行し、作業後に失効させる。実効100Mbpsなら約2日、500Mbpsなら約9時間。夜間と週末に分けて実施する |
| 検証 | 件数、サイズ、SHA-256 を元の保管場所と突き合わせ、報告書にまとめる |
| 費用 | Standard クラスで2TB、約4,500円/月。直近3年度より古いものをライフサイクルで Infrequent Access に移せば約3,000円/月になるが、取り出しに料金がかかるので、利用頻度を聞いてから決める |
| 削除防止 | 原本はアプリから削除できないようにする。R2 のバケットロック(保持ルール)の利用可否も確認する |
| 確認が要ること | 2TB の中身(Excel だけか、PDF や画像も含むか)、今の保管場所(ファイルサーバーか SharePoint か)、アップロードに使える回線 |
6. セキュリティ・個人情報・監査
6.1 デモ認証は本番に残さない
Phase-1 の認証はプロトタイプ専用です。本番のリリース前に、次をすべて撤去または置換します。
| 撤去・置換する対象 | 場所 |
|---|---|
| 固定ユーザーと平文パスワード | src/demo-data.ts L149–L150、users.password(0001 L6) |
| ログイン API | src/app.ts L29(/api/auth/login) |
| HMAC 署名 Cookie のセッション | src/auth.ts L19–L38 |
| リポジトリ内の署名鍵と直書きの既定値 | wrangler.toml L9、src/app.ts L22 と L38 |
| 全リクエストでの自動シード | src/app.ts L20 |
| デモ初期化 API | src/app.ts L377 |
| 障害再現フラグ | src/adapters.ts L210、L222(開発環境だけで有効) |
置き換え後は次の流れになります。
- Cloudflare Access が Entra ID でサインインさせる。MFA は Entra の条件付きアクセスで強制する。Access のポリシーでは「営業台帳利用者」グループだけを許可する
- Worker は
Cf-Access-Jwt-Assertionヘッダーの JWT を、チームドメインの公開鍵(https://{チーム名}.cloudflareaccess.com/cdn-cgi/access/certs)とaudで検証する。メールアドレスのヘッダーだけを信用することはしない - 検証したメールアドレスで
users表を引き、ロール(管理者 / 閲覧者)を決める。表にない人は、Access を通過していても拒否する requireUserとrequireAdmin(src/auth.tsL68、L74)の呼び出し側はそのまま使えるので、API ルートの書き換えは要らない
6.2 シークレット管理
- クライアントシークレットと API キーは
wrangler secret putで Workers のシークレットに入れます。wrangler.tomlとリポジトリには置きません。 - Entra のアプリは、Dynamics 365 用と Graph 用に分けます。付与するのは最小権限(読み取りと
Sites.Selected)だけです。 - シークレットは12か月ごとに更新します(Entra の上限は24か月)。期限の1か月前に通知し、更新作業は保守に含めます。
- デプロイ用の Cloudflare API トークンは、Workers、D1、R2 の編集だけに絞って CI のシークレットに置きます。
6.3 個人情報と監査
| 項目 | 方針 |
|---|---|
| 対象 | 顧客の担当者名(customers.contact_name)、社員名、案件メモ |
| 閲覧制御 | 閲覧者には顧客担当者名を伏せて表示し、管理者だけが見られるようにする(先方の要否確認後に設定) |
| 閲覧ログ | 顧客・案件の参照、月次資料と原本のダウンロードを access_logs に記録する(利用者、日時、対象、IP アドレス)。更新系は既存の audit_logs に記録する |
| 保持期間 | D1 には直近13か月を置き、それより前は月次で R2 に JSON Lines で書き出す。保存年数は社内規程に合わせる(仮に5年)。Access の Free プランはログの保持期間が短いため、監査は台帳側の記録で行う |
| バックアップ | D1 の Time Travel(30日以内の任意時点に復元)に加え、週次で D1 のエクスポートを R2 に保存する |
| データの所在 | D1 と R2 は位置ヒントを apac にする。ただし、選べる管轄(jurisdiction)は EU / FedRAMP / US だけで、国内保管を保証する設定はない(Phase-1 で使った wrangler 4.138 の d1 create --help で確認)。個人情報保護委員会のガイドラインに沿って、外国の事業者のクラウドに保存する場合の「外的環境の把握」を先方の社内規程上で整理していただく必要がある。国内保管が必須の場合は主案の前提が崩れるので、個人情報を持たない設計か国内クラウドを別途見積もる |
| 委託先管理 | 受託者の作業者アカウントは個人ごとに発行し、退任時に削除する。本番データへのアクセスは保守作業時だけにする |
7. AI(任意)
要件では「AI活用に興味がある(マストではない)」とされています。そこで主案には入れず、B案に次の範囲だけを置きます。
やる範囲(B案)
- 月次資料のコメント下書き:KPI と乖離の一覧(
findAnomaliesの結果)を Workers AI に渡し、3〜5行の所見の下書きを作る。数字は台帳の値を差し込むだけで、AI には計算させない。画面では「下書き」と明示し、人が直してから使う - 自然言語から検索条件への変換:「9月に青葉向けで計画を下回っているもの」のような文を、期間・顧客・担当者の条件(JSON)に変える。検索そのものは今の SQL で行う。入口は Phase-1 の
/api/ai/ask(src/app.tsL363)で、入出力はそのまま保つ
やらなくてよい範囲
- 入力漏れや異常値の検知。
assessDealとfindAnomaliesのルールで足りていて、説明もしやすい - 2TB のアーカイブを Vectorize で意味検索すること。索引の作成と維持の費用が効果に見合わない
- AI による台帳の自動修正や自動補完。補完は人が確認する今の流れを保つ
- 売上予測モデル
- 外部の LLM サービスへのデータ送信
費用は Workers AI の無料枠(1日10,000 Neurons)でほぼ収まります。利用回数には上限を設けます。日本語の品質はモデルによって差があるため、検証環境で Phase-1 の架空データを使って評価してから採用を決めます。
8. 開発・導入スケジュール
選定(2027年3〜5月)を経て、納期の2028年1月に収まる計画です。作業量は約20人日ですが、先方の確認やアプリ登録の手続きを待つ期間を含めて7か月に分けています。
| マイルストーン | 時期 | 完了条件 |
|---|---|---|
| M0 提案書の提出 | 2027年1月まで | 部長・室長へのご説明に約2か月かかると伺っているため、選定の前に余裕を持って提出する |
| M1 連携仕様とマスタ対応表の確定 | 2027年7月末 | 3系統の接続方式、資格情報の発行手続き、対応表の初版 |
| M2 基盤の本番化 | 2027年8月末 | 検証環境で Access+Entra の SSO、R2、閲覧ログが動く。デモ認証は撤去済み |
| M3 3系統の実データ取得 | 2027年10月末 | 検証環境で Dynamics 365 / Teams / Knowledge Suite から実データを取得し、sync_runs に履歴が残る |
| M4 移行完了 | 2027年11月末 | 直近3年度の台帳化、過去分の R2 格納と照合報告 |
| M5 受入試験の完了 | 2027年12月下旬 | 11月初・12月初の月初処理と、11月決算をまたぐ年度切替を並行稼働で確認 |
| M6 本番切替・検収 | 2028年1月中旬 | 受入基準(§2.3)を満たし、運用手順書を引き渡す |
毎年9月の予算取りに合わせ、2027年9月の時点でB案の要否を判断する材料(検証環境での試用結果)をお出しします。
9. 概算(税抜)
9.1 主案 A(初期100万円以内・月額10万円以内)
人日単価は 4.5万円(ニアショアとオフショアの併用を想定)で見積もっています。Phase-1 の台帳、取込、同期履歴、補完、月次出力を流用するので、新しく作るのは連携、認証、移行、運用の部分だけです。
| # | 作業 | 人日 | 金額 |
|---|---|---|---|
| 1 | 要件と連携仕様の確認、マスタ対応表の設計、進行管理 | 2.0 | 90,000 |
| 2 | 本番認証(Access+Entra、JWT 検証、ロール表、デモ認証の撤去) | 1.5 | 67,500 |
| 3 | Dynamics 365 アダプタ(前月売上、定期実行、再試行、明細行キー) | 3.0 | 135,000 |
| 4 | Teams / Graph アダプタ(見通しの読み取り、Sites.Selected、失敗通知) |
3.0 | 135,000 |
| 5 | Knowledge Suite 取込(API または CSV 定期取込、項目対応) | 2.0 | 90,000 |
| 6 | .xlsx の直接取込、R2 への原本保存、取込プロファイル10本 | 2.0 | 90,000 |
| 7 | 月次資料の定期生成(R2 保存、.xlsx 出力) | 1.0 | 45,000 |
| 8 | データ移行(直近3年度の台帳化、過去分の R2 格納と目録、照合) | 2.0 | 90,000 |
| 9 | 閲覧ログ、担当者名のマスキング、保持設定 | 1.0 | 45,000 |
| 10 | 自動テストの拡張、受入支援、並行稼働の立会い | 1.5 | 67,500 |
| 11 | 本番環境の構築、運用手順書、操作説明会1回 | 1.0 | 45,000 |
| 小計 | 20.0 | 900,000 | |
| 変動枠(先方 API の仕様が確定した後の差分。使った分だけ請求) | 上限 | 100,000 | |
| 初期費用の上限 | 1,000,000 |
- 単価が5万円の場合は小計がちょうど100万円になり、変動枠が残りません。その場合は #7 の .xlsx 化を外して SpreadsheetML のままにし、#8 の台帳化を直近2年度に縮めて、約2人日を減らします。
- 仕様が想定より重かった場合は、変動枠を使う前に Must と Should の入れ替えを先方にご相談します。上限は超えません。
月額(主案)
| 項目 | 前提 | 月額 |
|---|---|---|
| Workers Paid | 基本料5ドル。D1、Cron Triggers、標準ログの基本枠を含む | 約 750円 |
| D1 | 台帳は1GB未満。含まれる枠の範囲内 | 0円 |
| R2 | 2TB を全量格納したとき(0.015ドル/GB・月)。移行が終わるまではこれより少ない | 約 4,500円 |
| Cloudflare Access | Zero Trust Free(50名まで) | 0円 |
| クラウド費の計上額 | 実額は約5,300円。価格改定や操作課金に備えて切り上げる | 10,000円 |
| 保守運用 | 連携ジョブの日次確認と失敗時の再実行、初めの3か月は月初処理に立会い、シークレット更新、依存ライブラリの更新、問い合わせと軽微な修正(月1人日相当) | 60,000円 |
| 合計 | 70,000円 |
Microsoft 365 / Dynamics 365 / Knowledge Suite は先方の既存契約で足りる前提です。アプリケーションユーザーや API 利用に追加のライセンスが必要になった場合は別途ご相談します。Cloudflare のセルフサービス契約はクレジットカード払いです。請求書払いが必要なら、受託者が立て替えて請求する形も選べます。
9.2 オプション B(100万円超・決裁リスクあり)
| 追加項目 | 人日 | 金額 |
|---|---|---|
| Teams への書き戻し(Microsoft Lists への移行、行単位の更新) | 3.0 | 135,000 |
| Workers AI(月次コメントの下書き、自然言語から検索条件への変換、評価) | 2.5 | 112,500 |
| 補完と見通し修正の承認フロー | 2.0 | 90,000 |
| 台帳化を過去5年度に拡大、取込プロファイルを20本に | 3.0 | 135,000 |
| 過去ファイル目録の全文検索(D1 FTS5 を使った目録検索) | 2.5 | 112,500 |
| 同期基盤の強化(Queues による遅延再試行、差分同期) | 2.0 | 90,000 |
| 小計 | 15.0 | 675,000 |
- A案と合わせると初期は約157.5万円になります。要件に「100万円を超えると社長決裁となり、決裁が下りる可能性は低い」とあるとおり、一括で発注いただくのは難しいと考えています。
- 月額は、Workers AI と Queues の実費(数千円)と保守の増額(8万円)で約9万円です。月額の上限には収まります。
- 決裁基準を避けるための分割発注は提案しません。B案の各項目は、本番運用の結果を見て要否を判断する独立した改善です。必要なものだけを、2027年9月の予算取りで次年度(FY2028)の予算として正規に審議いただく想定です。
10. リスクと前提条件
| # | リスク・前提 | 影響 | 対応 |
|---|---|---|---|
| 1 | Dynamics 365 の製品種別(Sales / Business Central / Finance & Operations)が未確定 | 接続方式と工数が変わる | 第1回打ち合わせで確定する。アダプタで差を閉じ込める。F&O で追加の仕組み(仮想テーブルなど)が必要なら変動枠かB案 |
| 2 | Teams 上の見通しファイルの置き場所と形式(Excel / Lists、シート構成、同時編集の運用)が未確定 | 読み取り方式と書き戻しの可否が変わる | 主案は読み取りだけ。実ファイルの構成を見てから設計する |
| 3 | Graph のブック API がアプリ権限で使えるかが未検証 | Excel のままでは書き戻しができない可能性 | 主案はファイル取得と解析で読む。書き戻しは Lists への移行を前提とする(B案) |
| 4 | Knowledge Suite の API の有無、プラン、利用制限が不明 | 自動取込にならない可能性 | CSV の月2回取込を代替として主案に含める |
| 5 | Entra のアプリ登録と同意にはテナント管理者の作業が必要 | 手続きが遅れると M1〜M3 が遅れる | 7月中に依頼書を出す。手続きの待ち時間をスケジュールに含めている |
| 6 | 15年分の Excel の品質(表記ゆれ、結合セル、手入力) | 台帳化の工数が増える | 台帳化は直近3年度に限る。それより前は原本保管と目録にする |
| 7 | データの国内保管の要否 | 必須なら主案の前提が崩れる | §6.3 のとおり早めに確認する |
| 8 | 初期費用100万円に余裕がない | 追加要望を吸収できない | 変動枠と Must / Should の入れ替えで上限を守る |
| 9 | 先方の担当者が1名に集中している | 確認が滞る。属人化が戻る | 取込プロファイルと列対応の画面で、管理者が自分で運用できるようにする。手順書を残す |
| 10 | Cloudflare アカウントの名義(公開デモは受託者側のアカウント) | 契約と責任の所在が曖昧になる | 本番は先方名義のアカウントで構築する |
| 11 | 大きな .xlsx の解析で Worker の CPU 時間が足りなくなる | 取込に失敗する | 解析はブラウザ側で行い、行データを分割して送る。サーバー側ではマスタを一括照会する(今は1行ずつ照会している:src/import-service.ts L151–L154) |
| 12 | Microsoft / Knowledge Suite 側の API 変更と流量制限 | 同期の失敗 | 再試行と失敗通知を入れる。軽微な追従は保守に含める |
| 13 | Cloudflare の料金改定 | 月額が変わる | 月額はクラウド費を切り上げて計上している。年1回見直す |
11. 次のアクション(先方への確認事項チェックリスト)
連携
- Dynamics 365 の製品種別とバージョン、環境 URL、検証用サンドボックスの有無
- 「前月売上」として使っている帳票またはテーブル(請求書明細か、出荷か、受注か)と、月初に確定するタイミング(何営業日目か)
- Entra ID テナント管理者の窓口と、アプリ登録・管理者同意の社内手続き
- Teams の見通しファイルのチーム名とチャネル、ファイル形式(Excel / Lists)、シート構成、同時編集の運用ルール
- 見通しの正本を Teams に残すか、台帳に移すか
- Knowledge Suite の契約プラン、API の利用可否と条件、CSV エクスポートの項目
データ
- 10〜20個の Excel の一覧(ファイル名、用途、更新頻度、担当、行数)と、サンプルの提供(個人情報はマスキングで可)
- 顧客コード、製品コード、担当者の正本をどのシステムに置いているか
- 2TB の内訳(Excel / PDF / 画像など)と今の保管場所、アップロードに使える回線
- 台帳化する年度の範囲(主案は直近3年度)
セキュリティ・運用
- 個人情報の取扱規程:国内保管が必須か、保持期間、閲覧ログの保存期間
- 利用者約20名の一覧と、管理者にする人数
- 閲覧者に顧客担当者名を表示してよいか
- Cloudflare アカウントの名義、支払い方法(カード / 立替請求)、独自ドメインの要否
- AI 利用に関する社内ポリシー(B案を検討する場合)
こちらで進めること
- ReadyCrew 経由で WEB 会議を設定し、公開デモをご覧いただきながら上記を確認する
- 回答を受けて見積を確定し、2027年1月までに正式な提案書を提出する
- 実データを扱う前に公開デモを停止するか、Access で保護する
付録:Phase-1 から本開発への差分(ファイル別)
| ファイル | 変更内容 |
|---|---|
src/auth.ts |
HMAC Cookie(L19–L38)を Access JWT の検証に置き換える。requireUser / requireAdmin の形は残す |
src/app.ts |
ログイン(L29)、デモ初期化(L377)、自動シード(L20)、署名鍵の既定値(L22、L38)を撤去する。閲覧ログのミドルウェアを追加する |
src/adapters.ts |
IntegrationAdapter(L19)はそのまま。実 API 版の3アダプタ、トークン取得、再試行、対応表による変換を追加する。executeSync(L204)に trigger と attempt を加え、simulateFailure は開発環境だけにする |
src/index.ts |
Cron Triggers 用の scheduled ハンドラを追加する |
src/import-service.ts |
マスタの一括照会と db.batch による書き込み、R2 への原本保存、取込プロファイルを追加する |
src/report.ts |
.xlsx を生成し、定期生成したものを R2 に保存する |
src/quality.ts |
閾値(L23、L45)を settings から読むようにする |
migrations/0002_*.sql |
§3.2 の表を追加・変更する |
wrangler.toml |
[vars] の署名鍵(L9)を削除する。環境ごとの D1 / R2、[triggers] crons、Access の aud とチームドメインを設定する |
test/ |
実 API 版アダプタの契約テスト(fetch をモックし、匿名化した応答を使う)、Access JWT の検証テスト、Cron 実行のテストを追加する |