Compare commits

...

1 Commits

Author SHA1 Message Date
1e15a6b077 CLI changes for MyStocksPortfolio 2022-02-06 10:15:13 -05:00
6 changed files with 330 additions and 26 deletions

View File

@ -35,6 +35,16 @@
<version>1.0-SNAPSHOT</version>
<classifier>jersey</classifier>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>

View File

@ -3,19 +3,54 @@ package com.inteligr8.buxfer;
import java.io.IOException;
import java.io.OutputStream;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.inteligr8.buxfer.model.Transaction;
import com.inteligr8.buxfer.msp.MyStocksPortfolioTransaction;
public class CsvTransactionWriter implements Observer<Transaction> {
public abstract class CsvTransactionWriter<T> implements Observer<Transaction> {
private final OutputStream ostream;
private final CsvMapper mapper;
private final CsvSchema schema;
public CsvTransactionWriter(OutputStream ostream) {
public CsvTransactionWriter(OutputStream ostream, Class<T> txClass) {
this.ostream = ostream;
this.mapper = CsvMapper.builder().build();
this.mapper.registerModule(new JavaTimeModule());
if (txClass == null) {
this.schema = this.mapper.schema().withHeader();
} else {
this.schema = this.mapper.schemaFor(txClass).withHeader();
}
}
@Override
public int observed(Transaction tx) throws IOException {
return 0;
try {
ParsedTransaction ptx = NormalizedParser.getInstance().parse(tx);
return this.observed(ptx);
} catch (IllegalArgumentException iae) {
return 0;
}
}
public int observed(ParsedTransaction ptx) throws IOException {
if (ptx.getContractType() != null)
return 0;
Object otx = this.mapTransaction(ptx);
this.mapper.writerFor(MyStocksPortfolioTransaction.class)
.with(this.schema)
.writeValue(this.ostream, otx);
return 1;
}
protected abstract Object mapTransaction(ParsedTransaction ptx);
}

View File

@ -1,11 +0,0 @@
package com.inteligr8.buxfer;
import java.io.OutputStream;
public class MyStockPortfolioCsvTransactionWriter extends CsvTransactionWriter {
public MyStockPortfolioCsvTransactionWriter(OutputStream ostream) {
super(ostream);
}
}

View File

@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory;
import com.inteligr8.buxfer.api.CommandApi;
import com.inteligr8.buxfer.model.Transaction;
import com.inteligr8.buxfer.model.TransactionsResponse;
import com.inteligr8.buxfer.msp.MyStocksPortfolioCsvTransactionWriter;
public class WriterCLI {
@ -27,8 +28,7 @@ public class WriterCLI {
private enum Format {
Json,
Csv,
MyStockPortfolioCsv("my-stock-portfolio-csv");
MyStocksPortfolioCsv("my-stocks-portfolio-csv");
private final String key;
private Format() {
@ -91,13 +91,15 @@ public class WriterCLI {
for (Transaction tx : response.getItems())
observer.observed(tx);
break;
}
}
private static Options buildOptions() {
return new Options()
.addOption(new Option("u", "email", true, "A Buxfer email for authentication"))
.addOption(new Option("p", "password", true, "A Buxfer password for authentication"))
.addOption(new Option("bu", "buxfer-email", true, "A Buxfer email for authentication"))
.addOption(new Option("bp", "buxfer-password", true, "A Buxfer password for authentication"))
.addOption(new Option("t", "format", true, "The output format [json | csv | my-stock-portfolio-csv]"))
.addOption(new Option("f", "file", true, "The output filename"))
.addOption(new Option(null, "portfolio-name", true, "The portfolio name where applicable"));
@ -110,7 +112,7 @@ public class WriterCLI {
private static File determineFile(CommandLine cli) {
Format format = Format.valueByKey(cli.getOptionValue("format", "json"));
String filename = cli.hasOption("file") ? cli.getOptionValue("file") : "portfolio";
String filename = cli.hasOption("file") ? cli.getOptionValue("file") : cli.getOptionValue("portfolio-name", "portfolio");
if (filename.lastIndexOf('.') < 0) {
switch (format) {
case Json:
@ -129,10 +131,10 @@ public class WriterCLI {
switch (format) {
case Json:
return new JsonTransactionWriter(ostream);
case MyStockPortfolioCsv:
return new MyStockPortfolioCsvTransactionWriter(ostream);
case MyStocksPortfolioCsv:
return new MyStocksPortfolioCsvTransactionWriter(ostream, cli.getOptionValue("portfolio-name"));
default:
return new CsvTransactionWriter(ostream);
throw new IllegalArgumentException();
}
}
@ -140,10 +142,10 @@ public class WriterCLI {
BuxferClientConfiguration config = new BuxferClientConfiguration();
config.setBaseUrl("https://www.buxfer.com");
if (cli.hasOption("email"))
config.setAuthEmail(cli.getOptionValue("email"));
if (cli.hasOption("password"))
config.setAuthPassword(cli.getOptionValue("password"));
if (cli.hasOption("buxfer-email"))
config.setAuthEmail(cli.getOptionValue("buxfer-email"));
if (cli.hasOption("buxfer-password"))
config.setAuthPassword(cli.getOptionValue("buxfer-password"));
BuxferClientJerseyImpl client = new BuxferClientJerseyImpl(config);
return client.getApi().getCommandApi();

View File

@ -0,0 +1,30 @@
package com.inteligr8.buxfer.msp;
import java.io.OutputStream;
import java.time.ZoneId;
import com.inteligr8.buxfer.CsvTransactionWriter;
import com.inteligr8.buxfer.ParsedTransaction;
public class MyStocksPortfolioCsvTransactionWriter extends CsvTransactionWriter<MyStocksPortfolioTransaction> {
private long nextId;
public MyStocksPortfolioCsvTransactionWriter(OutputStream ostream, String portfolioName) {
super(ostream, MyStocksPortfolioTransaction.class);
this.nextId = 1L;
}
@Override
protected Object mapTransaction(ParsedTransaction ptx) {
MyStocksPortfolioTransaction msptx = new MyStocksPortfolioTransaction();
msptx.setId(this.nextId++);
msptx.setDatetime(ptx.getTransaction().getDate().atStartOfDay(ZoneId.systemDefault()).toOffsetDateTime());
msptx.setCurrency("USD");
msptx.setSymbol(ptx.getSecuritySymbol());
msptx.setQuantity((int)ptx.getSecurities());
msptx.setPricePerShare(ptx.getPricePerSecurity());
return msptx;
}
}

View File

@ -0,0 +1,238 @@
package com.inteligr8.buxfer.msp;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonPropertyOrder({
"Id",
"Symbol",
"Name",
"DisplaySymbol",
"Exchange",
"Portfolio",
"Currency",
"Quantity",
"Cost Per Share",
"Cost Basis Method",
"Commission",
"Date",
"TimeOfDay",
"PurchaseFX",
"Type",
"Method",
"Method Execution Ids",
"Notes"
})
public class MyStocksPortfolioTransaction {
public enum Type {
Buy,
Sell,
Dividend
}
public enum Method {
FIFO
}
@JsonProperty("Id")
private Long id;
@JsonProperty("Symbol")
private String symbol;
@JsonProperty("Name")
private String name;
@JsonProperty("DisplaySymbol")
private String symbolDisplay;
@JsonProperty("Exchange")
private String exchange;
@JsonProperty("Portfolio")
private String portfolio;
@JsonProperty("Currency")
private String currency;
@JsonProperty("Quantity")
private Integer quantity;
@JsonProperty("Cost Per Share")
private Double pricePerShare;
@JsonProperty("Cost Basis Method")
private Double costBasisMethod;
@JsonProperty("Commission")
private Double commission;
private OffsetDateTime datetime;
@JsonProperty("PurchaseFX")
private String fx;
@JsonProperty("Type")
private Type type;
@JsonProperty("Method")
private Method method;
@JsonProperty("Method Execution Ids")
private String methodExecutionId;
@JsonProperty("Notes")
private String notes;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSymbolDisplay() {
return symbolDisplay;
}
public void setSymbolDisplay(String symbolDisplay) {
this.symbolDisplay = symbolDisplay;
}
public String getExchange() {
return exchange;
}
public void setExchange(String exchange) {
this.exchange = exchange;
}
public String getPortfolio() {
return portfolio;
}
public void setPortfolio(String portfolio) {
this.portfolio = portfolio;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public Double getPricePerShare() {
return pricePerShare;
}
public void setPricePerShare(Double pricePerShare) {
this.pricePerShare = pricePerShare;
}
public Double getCostBasisMethod() {
return costBasisMethod;
}
public void setCostBasisMethod(Double costBasisMethod) {
this.costBasisMethod = costBasisMethod;
}
public Double getCommission() {
return commission;
}
public void setCommission(Double commission) {
this.commission = commission;
}
@JsonProperty("Date")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd Z")
public OffsetDateTime getDateTz() {
return this.datetime;
}
@JsonProperty("TimeOfDay")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "hh:mm:ss")
public LocalTime getTime() {
return this.datetime.toLocalTime();
}
public void setDatetime(OffsetDateTime datetime) {
this.datetime = datetime;
}
public String getFx() {
return fx;
}
public void setFx(String fx) {
this.fx = fx;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public String getMethodExecutionId() {
return methodExecutionId;
}
public void setMethodExecutionId(String methodExecutionId) {
this.methodExecutionId = methodExecutionId;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}