1
0

Handle transfers between own accounts
Some checks failed
Run Python tests (through Pytest) / Test (push) Failing after 23s
Verify Python project can be installed, loaded and have version checked / Test (push) Failing after 22s

This commit is contained in:
Jon Michael Aanes 2024-12-28 01:02:37 +01:00
parent 4e3ac4b693
commit c40ce86f27
Signed by: Jmaa
SSH Key Fingerprint: SHA256:Ab0GfHGCblESJx7JRE4fj4bFy/KRpeLhi41y4pF3sNA
2 changed files with 83 additions and 26 deletions

View File

@ -24,6 +24,7 @@ from decimal import Decimal
from collections import deque from collections import deque
from fin_depo.data import * from fin_depo.data import *
import datetime import datetime
import dataclassabc
import dataclasses import dataclasses
import logging import logging
import fin_data import fin_data
@ -42,9 +43,49 @@ logger = logging.getLogger(__name__)
FIN_DB = fin_data.FinancialDatabase(enable_kucoin=True, enable_nationalbanken_dk=True) FIN_DB = fin_data.FinancialDatabase(enable_kucoin=True, enable_nationalbanken_dk=True)
@dataclassabc.dataclassabc(frozen=True)
class TransferDetails(fin_depo.data.DoubleRegister):
withdrawal: fin_depo.data.WithdrawalDetails
deposit: fin_depo.data.DepositDetails
@property
def fee(self) -> AssetAmount | None:
return self.withdrawal.fee # TODO?
@property
def executed_time(self) -> datetime.datetime:
return self.withdrawal.executed_time
@property
def input(self) -> None:
return None
@property
def output(self) -> None:
return None
def collate_interaccount_transfers(transfers: list[fin_depo.data.DoubleRegister]) -> list[fin_depo.data.DoubleRegister]:
new_transfers = []
for t in transfers:
if isinstance(t, fin_depo.data.DepositDetails):
prev_transfer = new_transfers[-1] if len(new_transfers) > 0 else None
if isinstance(prev_transfer , fin_depo.data.WithdrawalDetails):
if prev_transfer.withdrawn == t.deposit:
del new_transfers[-1]
new_transfers.append(TransferDetails(prev_transfer, t))
continue
del prev_transfer
new_transfers.append(t)
del t
return new_transfers
def compute_fifo(transfers: list) -> TaxReport: def compute_fifo(transfers: list) -> TaxReport:
transfers.sort(key=lambda t:t.executed_time) transfers.sort(key=lambda t:t.executed_time)
transfers = collate_interaccount_transfers(transfers)
bought_and_sold_for: list[BoughtAndSold] = [] bought_and_sold_for: list[BoughtAndSold] = []
@ -52,7 +93,7 @@ def compute_fifo(transfers: list) -> TaxReport:
ledger_entries = [] ledger_entries = []
prices_bought_for: dict[Asset, deque[BoughtAndNotYetSold]] = {} prices_bought_for: dict[Asset, deque[BoughtAndNotYetSold]] = {}
if False: if True:
prices_bought_for[MPC] = deque() prices_bought_for[MPC] = deque()
# TODO: # TODO:
prices_bought_for[MPC].append(BoughtAndNotYetSold(AssetAmount(MPC, Decimal(80)), datetime.datetime(2024, 4,1,1,1,1,1))) prices_bought_for[MPC].append(BoughtAndNotYetSold(AssetAmount(MPC, Decimal(80)), datetime.datetime(2024, 4,1,1,1,1,1)))
@ -67,7 +108,8 @@ def compute_fifo(transfers: list) -> TaxReport:
amount = amount_to_sell amount = amount_to_sell
while amount.amount > 0: while amount.amount > 0:
if len(prices_bought_for[amount.asset]) == 0: if len(prices_bought_for[amount.asset]) == 0:
raise Exception('Miscalculation: ' + str(amount)) msg = f'Miscalculation: {amount} of {amount_to_sell}'
raise Exception(msg)
partial = prices_bought_for[amount.asset].popleft() partial = prices_bought_for[amount.asset].popleft()
amount_covered_by_partial = min(partial.amount, amount) amount_covered_by_partial = min(partial.amount, amount)
@ -116,6 +158,7 @@ def compute_fifo(transfers: list) -> TaxReport:
for transfer in transfers: for transfer in transfers:
# Sell # Sell
if _input := transfer.input: if _input := transfer.input:
variant = 'WITHDRAW' if transfer.output is None else 'SELL' variant = 'WITHDRAW' if transfer.output is None else 'SELL'
@ -130,6 +173,8 @@ def compute_fifo(transfers: list) -> TaxReport:
del variant del variant
del output del output
# TODO: Output line for transfer.
# Fee # Fee
if fee := transfer.fee: if fee := transfer.fee:
spend(fee, transfer.executed_time) spend(fee, transfer.executed_time)

View File

@ -55,13 +55,13 @@ def add_headers(sheet, column_headers):
cell.alignment = ALIGN_CENTER cell.alignment = ALIGN_CENTER
cell.border = BORDER_BOTTOM cell.border = BORDER_BOTTOM
def set_number_format(sheet, range): def set_number_format(sheet, range, format="0.00"):
for row in sheet[range]: for row in sheet[range]:
for cell in row: for cell in row:
cell.number_format = "0.00" cell.number_format = format
def write_current_assets(sheet, tax_report: TaxReport): def write_current_assets(sheet, tax_report: TaxReport):
column_headers = ['Værdipapir', 'Mængde', 'Kurs', 'Værdi (DKK)', column_headers = ['Værdipapir', 'Mængde', 'Kurs', 'Sum (DKK)',
'Beskatningstype'] 'Beskatningstype']
add_headers(sheet, column_headers) add_headers(sheet, column_headers)
row_idx = 2 row_idx = 2
@ -72,7 +72,7 @@ def write_current_assets(sheet, tax_report: TaxReport):
row = [ row = [
asset.raw_short_name(), asset.raw_short_name(),
total_amount, total_amount,
exchange_rate_asset_to_dkk, exchange_rate_asset_to_dkk or 'Unknown',
f'=B{row_idx}*C{row_idx}', f'=B{row_idx}*C{row_idx}',
TAX_TYPES[asset], TAX_TYPES[asset],
] ]
@ -97,7 +97,7 @@ def write_ledger_sheet(sheet, tax_report: TaxReport):
'Mængde', 'Mængde',
'Kontoudbyder', 'Kontoudbyder',
'' ''
] + [a.raw_short_name() for a in assets] ] + [a.raw_short_name() for a in assets] + ['', 'Kommentarer']
add_headers(sheet, column_headers) add_headers(sheet, column_headers)
row_idx = 2 row_idx = 2
@ -156,9 +156,9 @@ def write_fifo_sheet(sheet, bought_and_sold_for: list, exchange_rate_at_time) ->
'Mængde', 'Mængde',
'Anskaffelseskurs', 'Anskaffelseskurs',
'Salgskurs', 'Salgskurs',
'Anskaffelsesværdi (DKK)', 'Købssum (DKK)',
'Salgsværdi (DKK)', 'Salgssum (DKK)',
'Profit (DKK)', 'Tab (DKK)', 'Gevinst (DKK)', 'Tab (DKK)',
] ]
add_headers(sheet, column_headers) add_headers(sheet, column_headers)
row_idx = 2 row_idx = 2
@ -175,12 +175,12 @@ def write_fifo_sheet(sheet, bought_and_sold_for: list, exchange_rate_at_time) ->
fifo_entry.time_sold.replace(tzinfo=None), fifo_entry.time_sold.replace(tzinfo=None),
asset.raw_short_name(), asset.raw_short_name(),
fifo_entry.amount.amount, fifo_entry.amount.amount,
exchange_rate_dkk_bought, exchange_rate_dkk_bought or 'Unknown',
exchange_rate_dkk_sold, exchange_rate_dkk_sold or 'Unknown',
f'=F{row_idx}*D{row_idx}', f'=D{row_idx}*E{row_idx}',
f'=E{row_idx}*D{row_idx}', f'=D{row_idx}*F{row_idx}',
f'=max(0, G{row_idx} - H{row_idx})',
f'=max(0, H{row_idx} - G{row_idx})', f'=max(0, H{row_idx} - G{row_idx})',
f'=max(0, G{row_idx} - H{row_idx})',
] ]
sheet.append(row) sheet.append(row)
row_idx+= 1 row_idx+= 1
@ -245,26 +245,33 @@ def write_overview(sheet, tax_report: TaxReport, sums):
sheet['A9'] = 'Ledger' sheet['A9'] = 'Ledger'
sheet['B9'] = 'Afdækker alle handler og overførsler.' sheet['B9'] = 'Afdækker alle handler og overførsler.'
sheet['A10'] = 'FIFO Stablecoin' sheet['A10'] = 'FIFO Stablecoin'
sheet['B10'] = 'Beregner profit og tab for stablecoins ved FIFO-pricippet.' sheet['B10'] = 'Beregner gevinst og tab for stablecoins ved FIFO-pricippet.'
sheet['A11'] = 'FIFO Kryptovaluta' sheet['A11'] = 'FIFO Kryptovaluta'
sheet['B11'] = 'Beregner profit og tab for kryptovaluta ved FIFO-pricippet.' sheet['B11'] = 'Beregner gevinst og tab for kryptovaluta ved FIFO-pricippet.'
sheet['A12'] = 'FIFO Fiat' sheet['A12'] = 'FIFO Fiat'
sheet['B12'] = 'Beregner profit og tab for udenlandsk valuta ved FIFO-pricippet.' sheet['B12'] = 'Beregner gevinst og tab for udenlandsk valuta ved FIFO-pricippet.'
# Beregnet kolonner # Beregnet kolonner
sheet['D6'] = 'Beregnet Skatte Kolonnner' # TODO sheet['D6'] = 'Beregnet Skatte Rubrikker' # TODO
sheet.merge_cells('D6:E6') sheet.merge_cells('D6:E6')
sheet['A4'].alignment = ALIGN_CENTER sheet['A4'].alignment = ALIGN_CENTER
sheet['D7'] = 'Kolonne' # TODO sheet['D7'] = 'Rubrik' # TODO
sheet['E7'] = 'Værdi' sheet['E7'] = 'Værdi'
sheet['D8'] = 'Profit Krypto'
sheet['D8'] = 'Rubrik 20'
sheet['E8'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][0] sheet['E8'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][0]
sheet['D9'] = 'Tab Krypto' sheet['F8'] = '(Gevinst ved kryptospekulation)'
sheet['G8'] = 'Kilde: https://skat.dk/borger/aktier-og-andre-vaerdipapirer/skat-paa-krypto-kend-reglerne-saa-du-undgaar-et-skattesmaek/beregn-og-oplys-gevinst-og-tab-paa-krypto'
sheet['D9'] = 'Rubrik 58'
sheet['E9'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][1] sheet['E9'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][1]
sheet['D10'] = 'Profit Stable Coin' sheet['F9'] = '(Tab ved kryptospekulation)'
sheet['E10'] = '=$\'FIFO Stable Coin\'.'+sums['Stable Coin'][0] sheet['G10'] = 'Kilde: https://skat.dk/borger/aktier-og-andre-vaerdipapirer/skat-paa-krypto-kend-reglerne-saa-du-undgaar-et-skattesmaek/beregn-og-oplys-gevinst-og-tab-paa-krypto'
sheet['D11'] = 'Profit Stable Coin'
sheet['E11'] = '=$\'FIFO Stable Coin\'.'+sums['Stable Coin'][1] sheet['D10'] = 'Rubrik 346'
sheet['E10'] = f"=$'FIFO Stable Coin'.{sums['Stable Coin'][0]}'-$'FIFO Stable Coin'.{sums['Stable Coin'][1]}'"
sheet['F10'] = '(Gevinst og Tab ved Stable Coin / Financiel Kontrakt)'
sheet['G10'] = 'Kilde: https://skat.dk/borger/aktier-og-andre-vaerdipapirer/skat-paa-krypto-kend-reglerne-saa-du-undgaar-et-skattesmaek/stablecoins-finansielle-kontrakter'
# Disclaimer # Disclaimer
@ -275,6 +282,11 @@ def write_overview(sheet, tax_report: TaxReport, sums):
sheet.column_dimensions['B'].width = 70 sheet.column_dimensions['B'].width = 70
sheet.row_dimensions[4].height = 60 sheet.row_dimensions[4].height = 60
sheet.column_dimensions['D'].width = 20
sheet.column_dimensions['E'].width = 20
sheet.column_dimensions['F'].width = 50
sheet.column_dimensions['G'].width = 80
def produce_excel_report(report: TaxReport, output_path: Path): def produce_excel_report(report: TaxReport, output_path: Path):
workbook = openpyxl.Workbook() workbook = openpyxl.Workbook()