package name.abuchen.portfolio.checks.impl; import java.text.MessageFormat; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collections; import java.util.List; import name.abuchen.portfolio.Messages; import name.abuchen.portfolio.checks.Check; import name.abuchen.portfolio.checks.Issue; import name.abuchen.portfolio.checks.QuickFix; import name.abuchen.portfolio.model.Client; import name.abuchen.portfolio.model.Portfolio; import name.abuchen.portfolio.model.PortfolioTransaction; import name.abuchen.portfolio.model.Security; import name.abuchen.portfolio.money.Values; public class SharesHeldConsistencyCheck implements Check { private static class SharesIssue implements Issue { private Portfolio portfolio; private Security security; private long shares; public SharesIssue(Portfolio portfolio, Security security, long shares) { super(); this.portfolio = portfolio; this.security = security; this.shares = shares; } @Override public LocalDate getDate() { return null; } @Override public Object getEntity() { return portfolio; } @Override public Long getAmount() { return null; } @Override public String getLabel() { return MessageFormat.format(Messages.IssueInconsistentSharesHeld, security, portfolio, Values.Share.format(shares)); } @Override public List<QuickFix> getAvailableFixes() { return Collections.emptyList(); } } @Override public List<Issue> execute(Client client) { List<Issue> issues = new ArrayList<Issue>(); List<Security> securities = client.getSecurities(); for (Portfolio portfolio : client.getPortfolios()) { long[] shares = new long[securities.size()]; for (PortfolioTransaction t : portfolio.getTransactions()) { int index = securities.indexOf(t.getSecurity()); // negative index means either the security is not known to the // global collection or the security is null -> other checks if (index < 0) continue; switch (t.getType()) { case BUY: case TRANSFER_IN: case DELIVERY_INBOUND: shares[index] += t.getShares(); break; case SELL: case TRANSFER_OUT: case DELIVERY_OUTBOUND: shares[index] -= t.getShares(); break; default: throw new UnsupportedOperationException(); } } for (int ii = 0; ii < shares.length; ii++) { if (shares[ii] < 0) { Security security = securities.get(ii); issues.add(new SharesIssue(portfolio, security, shares[ii])); } } } return issues; } }