Last active
April 13, 2024 14:57
-
-
Save robin-hartmann/b70cde63135fd1b06472e9e6a89c30cc to your computer and use it in GitHub Desktop.
UserScript to copy a transaction activity from Scalable Capital
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 Copy Activity | |
// @namespace https://robin-hartmann.com/ | |
// @version 1.0.9 | |
// @description Copy Activity | |
// @author robin-hartmann | |
// @match https://de.scalable.capital/* | |
// @grant none | |
// @noframes | |
// ==/UserScript== | |
'use strict'; | |
(function () { | |
window.addEventListener('copy', async (e) => { | |
if (!window.getSelection().isCollapsed) { | |
return; | |
} | |
try { | |
const activity = await getActivity(); | |
if (!activity) { | |
return; | |
} | |
e.preventDefault(); | |
e.clipboardData.setData('text/plain', activity); | |
} catch (error) { | |
alert('error while copying activity:\n' + error); | |
} | |
}); | |
})(); | |
async function getActivity() { | |
const sellSvg = document.querySelectorAll('svg[data-testid="icon-SELL"]')[0]; | |
const buySvg = document.querySelectorAll('svg[data-testid="icon-BUY"],svg[data-testid="icon-SAVINGS_PLAN"]')[0]; | |
const type = sellSvg ? 'sell' : buySvg ? 'buy' : undefined; | |
if (!type) { | |
return undefined; | |
} | |
// TODO assert exactly one match | |
const shareLink = document.querySelectorAll('.MuiDialog-container a')[0]; | |
const shareUrl = new URL(shareLink.href); | |
const shareName = shareUrl.searchParams.get('isin'); | |
const shareCountSpan = document.querySelectorAll( | |
'[data-testid="value-Ausgeführte Stückzahl"] span' | |
)[0]; | |
const shareCount = shareCountSpan.textContent | |
.trim() | |
.replaceAll('.', '') | |
.replace(',', '.'); | |
const shareValueDiv = document.querySelectorAll( | |
'div[data-testid="value-Ausführungspreis"]' | |
)[0]; | |
// TODO assert none to multiple '.', exactly one ',', exactly one '€' | |
const shareValue = shareValueDiv.textContent | |
.trim() | |
.replaceAll('.', '') | |
.replace(',', '.') | |
.replace(' €', ''); | |
const totalValueDiv = document.querySelectorAll( | |
'div[data-testid="value-Kurswert"]' | |
)[0]; | |
const totalValue = totalValueDiv.textContent | |
.trim() | |
.replaceAll('.', '') | |
.replace(',', '.') | |
.replace(' €', ''); | |
const feesDiv = document.querySelectorAll( | |
'div[data-testid="value-Ordergebühr"]' | |
)[0]; | |
const fees = | |
feesDiv?.textContent | |
.replaceAll('.', '') | |
.replace(',', '.') | |
.replace(' €', '') || '0.00'; | |
const taxesDiv = document.querySelectorAll( | |
'div[data-testid="value-Steuern"]' | |
)[0]; | |
const taxes = | |
taxesDiv?.textContent | |
.replaceAll('.', '') | |
.replace(',', '.') | |
.replace(' €', '') || '0.00'; | |
const billDiv = document.querySelectorAll( | |
'div[data-testid="value-Wertpapierabrechnung"]' | |
)[0]; | |
const executionConfirmedLikeDivs = document.querySelectorAll( | |
'.MuiGrid-container.MuiGrid-item > div.MuiGrid-root.MuiGrid-item' | |
); | |
const executionConfirmedDiv = Array.from(executionConfirmedLikeDivs).filter( | |
(value) => value.textContent === 'Ausführung bestätigt' | |
)[0]; | |
const timestampDiv = executionConfirmedDiv.nextSibling; | |
const timestamp = new Date( | |
timestampDiv.textContent | |
.replace('Mär', 'Mar') | |
.replace('Mai', 'May') | |
.replace('Okt', 'Oct') | |
.replace('Dez', 'Dec') | |
); | |
const isoTimestamp = new Date( | |
timestamp.getTime() - timestamp.getTimezoneOffset() * 60 * 1000 | |
); | |
const date = isoTimestamp.toISOString().split('T')[0]; | |
const time = isoTimestamp.toISOString().split('T')[1].slice(0, 5); | |
const activity = { | |
type, | |
shareName, | |
shareCount, | |
shareValue, | |
totalValue, | |
fees, | |
taxes, | |
date, | |
time, | |
}; | |
shareLink.style.color = 'green'; | |
if (!billDiv && type === 'sell') { | |
alert("bill isn't available yet, taxes may be missing"); | |
} | |
return JSON.stringify(activity, null, 2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment