|
// ==UserScript== |
|
// @name Postfinance CSV Export |
|
// @namespace http://death-knight.com |
|
// @include https://www.postfinance.ch/ap/ra/ob/html/finance/* |
|
// @updateURL https://gist.github.com/weiserr/bc0745d3145b29f02b1d/raw/postfinance-ynab.user.js |
|
// @downloadURL https://gist.github.com/weiserr/bc0745d3145b29f02b1d/raw/postfinance-ynab.user.js |
|
// @version 16 |
|
// @grant none |
|
// ==/UserScript== |
|
|
|
// Function definitions |
|
function createGenerateButton() { |
|
let input = document.createElement("button"); |
|
input.type = "button"; |
|
input.className = "ynab-button appearance-none before:absolute before:bg-inherit before:border before:border-inherit before:disabled:opacity-0 before:duration-150 before:ease-in-out before:hover:opacity-100 before:inset-[-3px] before:opacity-0 before:rounded-max before:transform before:transition-opacity before:z-[-1] bg-fpui-button-primary-background-color border border-fpui-button-primary-border-color border-solid cc-text-sm disabled:bg-fpui-button-primary-background-disabled-color disabled:border-fpui-button-primary-border-disabled-color disabled:text-fpui-button-primary-text-disabled-color fpui-button gap-2 h-13 inline-flex items-center leading-none p-3 place-content-center place-items-center relative rounded-max sm:w-auto text-center text-fpui-button-primary-text-color w-full xs:px-8 xs:py-4 z-0"; |
|
input.textContent = "YNAB Export"; |
|
input.onclick = createExportButton; |
|
|
|
document.querySelectorAll('fpui-actions').forEach(elem => {if(elem.querySelectorAll(".ynab-button").length < 1) {elem.appendChild(input)}}); |
|
} |
|
|
|
function createExportButton() { |
|
const csv = createCSV(); |
|
const date = new Date(); |
|
const year = date.getFullYear(); |
|
const month = date.getMonth() + 1; |
|
const day = date.getDate(); |
|
const filename = "ynab-" + year + "-" + month + "-" + day + ".csv"; |
|
|
|
// create a temporary download link |
|
let input = document.createElement("a"); |
|
input.setAttribute('href', 'data:text/csv;charset=UTF-8,' + encodeURIComponent(csv)); |
|
input.setAttribute('download', filename); |
|
input.style.display = 'none'; |
|
|
|
// ...and click it to trigger the download |
|
document.body.appendChild(input); |
|
input.click(); |
|
document.body.removeChild(input); |
|
} |
|
|
|
function createCSV() { |
|
// acquire the data computed by the Post |
|
const rows = Array.from(document.querySelector('[data-cy="movements-table"] > tbody').querySelectorAll("tr")); |
|
|
|
// process the content |
|
let result = rows.map((row, index) => sanitizeRow(row)); |
|
|
|
// add the header |
|
result.unshift(createHeader()); |
|
|
|
// join the results into a single string |
|
return result.join("\n"); |
|
} |
|
|
|
function createHeader() { |
|
return 'Date,Payee,Category,Memo,Outflow,Inflow'; |
|
} |
|
|
|
function sanitizeRow(row) { |
|
const date = row.querySelector('[data-cy="date"] > span:nth-child(2)').textContent; |
|
const payee = row.querySelector('[data-cy="shortText"] > span:nth-child(2)').textContent.replace(/\"/gi, '').replace(/\n/gi, ' ').replace(/,/gi, '; ').trim(); |
|
const category = ''; |
|
const memo = ''; |
|
const outflow = row.querySelector('[data-cy="debit"] fpui-amount > span:nth-child(1)')?.textContent?.replace(/[^\d\.]/g, '')?.trim() ?? ''; |
|
const inflow = row.querySelector('[data-cy="credit"] fpui-amount > span:nth-child(1)')?.textContent?.replace(/[^\d\.]/g, '')?.trim() ?? ''; |
|
|
|
let line = []; |
|
line.push(date); |
|
line.push(payee); |
|
line.push(category); |
|
line.push(memo); |
|
line.push(outflow); |
|
line.push(inflow); |
|
|
|
return line.join(','); |
|
} |
|
|
|
function waitForElem(selector) { |
|
if (document.URL == "https://www.postfinance.ch/ap/ra/ob/html/finance/assets/movements-overview" && document.querySelector(selector)) { |
|
createGenerateButton(); |
|
} |
|
|
|
const observer = new MutationObserver((mutations) => { |
|
if (document.URL == "https://www.postfinance.ch/ap/ra/ob/html/finance/assets/movements-overview" && document.querySelector(selector)) { |
|
createGenerateButton(); |
|
} |
|
}); |
|
|
|
observer.observe(document.body, { |
|
childList: true, |
|
subtree: true, |
|
}); |
|
} |
|
|
|
|
|
waitForElem('fpui-actions'); |
Hi, there is a bug, every transactions goes to the inflow column of YNAB. VNAB understand that value with minus at the end should be swaped so either leave all transaction in the inflow column with the minus for the outflow transactions, either put the outflow transaction in the outflow colum and remove the minus on the value.