Created
September 24, 2021 15:45
-
-
Save xkikeg/12c6b72801706b90d3e425757ae83a20 to your computer and use it in GitHub Desktop.
Create ledger text out of Money forward (https://moneyforward.com/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Moneyforward to ledger | |
// @version 1 | |
// @grant GM.setClipboard | |
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js | |
// @match https://moneyforward.com/accounts/show/* | |
// ==/UserScript== | |
function runReport(node) { | |
var result = []; | |
$('#cf-detail-table > tbody > tr').each(function(i, trnode) { | |
result.push(convertTransaction(trnode)); | |
}); | |
result.reverse(); | |
GM.setClipboard(result.join('')); | |
} | |
class Post { | |
constructor(account, amount, comment=null) { | |
this.account = account; | |
this.amount = amount; | |
this.comment = comment; | |
} | |
print() { | |
var res = ' ' + this.account + ' ' + this.amount; | |
if (this.comment) { | |
res += ' ; ' + this.comment; | |
} | |
return res; | |
} | |
} | |
function convertTransaction(trnode) { | |
var date; | |
var code; | |
var payee; | |
var amount; | |
var srcAccount; | |
var destAccount; | |
$(trnode).find('td').each(function(i, td) { | |
let tdtext = $(td).text().trim(); | |
switch (i) { | |
case 0: | |
// do nothing | |
break; | |
case 1: | |
let datetext = $(td).data('table-sortable-value'); | |
let match = /(\d+\/\d+\/\d+)-(\d+)/.exec(datetext); | |
if (!match) { | |
console.error('failed to match date: ', datetext); | |
} else { | |
date = match[1]; | |
code = match[2]; | |
} | |
break; | |
case 2: | |
payee = $(td).find('div span').text().trim(); | |
break; | |
case 3: | |
amount = $(td).find('span.offset').text().trim(); | |
break; | |
case 4: | |
let srcData = $(td).data('original-title'); | |
if (srcData.startsWith('みずほ銀行 北沢支店 普通')) { | |
srcAccount = 'Assets:Banks:Mizuho:Kitazawa'; | |
} else if (srcData.startsWith('みずほ銀行 兜町支店 普通')) { | |
srcAccount = 'Assets:Banks:Mizuho:Kabuto'; | |
} | |
let dstBox = $(td).find('.transfer_account_box'); | |
if (dstBox) { | |
switch(dstBox.text().trim()) { | |
case '三井住友カード': | |
destAccount = 'Liabilities:ANA Card'; | |
break; | |
case 'セゾンカード': | |
destAccount = 'Liabilities:Mizuho Card'; | |
break; | |
} | |
} | |
break; | |
case 6: | |
switch (tdtext) { | |
case '生命保険': | |
destAccount = 'Expenses:Insurances:Life'; | |
break; | |
case 'その他保険': | |
destAccount = 'Expenses:Insurances:Medical'; | |
break; | |
case '学費': | |
destAccount = 'Liabilities:Fixed:JASSO'; | |
break; | |
case 'その他税・社会保障': | |
destAccount = 'Expenses:Tax:Income'; | |
break; | |
} | |
break; | |
} | |
}); | |
return [ | |
'', | |
date + ' * (' + code + ') ' + payee, | |
new Post(srcAccount, amount + ' JPY').print(), | |
new Post(destAccount, negateAmount(amount) + ' JPY').print(), | |
'', | |
].join('\n'); | |
} | |
function negateAmount(v) { | |
if (v[0] == '-') { | |
return v.slice(1); | |
} | |
return '-' + v; | |
} | |
window.addEventListener('load', init, false); | |
function init() { | |
var r= $('<input type="button" value="new button"/>'); | |
$("#ttl_genyokinbreak_table").prepend(r); | |
r.on('click', runReport); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment