Several improvements and bug fixes for 2025 tax return #25
57
cmd/any2anexoj-cli/csv_writer.go
Normal file
57
cmd/any2anexoj-cli/csv_writer.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/nmoniz/any2anexoj/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CSVWriter struct {
|
||||||
|
w *csv.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCSVWriter(w io.Writer) *CSVWriter {
|
||||||
|
return &CSVWriter{w: csv.NewWriter(w)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cw *CSVWriter) Render(aw *internal.AggregatorWriter) error {
|
||||||
|
err := cw.w.Write([]string{
|
||||||
|
"source_country", "code",
|
||||||
|
"realization_year", "realization_month", "realization_day", "realization_value",
|
||||||
|
"acquisition_year", "acquisition_month", "acquisition_day", "acquisition_value",
|
||||||
|
"expenses", "foreign_tax_paid", "counter_country",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write csv header: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ri := range aw.Iter() {
|
||||||
|
err := cw.w.Write(reportItemToRow(ri))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write csv row: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cw.w.Flush()
|
||||||
|
return cw.w.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func reportItemToRow(ri internal.ReportItem) []string {
|
||||||
|
return []string{
|
||||||
|
fmt.Sprintf("%d", ri.AssetCountry),
|
||||||
|
string(ri.Nature),
|
||||||
|
fmt.Sprintf("%d", ri.SellTimestamp.Year()),
|
||||||
|
fmt.Sprintf("%d", int(ri.SellTimestamp.Month())),
|
||||||
|
fmt.Sprintf("%d", ri.SellTimestamp.Day()),
|
||||||
|
ri.SellValue.StringFixed(2),
|
||||||
|
fmt.Sprintf("%d", ri.BuyTimestamp.Year()),
|
||||||
|
fmt.Sprintf("%d", int(ri.BuyTimestamp.Month())),
|
||||||
|
fmt.Sprintf("%d", ri.BuyTimestamp.Day()),
|
||||||
|
ri.BuyValue.StringFixed(2),
|
||||||
|
ri.Fees.StringFixed(2),
|
||||||
|
ri.Taxes.StringFixed(2),
|
||||||
|
fmt.Sprintf("%d", ri.BrokerCountry),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ var (
|
|||||||
platform = pflag.StringP("platform", "p", "trading212", "One of the supported platforms")
|
platform = pflag.StringP("platform", "p", "trading212", "One of the supported platforms")
|
||||||
lang = pflag.StringP("language", "l", language.Portuguese.String(), "The 2 letter language code")
|
lang = pflag.StringP("language", "l", language.Portuguese.String(), "The 2 letter language code")
|
||||||
debug = pflag.BoolP("debug", "d", false, "Activate to log debug messages")
|
debug = pflag.BoolP("debug", "d", false, "Activate to log debug messages")
|
||||||
|
format = pflag.StringP("format", "f", "table", "Output format: table or csv")
|
||||||
ofAPIKey = pflag.String("open-figi-api-key", "", "An OpenFIGI API key for faster report generation (better rate api rate limits)")
|
ofAPIKey = pflag.String("open-figi-api-key", "", "An OpenFIGI API key for faster report generation (better rate api rate limits)")
|
||||||
// TODO: improve documentation on selectors
|
// TODO: improve documentation on selectors
|
||||||
selectors = pflag.StringSlice("selectors", nil, "Only process entries that conform to all the selectors:")
|
selectors = pflag.StringSlice("selectors", nil, "Only process entries that conform to all the selectors:")
|
||||||
@@ -80,16 +81,19 @@ func run(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch *format {
|
||||||
|
case "csv":
|
||||||
|
return NewCSVWriter(os.Stdout).Render(writer)
|
||||||
|
case "table":
|
||||||
loc, err := NewLocalizer(*lang)
|
loc, err := NewLocalizer(*lang)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("create localizer: %w", err)
|
return fmt.Errorf("create localizer: %w", err)
|
||||||
}
|
}
|
||||||
|
NewPrettyPrinter(os.Stdout, loc).Render(writer)
|
||||||
printer := NewPrettyPrinter(os.Stdout, loc)
|
|
||||||
|
|
||||||
printer.Render(writer)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported format %q: must be table or csv", *format)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReader(platform string, ofAPIKey string) (internal.RecordReader, error) {
|
func getReader(platform string, ofAPIKey string) (internal.RecordReader, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user