[{"data":1,"prerenderedAt":297},["ShallowReactive",2],{"content-/loan-repayment-module-mf-journal":3,"all-pages-for-dir":295,"og-image-/loan-repayment-module-mf-journal":296},{"id":4,"title":5,"body":6,"category":275,"description":276,"extension":277,"meta":278,"navigation":245,"path":279,"project_name":280,"published":281,"publishedAt":282,"seo":283,"stem":284,"tags":285,"todo":292,"updatedAt":293,"__hash__":294},"pages/2026-04/2026-04-01/loan-repayment-module-mf-journal.md","返済予定表のモジュール化と会計ソフト仕訳生成パイプラインを構築した",{"type":7,"value":8,"toc":254},"minimark",[9,13,17,21,29,33,38,59,62,65,75,78,82,85,95,102,105,112,115,122,125,129,136,142,145,156,159,165,185,192,195,202,205,208,211,218,221,224,227,230,234],[10,11,12],"h1",{"id":12},"返済予定表のモジュール化と会計ソフト仕訳生成パイプライン",[14,15,16],"p",{},"日本政策金融公庫の融資返済データを手入力する作業を消すために、丸一日かけてGoogle Sheets上に返済予定表テンプレートを組み上げ、そこから会計ソフトの仕訳データを自動生成するパイプラインをつないだ。",[18,19,20],"h2",{"id":20},"既存スプレッドシートの構造分析",[14,22,23,24,28],{},"まず手元にあった返済予定表スプレッドシートを ",[25,26,27],"code",{},"gws"," CLI で読み取り、列構造を把握した。元金均等返済で、月次の元金・利息・残高が72行並んでいる。この構造をそのまま再現するのではなく、入力変数を分離してテンプレート化する方針を決めた。",[18,30,32],{"id":31},"tpl_返済予定表シートの構築","TPL_返済予定表シートの構築",[34,35,37],"h3",{"id":36},"batchupdateで問題を回避","batchUpdateで「!」問題を回避",[14,39,40,42,43,46,47,50,51,54,55,58],{},[25,41,27],{}," CLIでシートにデータを書き込む際、シート名に「TPL_返済予定表」のような日本語名を使うと、",[25,44,45],{},"!"," 区切りのA1記法でパースエラーが出る。",[25,48,49],{},"updateCells"," + ",[25,52,53],{},"sheetId"," 指定の ",[25,56,57],{},"batchUpdate"," に切り替えたら、シート名を経由せずにセルを特定できるようになり、問題が消えた。",[34,60,61],{"id":61},"入力変数の設計",[14,63,64],{},"シート上部に青文字で入力変数を配置した。",[66,67,68,72],"ul",{},[69,70,71],"li",{},"融資実行日、融資金額、年利率、返済回数、初回返済日",[69,73,74],{},"口座名（普通預金の補助科目）--- 後から追加した変数",[14,76,77],{},"これらを変えるだけで72行の月次データが再計算される構造にした。",[34,79,81],{"id":80},"日割り利息計算-365日固定割りへの修正","日割り利息計算 --- 365日固定割りへの修正",[14,83,84],{},"最初は「月利 = 年利 / 12」で組んでいた。しかし日本の融資実務では利息を日割りで計算するのが標準だ。計算式を以下に修正した。",[86,87,92],"pre",{"className":88,"code":90,"language":91},[89],"language-text","利息 = 前月残高 × 年利率 × 経過日数 / 365\n","text",[25,93,90],{"__ignoreMap":94},"",[14,96,97,98,101],{},"経過日数は前回返済日から今回返済日までの実日数を ",[25,99,100],{},"DAYS"," 関数で取得する。365日固定割りなので閏年でも分母は変わらない。この修正で、手元の公庫返済予定表と1円単位で一致するようになった。",[34,103,104],{"id":104},"最終回の端数処理",[14,106,107,108,111],{},"元金均等返済で「融資金額 / 返済回数」が割り切れない場合、毎月の元金に1円未満の端数が出る。積み残した端数を最終回で一括返済する処理を入れた。具体的には、最終回の元金を「残高全額」に切り替える ",[25,109,110],{},"IF"," 式を組んでいる。",[34,113,114],{"id":114},"合計行を上部に移動",[14,116,117,118,121],{},"当初は合計行をシート最下部に置いていたが、返済期間が変わるたびに合計行の位置がずれる。合計行を入力変数の直下（データ行の上）に移動した。",[25,119,120],{},"SUMIFS"," で返済回数以内の行だけ集計するので、72行の枠が余っても合計値は正しく出る。",[18,123,124],{"id":124},"会計ソフト仕訳生成パイプライン",[34,126,128],{"id":127},"アーキテクチャ-gws-python-gws","アーキテクチャ: gws → Python → gws",[14,130,131,132,135],{},"返済予定表のデータを読み取り、会計ソフトのインポート形式に変換して、別シートに書き戻す。この一連の流れを ",[25,133,134],{},"repayment_to_mf_journal.sh"," というシェルスクリプトにまとめた。",[86,137,140],{"className":138,"code":139,"language":91},[89],"gws sheets get (返済予定表読み取り)\n  ↓ JSON\nPython変換スクリプト (仕訳データ生成)\n  ↓ JSON\ngws sheets batchUpdate (仕訳シート書き込み)\n",[25,141,139],{"__ignoreMap":94},[34,143,144],{"id":144},"subprocess経由のgws認証問題",[14,146,147,148,151,152,155],{},"最初はPythonスクリプト内から ",[25,149,150],{},"subprocess.run([\"gws\", \"sheets\", \"get\", ...])"," でデータを取得しようとした。ところがPythonの子プロセスからgwsを呼ぶと認証トークンの受け渡しがうまくいかず、",[25,153,154],{},"401 Unauthorized"," が返ってくる。",[14,157,158],{},"gws単体で実行すれば認証は通る。原因を追いかける時間が惜しかったので、方針を変えた。",[14,160,161],{},[162,163,164],"strong",{},"ファイルベースI/Fに切り替え:",[166,167,168,175,178],"ol",{},[69,169,170,171,174],{},"シェルスクリプトで ",[25,172,173],{},"gws sheets get"," → JSONファイルに保存",[69,176,177],{},"Pythonスクリプトはファイルから読み取り → 変換結果をJSONファイルに出力",[69,179,180,181,184],{},"シェルスクリプトで出力JSONを ",[25,182,183],{},"gws sheets batchUpdate"," に渡す",[14,186,187,188,191],{},"プロセス間のデータ受け渡しをファイルに落としたことで、認証の問題が構造的に消えた。副産物として、中間ファイルが残るので、変換のどの段階でデータが壊れたか ",[25,189,190],{},"cat"," 一発で切り分けられるようになった。",[34,193,194],{"id":194},"bashクォーティングとの格闘",[14,196,197,198,201],{},"シェルスクリプト内でJSONを組み立てる箇所で、シングルクォートとダブルクォートの入れ子が壊れる場面が何度かあった。特に ",[25,199,200],{},"jq"," に渡す式の中で変数展開する箇所が厄介で、ヒアドキュメントに逃がすことで解決した。",[34,203,204],{"id":204},"口座名の入力変数追加",[14,206,207],{},"仕訳の借方・貸方に「普通預金（○○銀行）」のような補助科目名が必要になる。返済予定表シートの入力変数に口座名フィールドを追加し、Python変換スクリプトがこの値を仕訳データに埋め込むようにした。融資先が複数ある場合でも、口座名を切り替えるだけで対応できる。",[18,209,210],{"id":210},"cf-lifecycle-journalスキルの作成",[14,212,213,214,217],{},"ここまでの手順を ",[25,215,216],{},"cf-lifecycle-journal"," というClaude Codeスキルとしてドキュメント化した。次回以降、新しい融資の返済予定表を追加するときにスキルを呼び出せば、テンプレートのコピーから仕訳生成まで一気に走る。",[14,219,220],{},"Google Docsにも同内容を保存し、Google Tasksに明日の作業として登録した。",[18,222,223],{"id":223},"振り返り",[14,225,226],{},"一日の作業で手を動かした時間の半分以上は、gws認証問題とbashクォーティングの試行錯誤に消えた。技術的に難しかったわけではない。「子プロセスから認証が通らない」という事実に気づくまでに時間がかかり、気づいた後はファイルI/Fに切り替えて10分で動いた。",[14,228,229],{},"日割り利息の修正も、公庫の返済予定表と突き合わせて初めて1円のずれに気づいた。「月利 = 年利 / 12」は概算としては正しいが、実務の計算とは合わない。融資実務の利息計算は日割りが基本、という知識が手を動かして初めて身体に入った。",[18,231,233],{"id":232},"明日のto-do","明日のTo Do",[66,235,238,248],{"className":236},[237],"contains-task-list",[69,239,242,247],{"className":240},[241],"task-list-item",[243,244],"input",{"disabled":245,"type":246},true,"checkbox"," 年次推移表から5年分のCF精算表を一括生成する",[69,249,251,253],{"className":250},[241],[243,252],{"disabled":245,"type":246}," 営業CFの調整項目について、書籍からの補足情報を追加する",{"title":94,"searchDepth":255,"depth":255,"links":256},2,[257,258,266,272,273,274],{"id":20,"depth":255,"text":20},{"id":31,"depth":255,"text":32,"children":259},[260,262,263,264,265],{"id":36,"depth":261,"text":37},3,{"id":61,"depth":261,"text":61},{"id":80,"depth":261,"text":81},{"id":104,"depth":261,"text":104},{"id":114,"depth":261,"text":114},{"id":124,"depth":255,"text":124,"children":267},[268,269,270,271],{"id":127,"depth":261,"text":128},{"id":144,"depth":261,"text":144},{"id":194,"depth":261,"text":194},{"id":204,"depth":261,"text":204},{"id":210,"depth":255,"text":210},{"id":223,"depth":255,"text":223},{"id":232,"depth":255,"text":233},"dev","Google Sheetsで返済予定表テンプレートを構築し、シェルスクリプト+Pythonで会計ソフト向け仕訳データを自動生成するパイプラインを完成させた記録","md",{},"/loan-repayment-module-mf-journal","eurekapu-nuxt4",false,"2026-04-01T00:00:00.000Z",{"title":5,"description":276},"2026-04/2026-04-01/loan-repayment-module-mf-journal",[286,287,288,289,290,291],"Google Sheets","gws CLI","返済予定表","仕訳生成","シェルスクリプト","Python","memo",null,"nKph_Eo3_HWA5F5tK9eg6bPA57F8lZvh4KeOxks2nwY",[],"https://log.eurekapu.com/favicon.svg",1775338203733]