しんりのblog

思ってる事、好きな事、トライした事などなどを書きます。

freee APIを使って資金繰り表を作るときに苦労した事 part 1

先日freeeのAPIを作って資金繰り予定表を作った話を書いてから時間たっちゃったけど、これからfreee API取り組む人のためにどんな所に苦労してどうやって解決したか書いておこうと思う。

【前提】Web API めちゃくちゃ概略
Web APIについての詳細はいろんなBlog、サイトがあるのでそちらを見てもらえれば。
自分はバリバリの文系人間なので、専門的な事は分からないが、今回の説明に必要なので超簡単に自分が理解してるイメージを書いておく。

  1. Web APIWebブラウザでホームページを見るのと同じように、HTTPを使ってサーバーとやり取りをしている。
  2. ホームページの場合URLにアクセスするとHTMLが返ってくるので、それをWebブラウザが読み替えてホームページを表示している。
  3. Web APIも同じようにURLに何かしらの指示を送るとJSONXMLなどのデータ、ファイルが返ってくる。
  4. 指示の仕方はGET(取得)、POST(作成)、PUT(変更)、DELETE(削除)などのメソッドと呼ばれる指示とURI(URL or URN)を指定する。
  5. 返ってきたJSONなどを、プログラムで自分が見たいように加工してあげる。

現在会計freeeのAPIで公開されているのはこちら
developer.freee.co.jp

こちらに記載してあるAPIエンドポイントの
https://api.freee.co.jp
の後にapi/1/と行いたい内容のURIを書くと実行できる。

BSを取得したい場合、さっきのリファレンスで試算表の取得を見ると、
/reports/trial_bsと書いてあり、Parametersに絞り込むためのパラメーターが書いてある。

例として事業所IDXXXXXXの2019年1月のBSを取得したい場合、
Parametersの中に事業所IDが「company_id」、会計年度が「fiscal_year」、開始会計月(mm)が「start_month」、終了会計月(mm)が「end_month」とあるので、

https://api.freee.co.jp/api/1//reports/trial_bs?company_id=XXXXXX&fiscal_year=2019&start_month=01&end_month=01
と書いてあげる。

1、月次推移表APIがないので、試算表APIから自分で作らないといけない。

freeeはオープンAPI戦略を取っているので、他の会計ソフトと比べるとかなりの種類のAPIが公開されており、最近もどんどん追加されてるけど、月次推移表はまだ用意されてない。

そこで試算表APIで月毎の試算表のデータを取ってきて、自分で試算表を作る必要がある。

 やり方は色々あると思うけど、自分がやったのはURIの年と月を変数にして12回for文で繰り返すことにより配列に12ヵ月分入れるやり方。
12回APIを呼び出さないといけないので、結構時間かかる。
ここは詳しい人にもっといい方法があれば教えて欲しいところ。

for(var r = 0; r<12 ;r++){

var requestUrl_3 ="https://api.freee.co.jp/api/1/reports/trial_bs?company_id="+ companyId+"&account_item_display_type=group&breakdown_display_type=account_item&fiscal_year="+ prf_year[r]+"&start_month="+ prf_month[r]+"&end_month="+ prf_month[r];
res3[r] = UrlFetchApp.fetch( requestUrl_3 , options ).getContentText();
//レスポンスのデータを配列に格納
bsResponse_3[r] = JSON.parse( res3[r] );
data_3[r] = bsResponse_3[r].trial_bs;

parent_account_category_name_3[r] = [];
account_category_name_3[r] = [];
account_item_name_3[r] = [];
hierarchy_level_3[r] =[];
closing_balance_3[r] = [];
debit_amount_3[r] = [];
credit_amount_3[r] = [];
opening_balance_3[r] = [];

for ( var q = 0 ; q < data_3[r].balances.length ; q++ ) {
account_category_name_3[r][q]=[ data_3[r].balances[q].account_category_name ];
closing_balance_3[r][q]=[ data_3[r].balances[q].closing_balance ] ;
hierarchy_level_3[r][q]=[ data_3[r].balances[q].hierarchy_level ] ;
account_item_name_3[r][q]=[ data_3[r].balances[q].account_item_name ] ;
debit_amount_3[r][q]=[ data_3[r].balances[q].debit_amount ] ;
credit_amount_3[r][q]=[ data_3[r].balances[q].credit_amount ] ;
opening_balance_3[r][q]=[ data_3[r].balances[q].opening_balance ] ;
}

2、月毎に勘定科目、タグの数が違うのでそのまま配列に入れるとずれてしまう
 これは例えば1月に使ってなかった勘定科目を12月に使ってると、1月の試算表には出てこないが12月には出てくるのでそのまま配列に入れると位置がずれてくる。
またfreeeの試算表は残高が多い順にタグが並ぶので、タグで集計する場合はそのまま配列に入れるとこれも同じくずれてくる。
そこで年度の試算表から勘定科目一覧を持ってきて勘定科目で比較して一致した列に残高を入れるようにした。
イメージはこんな感じ。
集計用の列の勘定科目が同じなケースがあるので、下の列も合わせて比較することによってユニークになるようにした。

/*******
 月次の残高を科目に合わせて並び替え
 *******/ 
    
    bs_closing_balance[r] = [];//月次の期末残高用配列
     bs_debit_amount[r]=[];
     bs_credit_amount[r]=[];
     bs_opening_balance[r]=[];
    
    var arrData3 = Array.prototype.concat.apply([], account_category_name); 
    var arrData5 = Array.prototype.concat.apply([], account_item_name); 
    var arrData7 = Array.prototype.concat.apply([], hierarchy_level); 
 
    var arrData4 = Array.prototype.concat.apply([], account_category_name_3[r]); 
    var arrData6 = Array.prototype.concat.apply([], account_item_name_3[r]); 
    var arrData8 = Array.prototype.concat.apply([], hierarchy_level_3[r]);
    
    
  /*******
 アカウントアイテムはユニークなので入ってる時はそのまま挿入。入ってない場合はアカウントカテゴリー、アカウントアイテム、ヒエラルキーレベルが一個下も一致した場合にアカウントカテゴリーを入力
 *******/    
    
 var dd =0;
  for(var s = 0; s < account_category_name.length ; s++){
     for(var t = 0; t < closing_balance_3[r].length ; t++){  
 
       if(!arrData5[s]){ 
    if(((arrData3[s]==arrData4[t])&&( arrData7[s]==arrData8[t])&&(arrData5[s]==arrData6[t])) && ((arrData3[s+1]==arrData4[t+1])&&(arrData5[s+1]==arrData6[t+1])&&( arrData7[s+1]==arrData8[t+1]))){ 
         bs_closing_balance[r][s]=closing_balance_3[r][t];
         bs_debit_amount[r][s]=debit_amount_3[r][t];
         bs_credit_amount[r][s]=credit_amount_3[r][t];
        bs_opening_balance[r][s]=opening_balance_3[r][t];
         break;
    }else if(arrData3[s+dd]==arrData4[t+1]){
      for(dd=1; dd<100 ;dd++){
        bs_closing_balance[r][s]=closing_balance_3[r][t];
        bs_debit_amount[r][s]=debit_amount_3[r][t];
         bs_credit_amount[r][s]=credit_amount_3[r][t];
        bs_opening_balance[r][s]=opening_balance_3[r][t];
      break;
      }
    }
  }
       else{
         if(( arrData7[s]==arrData8[t])&&(arrData5[s]==arrData6[t])){
         bs_closing_balance[r][s]=closing_balance_3[r][t];
         bs_debit_amount[r][s]=debit_amount_3[r][t];
         bs_credit_amount[r][s]=credit_amount_3[r][t];  
           bs_opening_balance[r][s]=opening_balance_3[r][t];
           
         break;
    }
       }
  if(!bs_closing_balance[r][s]){
   bs_closing_balance[r][s]=[0]; 
   bs_debit_amount[r][s]=[0];
   bs_credit_amount[r][s]=[0]; 
   bs_opening_balance[r][s]=[0];
   }       
      
  
  }
  }
  }
  }catch(e){
    Browser.msgBox("その期間のデータがfreeeにありません");
  }

 
3、売掛、買掛レポートはAPIがないので取引APIから自分で集計をしないといけない。
売掛レポート、買掛レポートはAPIがないので取引を取得して決済期日から集計した。
100件づつしか取り込めないので100件取り込んだら、+100 件目から取り込むように書いてみた。

 while(i != 10000){
    
  var requestUrl ="https://api.freee.co.jp/api/1/deals?company_id="+ companyId +"&status=unsettled&offset="+ i +"&limit=100";
  //特定の事業所の未決済取引を100件づつ取得  
  var res = UrlFetchApp.fetch( requestUrl , options ).getContentText();
  //レスポンスのデータを配列に格納
  var mikessaiResponse = JSON.parse( res );
  var data = mikessaiResponse.deals;
  var length =data.length;
   
  for ( var j = 0 ; j < data.length ; j++ ) {
    id.push( [ data[j].id ] );
    issue_date.push( [ data[j].issue_date ] );
    due_date.push( [ data[j].due_date ] );
    
    partner_id.push( [ data[j].partner_id ] );
    type.push( [ data[j].type ] );
    amount.push( [ data[j].amount ] ); 
    due_amount.push( [ data[j].due_amount ] ); 
    due_year[j] = [due_date[j].toString().substr( 0,4 )]; //決済期日の年切り出し(最初から4文字)
    due_month[j] = [due_date[j].toString().substr( 5,2 )];//決済期日の月切り出し(5文字目から2文字)
    due_ym[j]= [Number(due_year[j]+Number(due_month[j]))];
  };
    
//100件づつ取り込みなので次の100件用にインクリメント。取り込みが100件以下ならブレイク。    
  if (data.length != 100){
  break
  }
  i = i+100;
}

あとは取引先、年月毎に集計して表にしてみた。
ここら辺は下記プログラムの未決済取引取得モジュールを参考にしてみていただければ。
docs.google.com


続きの最後資金繰予定表を作るところはまた今度書きます。