148 lines
5.0 KiB
Python
148 lines
5.0 KiB
Python
import sys
|
|
import requests
|
|
import fin_depo
|
|
from . import secrets
|
|
import fin_defs
|
|
from decimal import Decimal
|
|
from collections import deque
|
|
from fin_depo.data import *
|
|
import datetime
|
|
import dataclasses
|
|
import logging
|
|
|
|
from .data import TaxReport, BoughtAndSold, BoughtAndNotYetSold
|
|
from pathlib import Path
|
|
|
|
import openpyxl
|
|
import openpyxl.styles
|
|
|
|
TAX_TYPES: dict[fin_defs.Asset, str] = {
|
|
fin_defs.DKK: 'Fiat',
|
|
fin_defs.EUR: 'Fiat',
|
|
fin_defs.BTC: 'Krypto-valuta',
|
|
fin_defs.MPC: 'Krypto-valuta',
|
|
fin_defs.WELL_KNOWN_SYMBOLS['MATIC']: 'Krypto-valuta',
|
|
fin_defs.USDT: 'Stable Coin (Financiel Kontrakt)',
|
|
}
|
|
|
|
NOW = datetime.datetime.now(tz=datetime.UTC)
|
|
|
|
def mult_a(a, b):
|
|
if a == 0 or b == 0:
|
|
return 0
|
|
if a is None or b is None:
|
|
return 'Unknown'
|
|
return a * b
|
|
|
|
BOLD_FONT = openpyxl.styles.Font(bold=True)
|
|
ALIGN_CENTER = openpyxl.styles.Alignment(horizontal="center", vertical="center")
|
|
|
|
def add_headers(sheet, column_headers):
|
|
sheet.append(column_headers)
|
|
for row in sheet['A1:J1']:
|
|
for cell in row:
|
|
cell.font = BOLD_FONT
|
|
|
|
def write_current_assets(sheet, tax_report: TaxReport):
|
|
column_headers = ['Værdipapir', 'Mængde', 'Estimeret værdi (DKK)',
|
|
'Beskatningstype']
|
|
add_headers(sheet, column_headers)
|
|
for asset, positions in tax_report.current_assets.items():
|
|
total_amount: Decimal = sum((p.amount.amount for p in positions), start=Decimal(0))
|
|
exchange_rate_asset_to_dkk = tax_report.exchange_rate_at_time(asset, fin_defs.DKK, NOW)
|
|
#assert exchange_rate_asset_to_dkk is not None, asset
|
|
row = [
|
|
asset.raw_short_name(),
|
|
total_amount,
|
|
mult_a(total_amount, exchange_rate_asset_to_dkk),
|
|
TAX_TYPES[asset],
|
|
]
|
|
sheet.append(row)
|
|
del asset, positions, row, total_amount
|
|
|
|
def write_ledger_sheet(sheet, tax_report: TaxReport):
|
|
assets = list({e.amount.asset for e in tax_report.ledger_entries})
|
|
|
|
column_headers = [
|
|
'Tidspunkt (UTC)',
|
|
'Type',
|
|
'Værdipapir',
|
|
'Mængde',
|
|
'Balance',
|
|
'Kontoudbyder',
|
|
''
|
|
] + [a.raw_short_name() for a in assets]
|
|
|
|
add_headers(sheet, column_headers)
|
|
row_idx = 2
|
|
prev_entry_time = None
|
|
start_of_same_entry = 2
|
|
for ledger_entry in tax_report.ledger_entries:
|
|
entry_time = ledger_entry.time.replace(tzinfo=None,microsecond=0,fold=0)
|
|
row = [
|
|
entry_time,
|
|
ledger_entry.type,
|
|
ledger_entry.amount.asset.raw_short_name(),
|
|
ledger_entry.amount.amount,
|
|
ledger_entry.balance.amount,
|
|
ledger_entry.account_provider,
|
|
'',
|
|
] + [(ledger_entry.balance.amount if ledger_entry.balance.asset == a else '') for a in assets]
|
|
sheet.append(row)
|
|
row_idx+= 1
|
|
|
|
if entry_time != prev_entry_time:
|
|
# TODO:
|
|
sheet.merge_cells(f'A{start_of_same_entry}:A{row_idx-1}')
|
|
sheet[f'A{start_of_same_entry}'].alignment = ALIGN_CENTER
|
|
start_of_same_entry = row_idx
|
|
prev_entry_time = entry_time
|
|
del ledger_entry, row
|
|
|
|
|
|
def write_fifo_sheet(sheet, tax_report: TaxReport):
|
|
# TODO: Account for transfers
|
|
column_headers = [
|
|
'Værdipapir', 'Mængde', 'Anskaffelsesværdi (DKK)', 'Købsdato (UTC)',
|
|
'Salgsværdi (DKK)', 'Salgsdato (UTC)', 'Profit (DKK)', 'Tab (DKK)',
|
|
'Beskatningstype',
|
|
]
|
|
add_headers(sheet, column_headers)
|
|
row_idx = 2
|
|
for fifo_entry in tax_report.bought_and_sold_for:
|
|
asset = fifo_entry.amount.asset
|
|
|
|
exchange_rate_dkk_bought = tax_report.exchange_rate_at_time(asset, fin_defs.DKK, fifo_entry.time_bought)
|
|
#assert exchange_rate_dkk_bought is not None, asset
|
|
exchange_rate_dkk_sold = tax_report.exchange_rate_at_time(asset, fin_defs.DKK, fifo_entry.time_sold)
|
|
#assert exchange_rate_dkk_bought is not None, asset
|
|
|
|
row = [
|
|
asset.raw_short_name(),
|
|
fifo_entry.amount.amount,
|
|
mult_a(fifo_entry.amount.amount , exchange_rate_dkk_bought),
|
|
fifo_entry.time_bought.replace(tzinfo=None),
|
|
mult_a(fifo_entry.amount.amount , exchange_rate_dkk_sold),
|
|
fifo_entry.time_sold.replace(tzinfo=None),
|
|
f'=max(0, E{row_idx} - C{row_idx})',
|
|
f'=max(0, C{row_idx} - E{row_idx})',
|
|
TAX_TYPES[asset],
|
|
]
|
|
sheet.append(row)
|
|
row_idx+= 1
|
|
del fifo_entry, asset, row
|
|
|
|
def produce_excel_report(report: TaxReport, output_path: Path):
|
|
workbook = openpyxl.Workbook()
|
|
|
|
workbook.active.title = 'Current Assets'
|
|
write_current_assets(workbook.active, report)
|
|
|
|
sheet_ledger = workbook.create_sheet('Ledger')
|
|
write_ledger_sheet(sheet_ledger , report)
|
|
|
|
sheet_fifo = workbook.create_sheet('FIFO')
|
|
write_fifo_sheet(sheet_fifo, report)
|
|
|
|
workbook.save(output_path)
|