From ea7a14dcc3c8678d2104b3887bc1244f88399bce Mon Sep 17 00:00:00 2001 From: ZfT2 Date: Thu, 5 Feb 2026 22:05:46 +0100 Subject: [PATCH 1/5] Introduce ex-date field for dividend transactions to PP model --- .../ReadingHistoricClientFilesTest.java | 19 +- .../client69.binary+pwd.portfolio | Bin 0 -> 1754 bytes .../fileversions/client69.binary.portfolio | Bin 0 -> 1737 bytes .../src/fileversions/client69.xml | 264 +++++++++++++++ .../datatransfer/ExtractorMatchers.java | 25 ++ .../actions/DetectDuplicatesActionTest.java | 2 +- .../name/abuchen/portfolio/ui/Messages.java | 1 + .../AccountTransactionDialog.java | 12 + .../transactions/AccountTransactionModel.java | 18 +- .../abuchen/portfolio/ui/messages.properties | 4 + .../portfolio/ui/messages_de.properties | 2 + .../model/proto/v1/ClientProtos.java | 194 +++++------ .../model/proto/v1/PTransaction.java | 319 ++++++++++++++---- .../model/proto/v1/PTransactionOrBuilder.java | 15 + .../portfolio/model/AccountTransaction.java | 20 ++ .../name/abuchen/portfolio/model/Client.java | 2 +- .../portfolio/model/ClientFactory.java | 3 +- .../portfolio/model/ProtobufWriter.java | 4 + .../name/abuchen/portfolio/model/client.proto | 1 + 19 files changed, 730 insertions(+), 175 deletions(-) create mode 100644 name.abuchen.portfolio.tests/src/fileversions/client69.binary+pwd.portfolio create mode 100644 name.abuchen.portfolio.tests/src/fileversions/client69.binary.portfolio create mode 100644 name.abuchen.portfolio.tests/src/fileversions/client69.xml diff --git a/name.abuchen.portfolio.tests/src/fileversions/ReadingHistoricClientFilesTest.java b/name.abuchen.portfolio.tests/src/fileversions/ReadingHistoricClientFilesTest.java index 146f2467b7..a4218685a2 100644 --- a/name.abuchen.portfolio.tests/src/fileversions/ReadingHistoricClientFilesTest.java +++ b/name.abuchen.portfolio.tests/src/fileversions/ReadingHistoricClientFilesTest.java @@ -26,7 +26,7 @@ public class ReadingHistoricClientFilesTest public static Collection getFiles() { return Arrays.asList(new Object[][] { // NOSONAR - { "client52", 52 }, { "client53", 53 } }); + { "client52", 52 }, { "client53", 53 }, { "client69", 69 } }); } @@ -55,10 +55,15 @@ public void compare() throws IOException String binaryEncrypted = ClientTestUtilities.toString(binaryEncryptedClient); assertThat(binaryEncryptedClient.getFileVersionAfterRead(), is(versionOnDisk)); - Client xmlEncrpytedClient = ClientFactory.load(find(file + ".xml+pwd.portfolio"), "123456".toCharArray(), - new NullProgressMonitor()); - String xmlEncrpyted = ClientTestUtilities.toString(xmlEncrpytedClient); - assertThat(xmlEncrpytedClient.getFileVersionAfterRead(), is(versionOnDisk)); + String xmlEncrpyted = null; + if (versionOnDisk < 60) + { + + Client xmlEncrpytedClient = ClientFactory.load(find(file + ".xml+pwd.portfolio"), "123456".toCharArray(), + new NullProgressMonitor()); + xmlEncrpyted = ClientTestUtilities.toString(xmlEncrpytedClient); + assertThat(xmlEncrpytedClient.getFileVersionAfterRead(), is(versionOnDisk)); + } if (!xml.equals(binary)) { @@ -76,7 +81,7 @@ public void compare() throws IOException is(xml.substring(pos, Math.min(pos + 100, xml.length())))); } - if (!xml.equals(xmlEncrpyted)) + if (xmlEncrpyted != null && !xml.equals(xmlEncrpyted)) { int pos = ClientTestUtilities.indexOfDifference(xml, xmlEncrpyted); assertThat("encrypted xml is not identical to xml " + pos, @@ -85,4 +90,4 @@ public void compare() throws IOException } } -} +} \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.binary+pwd.portfolio b/name.abuchen.portfolio.tests/src/fileversions/client69.binary+pwd.portfolio new file mode 100644 index 0000000000000000000000000000000000000000..01fdf247ec11809c9442c088cfc78dbd00557414 GIT binary patch literal 1754 zcmV<01||7WPf}DyPfSTq0eviwF_+KnmxEoQuYmW+mvo!&_}G(pFI$yEVDi`*_GyhO z_z;BQ<)E((nn>w|Ho5W|M|y}cN)b9f50jJP`E#~sL}M}?5t7KWC8XFTE8gwb=dA-X z!UChG2R#ire}U!QfKSQ6kSfaF3h}}BJ74#9j7-YLttC~Ll*E}QfDxc3U2WJkiQyjU zM|oKp^FH0;@xQ{=Q|yv4`#6smYX)uFCTcdu*Ct1$w$3A}cND3z3{WQ1)B4y5wvz<$`RMwmkP+hUdcdr6^0<6D0jh0S4wu8`RA=7=;3r<& z&<)Q0O%pDlB$CRAjvSq*Onc?1fJMePtJDkm=l)98q|q>g-9=v54$x&EEu^0K3lu+f zr+`0B#YNX{rO+;~f^}o~7RPjWd0@Td8#XjoPS)005v)@opJx#!DRF?_u>Vh?kNcj+ z%h!MetrWmD;Gl7thsI8r*Qa)J>boFm6}xN?@N^afliip|>sI9V-Dtd{)*J?0Sy`=x z`{HRbY=+vVZLvs=18zlQZ$Vj%IfBUMGeq3Db8tBZ@5E11WL~zbDYqmEeVCQkGYk|6>xXi7tx-Fg(^F?Gd`@?)ei^O!d zPiED`>(_UF{lv|Q2}q02*V*$xN8Nyh9*VLH`gyiKj{Q z_=3f?VMH|xoON-SBzrPd$No;Pnd=qJ2Y&zVqB+?!>2W4La<@G6D%-Q9kal_>%vbnV zlcEBLF30`_O~B^II27wc0OejVZ6gPE_t&7C2mVGH9n#X8DlS)mxDj|Zlp~LYA(~x; zxMMzdK6`huqK)By%742sf0e~-lc~>RffjJL9(aoTWvbM9q&k%)Y6W3RLc(~x zGH-Cra?GyY_D+Nsd-i4eEuQrsp#zFb-$+)NA@qr?3MnWtd^1bS`?4#wR*PF_2CKrc ziWt)}DMYE{o+n0|foA!w$T;I0Pj%y+X>aeH;L|L%JW)(+h;(j!YHdF%35%uz_k-xX z1+&3JfJJ;AePtOZ#l1kcu(YiZAts@0LRvFc!RZW_C){BQ`0?p|ee63aBc!Y@WezAm z2ms5A^l2eTGj!@TE6+FU7%16`dbf+fg!8A4qGH7gUGG%fs!TB91_B|@ANS0-HWCb z=vFoSGKMZLJ?&QtI^BLL7!P`+E-GkL@4aU9<;D~-*^!6SUhDO?{RpH|w z1uTm-Z$`cBW7(^i84)VqzzSR~&un)UQZVuNJx|H!H#Q|e$oFh&+yasc?9JwFq-v>+ z@Kvnoqj+#1-UzsxR!G(1#1bygXMMqV>6ioMcbW@-Sa=xjV8TL(ac^C43H4}uIr9!* zeSc24+XDd%yeKo=FjTo}+eV6r=uShHt@`O^2uZt7BgMY1ytjF`mLe`NTgjld;j=?* w;Y-?#SN2<&di>(vxL4iGZ_|fH{G0jdH<(y++@|3SSa^zvAgk@ah4>lD&2GwJB>(^b literal 0 HcmV?d00001 diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.binary.portfolio b/name.abuchen.portfolio.tests/src/fileversions/client69.binary.portfolio new file mode 100644 index 0000000000000000000000000000000000000000..02467c0f1aedbab795641e03e10f5882a600ffae GIT binary patch literal 1737 zcmV;)1~&OnO9KQH00;;O079lkTmS$7000000000001f~E0AyiwVJ>iQa&%^IY-w-B zS50i&R2(PmR)Q&|m?5Shv?%JfZp@$guoG0Ow9Q7hYD8_!FOlvZi(UHih=`=j#Y$lUa(-JapA~o*XHYRHtau$-s zW64RUiZo2P;sUj>lXUr$e5$u}YP!%rQ4&RQeC&iIiqcpgEcl7i*`9LwdaOTw=if^| z^$mXb-$#G+Bqo`mTwYYMVThchX<05KNtn~LjKSp;6{%Sjn`SP@4j9&wWnjlBtr&>n zL}Qou<*Oe6)U8kdyw;nVXNEFjMi))Z#~xJ+Koa+;xQTwYD9SWc^AT2eMc9o`lJ z*z3+`!Cv40{Oj+r!=LmpLy~03STnO65_NDhu*7Mynd7895|JWGSTb{i@x->^kN3qd z{PNZ9-P1u_Xa0Ho%?t1UeK9e=x2O@UR~_G}c-%?CC#Ad$36)i{t$M97@z~&RJz=ue zo`ChU?d863`4*Jpz0ZTV{<`wbcRlaM6j_w=oS5b0%(>H;&^oGHn81RdN>a}7VwMjq z&PD6X*A4S>3?jI7<@WBgKPH%Q<{8s+kfURM6;)lA*Ik?CtCZHgf*{EB?tfi3K z3sKOPRA?F=XV`h)qnMgOsLAATY4+$LHWPJ;=mq%C)ro6bwPsWSN^4UAqH!I=TgFnmXWxx)!q$hJ^$X1i^)2HljS(+AP#{39-fV73Miqt6>!88>l3Q!_*&Q_jjZ= zY9hewqL%*{vj>n33xz*3l;nLOD-onxK`Qv)oQ zEF4m2$2Z|bm4aSHgbJe#ZX;((v(tr+fh-ejS}W_!1T&~Rn%z%kL>4gRkWS&`rmKQSU47vm$dk<8MqOdL4NQXB-oWQt_?s=7 zf@WK`J7Q0>-73Bn>8b+(%mzwBDFiN^9mT#AV|LZtip%brf@dOp9^UUD8}mpD4i$&5 zyM&r<&2nKD4P4_}lP3?(BREEC$f@u%lt7^h`7Irb6s$C#;#nBbp-CH6@HiZkaByQX z_89wiH!4G0BkH>AJM>{Qx!8@#fh`fst=|uu%cX8yUfL3I61+WXV~3W3#=|D`WsK>C z75n@#>>-;jxbR|d!Z}I~&z7bSC3@kR3QQiLk0xAStKq`SJ0MubM2AqL6t4nBlibD^hFfm6DoGB*`2+V6>Z97B#FG)t zBdhj}81s~k9B9*^qnZV4$O9HLnB8tQd=xV#By7#wxvo} zX{IgBwWZmvw($OUD%f@E1TR^x564e1U|mh~U8R!PRlLXrA6cAf5sz|JxVF2*(jyV) zr1dw}6Cd|5%6$t(0Vrt0*UX~lVd~9+7!J!JMN*YCHZYf!H3bT08t}mfRgU+V1qJ{B000310RTJz004Ie00000WlJcD literal 0 HcmV?d00001 diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.xml b/name.abuchen.portfolio.tests/src/fileversions/client69.xml new file mode 100644 index 0000000000..252b9ee609 --- /dev/null +++ b/name.abuchen.portfolio.tests/src/fileversions/client69.xml @@ -0,0 +1,264 @@ + + 69 + EUR + + + 2bab2728-f3b2-4ca0-8330-825446831ade + Commerzbank AG Inhaber-Aktien o.N. + EUR + DE000CBK1001 + CBK.DE + PP + + + + + + false + 2026-02-04T21:30:37.744832272Z + + + + + + 6908edd0-1bb5-411e-bb4d-678a858eff66 + dividendExdate + EUR + false + + + 11d2ebf5-a0c5-4de1-b2f6-19a0a701e1f6 + 2019-05-27T00:00 + EUR + 1007 + + 7000000000 + Abrechnungs-Nr. 19200128 + 2019-05-24_Wertpapierertrag 24.05.2019_DE000CBK1001.pdf + + + + + + + + + + + + 2026-02-04T22:54:03.661392364Z + DIVIDENDS + 2019-05-23 + + + + + + 2026-02-04T22:52:02.886672581Z + + + + + 404c0fbf-68ab-4925-bdcb-9838e2380317 + dividendExdate + false + + + + + + 2026-02-04T22:51:41.462743232Z + + + + + + + + + + + https://finance.yahoo.com/quote/{tickerSymbol} + + + + https://www.onvista.de/suche.html?SEARCH_VALUE={isin} + + + + https://www.finanzen.net/suchergebnis.asp?frmAktiensucheTextfeld={isin} + + + + https://www.ariva.de/{isin} + + + + https://www.justetf.com/etf-profile.html?isin={isin} + + + + https://www.fondsweb.com/{isin} + + + + https://www.morningstar.de/de/funds/SecuritySearchResults.aspx?type=ALL&search={isin} + + + + https://extraetf.com/etf-profile/{isin} + + + + https://www.alleaktien.de/data/{isin} + + + + https://www.comdirect.de/inf/aktien/{isin} + + + + https://www.comdirect.de/inf/etfs/{isin} + + + + https://divvydiary.com/symbols/{isin} + + + + https://www.trackingdifferences.com/ETF/ISIN/{isin} + + + + https://www.tradingview.com/chart/?symbol=XETR:{tickerSymbolPrefix} + + + + https://www.cnbc.com/quotes/{tickerSymbolPrefix} + + + + https://www.nasdaq.com/market-activity/stocks/{tickerSymbolPrefix} + + + + https://aktienfinder.net/aktien-profil/{isin} + + + + http://aktien.guide/isin/aktien/{isin} + + + + + logo + Logo + Logo + name.abuchen.portfolio.model.Security + java.lang.String + name.abuchen.portfolio.model.AttributeType$ImageConverter + + + + logo + Logo + Logo + name.abuchen.portfolio.model.Account + java.lang.String + name.abuchen.portfolio.model.AttributeType$ImageConverter + + + + logo + Logo + Logo + name.abuchen.portfolio.model.Portfolio + java.lang.String + name.abuchen.portfolio.model.AttributeType$ImageConverter + + + + logo + Logo + Logo + name.abuchen.portfolio.model.InvestmentPlan + java.lang.String + name.abuchen.portfolio.model.AttributeType$ImageConverter + + + + ter + Gesamtkostenquote (TER) + TER + ter + name.abuchen.portfolio.model.Security + java.lang.Double + name.abuchen.portfolio.model.AttributeType$PercentConverter + + + + aum + Fondsgröße + Fondsgröße + name.abuchen.portfolio.model.Security + java.lang.Long + name.abuchen.portfolio.model.AttributeType$AmountPlainConverter + + + + vendor + Anbieter + Anbieter + vendor + name.abuchen.portfolio.model.Security + java.lang.String + name.abuchen.portfolio.model.AttributeType$StringConverter + + + + acquisitionFee + Kaufgebühr (prozentual) + Kaufgebühr + name.abuchen.portfolio.model.Security + java.lang.Double + name.abuchen.portfolio.model.AttributeType$PercentConverter + + + + managementFee + Verwaltungsgebühr (prozentual) + Verwaltungsgebühr + name.abuchen.portfolio.model.Security + java.lang.Double + name.abuchen.portfolio.model.AttributeType$PercentConverter + + + + + + name.abuchen.portfolio.ui.views.SecuritiesTable + + + + 40227a75-8308-4477-896c-3fa920f43367 + Standard + {"items":[{"id":"0","sortDirection":128,"width":400},{"id":"note","width":200},{"id":"1","width":100},{"id":"2","width":80},{"id":"7","width":80},{"id":"4","width":60},{"id":"5","width":80},{"id":"changeonpreviousamount","width":80},{"id":"9","width":80},{"id":"10","width":80},{"id":"q-date-first-historic","width":261}]} + + + + + + name.abuchen.portfolio.ui.views.StatementOfAssetsViewer + + + + 71873ede-52b7-44fd-9877-1155f6c3e6aa + Standard + {"items":[{"id":"0","width":80},{"id":"1","width":300},{"id":"2","width":80},{"id":"4","width":60},{"id":"5","width":80},{"id":"6","width":80},{"id":"note","width":821}]} + + + + + + + \ No newline at end of file diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java index 9115131d23..8b40821c2c 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java @@ -134,6 +134,14 @@ public AccountTransactionMatcher(String label, AccountTransaction.Type type, Mat && tx.getSubject() instanceof AccountTransaction atx && atx.getType() == type ? atx : null, properties); } + + public AccountTransactionMatcher(String label, AccountTransaction.Type type, LocalDate dateEx, + Matcher[] properties) + { + super(label, item -> item instanceof TransactionItem tx // + && tx.getSubject() instanceof AccountTransaction atx && atx.getType() == type + && atx.getDateEx() == dateEx ? atx : null, properties); + } } private static class TransactionSecurityMatcher extends TypeSafeDiagnosingMatcher @@ -254,6 +262,12 @@ public static Matcher dividend(Matcher... propertie return new AccountTransactionMatcher("dividend", AccountTransaction.Type.DIVIDENDS, properties); //$NON-NLS-1$ } + @SafeVarargs + public static Matcher dividendWithExDate(LocalDate dateEx, Matcher... properties) + { + return new AccountTransactionMatcher("dividend", AccountTransaction.Type.DIVIDENDS, dateEx, properties); //$NON-NLS-1$ + } + @SafeVarargs public static Matcher interest(Matcher... properties) { @@ -396,6 +410,17 @@ public static Matcher hasDate(String dateString) Transaction::getDateTime); } + // public static Matcher hasDateEx(String dateString) + // { + // //LocalDate expectecd = LocalDate.parse(dateString); + // + // return new AccountTransactionMatcher("dividends", + // AccountTransaction.Type.DIVIDENDS, dateString, properties); //$NON-NLS-1$ + // + //// return new PropertyMatcher<>("dateEx", //$NON-NLS-1$ expectecd, // + //// null ); + // } + public static Matcher hasShares(double value) { // work with BigDecimal to have better assertion failed messages diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/actions/DetectDuplicatesActionTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/actions/DetectDuplicatesActionTest.java index a138f1fd73..bf04f4aab2 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/actions/DetectDuplicatesActionTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/actions/DetectDuplicatesActionTest.java @@ -36,7 +36,7 @@ public void testDuplicateDetection4AccountTransaction() throws IntrospectionExce var action = new DetectDuplicatesAction(new Client()); new PropertyChecker( - AccountTransaction.class, "note", "source", "forex", "monetaryAmount", "updatedAt") + AccountTransaction.class, "note", "source", "forex", "monetaryAmount", "dateEx", "updatedAt") .before((name, o, c) -> assertThat(name, action.process(o, account(c)).getCode(), is(Code.WARNING))) .after((name, o, c) -> assertThat(name, action.process(o, account(c)).getCode(), diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java index dd93499cc8..913de83d16 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java @@ -1096,6 +1096,7 @@ public class Messages extends NLS public static String MsgDialogNotAValidCurrency; public static String MsgDialogNotAValidISIN; public static String MsgEmbeddedBrowserError; + public static String MsgExDateNotAllowed; public static String MsgErrorAccountNotExist; public static String MsgErrorConvertedAmount; public static String MsgErrorConvertToBuySellCurrencyMismatch; diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java index 51db8a654b..7805bcdc2b 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java @@ -50,10 +50,12 @@ import name.abuchen.portfolio.ui.Messages; import name.abuchen.portfolio.ui.UIConstants; import name.abuchen.portfolio.ui.dialogs.transactions.AccountTransactionModel.Properties; +import name.abuchen.portfolio.ui.util.DatePicker; import name.abuchen.portfolio.ui.util.FormDataFactory; import name.abuchen.portfolio.ui.util.LabelOnly; import name.abuchen.portfolio.ui.util.SWTHelper; import name.abuchen.portfolio.ui.util.SecurityNameLabelProvider; +import name.abuchen.portfolio.ui.util.SimpleDateTimeDateSelectionProperty; public class AccountTransactionDialog extends AbstractTransactionDialog // NOSONAR { @@ -121,6 +123,14 @@ protected void createFormElements(Composite editArea) // NOSONAR dateTime.bindTime(Properties.time.name()); dateTime.bindButton(() -> model().getTime(), time -> model().setTime(time)); + Label lblDateEx = new Label(editArea, SWT.RIGHT); + lblDateEx.setText(Messages.ColumnExDate); + DatePicker dateEx = new DatePicker(editArea); + IObservableValue targetDate = new SimpleDateTimeDateSelectionProperty().observe(dateEx.getControl()); + IObservableValue modelDate = BeanProperties.value(Properties.dateEx.name()).observe(model); + context.bindValue(targetDate, modelDate); + // dateEx.setSelection(null); + // shares Input shares = new Input(editArea, Messages.ColumnShares); @@ -251,6 +261,8 @@ public void widgetSelected(SelectionEvent e) startingWith(dateTime.date.getControl()).thenRight(dateTime.time).thenRight(dateTime.button, 0); + startingWith(dateTime.button).thenRight(lblDateEx).thenRight(dateEx.getControl()); + // shares [- amount per share] forms.thenBelow(shares.value).width(amountWidth).label(shares.label).suffix(btnShares) // // fxAmount - exchange rate - amount diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java index 37d5e24811..5b10e165db 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java @@ -32,7 +32,7 @@ public class AccountTransactionModel extends AbstractModel { public enum Properties { - security, account, date, time, shares, fxGrossAmount, dividendAmount, exchangeRate, inverseExchangeRate, grossAmount, // NOSONAR + security, account, date, dateEx, time, shares, fxGrossAmount, dividendAmount, exchangeRate, inverseExchangeRate, grossAmount, // NOSONAR fxTaxes, taxes, fxFees, fees, total, note, exchangeRateCurrencies, inverseExchangeRateCurrencies, // NOSONAR accountCurrencyCode, securityCurrencyCode, fxCurrencyCode, calculationStatus; // NOSONAR } @@ -41,6 +41,7 @@ public enum Properties private final Client client; private AccountTransaction.Type type; + private LocalDate dateEx; private Account sourceAccount; private AccountTransaction sourceTransaction; @@ -103,6 +104,9 @@ public void applyChanges() if (account == null) throw new UnsupportedOperationException(Messages.MsgMissingAccount); + if (dateEx != null && type != Type.DIVIDENDS) + throw new UnsupportedOperationException(Messages.MsgExDateNotAllowed); + AccountTransaction t; if (sourceTransaction != null && sourceAccount.equals(account)) @@ -125,6 +129,7 @@ public void applyChanges() } t.setDateTime(LocalDateTime.of(date, time)); + t.setDateEx(dateEx); t.setSecurity(!EMPTY_SECURITY.equals(security) ? security : null); t.setShares(supportsShares() ? shares : 0); t.setAmount(total); @@ -177,6 +182,7 @@ public void resetToNewTransaction() setFxTaxes(0); setNote(null); setTime(PresetValues.getTime()); + setDateEx(null); } public boolean supportsShares() @@ -444,6 +450,16 @@ public void setTime(LocalTime time) firePropertyChange(Properties.time.name(), this.time, this.time = time); // NOSONAR } + public LocalDate getDateEx() + { + return dateEx; + } + + public void setDateEx(LocalDate dateEx) + { + this.dateEx = dateEx; + } + public long getShares() { return shares; diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties index 5dcd417952..63801d5cd0 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties @@ -346,6 +346,8 @@ ColumnDataSeries = Data Series ColumnDate = Date +ColumnDateEx = Ex-Date + ColumnDateFirstHistoricalQuote = First historical (Date) ColumnDateFirstHistoricalQuote_MenuLabel = Date of first historical quote @@ -2184,6 +2186,8 @@ MsgDialogNotAValidISIN = Invalid ISIN: {0} MsgEmbeddedBrowserError = Unable to create embedded browser to display charts\n\n* Are you running the latest version of your browser?\n* On Linux one has to install the packet ''libwebkitgtk-3.0-0''\n\nThe error message\n "No more handles [Unknown Mozilla path (MOZILLA_FIVE_HOME not set)]"\nindicates that libwebkitgtk has to be installed. On Ubuntu 18.04, run\n sudo apt-get install libwebkitgtk-3.0-0\n\n\nDetails:\n{0} +MsgExDateNotAllowed = Ex-Date is only allowed for dividend transactions. + MsgErrorAccountNotExist = There is no account.\nPlease create a new account. MsgErrorConvertToBuySellCurrencyMismatch = Transaction with currency {0} cannot be booked on account ''{2}'' with the currency {1}. diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties index 494cd89985..cc801c92c6 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties @@ -2177,6 +2177,8 @@ MsgDialogNotAValidISIN = Ung\u00FCltige ISIN: {0} MsgEmbeddedBrowserError = Fehler beim \u00D6ffnen des Web Browsers zur Darstellung der Grafiken\n\n* Aktuellste Version des Browsers installiert?\n* Unter Linux muss das Paket ''libwebkitgtk-3.0-0'' installiert sein.\n\nDer Fehlertext\n "No more handles [Unknown Mozilla path (MOZILLA_FIVE_HOME not set)]"\nhei\u00DFt meistens, dass libwebkitgtk installiert werden muss. Unter Ubuntu 18.04 z. B. mit\n sudo apt-get install libwebkitgtk-3.0-0\n\n\nDetails:\n{0} +MsgExDateNotAllowed = Ex-Datum ist nur für Dividenden-Transaktionen erlaubt. + MsgErrorAccountNotExist = Es ist kein Konto vorhanden.\nBitte erstellen Sie ein Konto. MsgErrorConvertToBuySellCurrencyMismatch = Buchung in der W\u00E4hrung {0} kann nicht auf Konto ''{2}'' mit der W\u00E4hrung {1} gebucht werden. diff --git a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java index 0b1ebd0c9c..fc13b760f7 100644 --- a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java +++ b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java @@ -242,7 +242,7 @@ public static void registerAllExtensions( "xRateToBase\030\006 \001(\0132%.name.abuchen.portfol" + "io.PDecimalValueH\002\210\001\001\")\n\004Type\022\017\n\013GROSS_V" + "ALUE\020\000\022\007\n\003TAX\020\001\022\007\n\003FEE\020\002B\013\n\t_fxAmountB\021\n" + - "\017_fxCurrencyCodeB\017\n\r_fxRateToBase\"\230\007\n\014PT" + + "\017_fxCurrencyCodeB\017\n\r_fxRateToBase\"\324\007\n\014PT" + "ransaction\022\014\n\004uuid\030\001 \001(\t\0227\n\004type\030\002 \001(\0162)" + ".name.abuchen.portfolio.PTransaction.Typ" + "e\022\024\n\007account\030\003 \001(\tH\000\210\001\001\022\026\n\tportfolio\030\004 \001" + @@ -250,101 +250,103 @@ public static void registerAllExtensions( "herPortfolio\030\006 \001(\tH\003\210\001\001\022\026\n\totherUuid\030\007 \001" + "(\tH\004\210\001\001\0227\n\016otherUpdatedAt\030\010 \001(\0132\032.google" + ".protobuf.TimestampH\005\210\001\001\022(\n\004date\030\t \001(\0132\032" + - ".google.protobuf.Timestamp\022\024\n\014currencyCo" + - "de\030\n \001(\t\022\016\n\006amount\030\013 \001(\003\022\023\n\006shares\030\014 \001(\003" + - "H\006\210\001\001\022\021\n\004note\030\r \001(\tH\007\210\001\001\022\025\n\010security\030\016 \001" + - "(\tH\010\210\001\001\0227\n\005units\030\017 \003(\0132(.name.abuchen.po" + - "rtfolio.PTransactionUnit\022-\n\tupdatedAt\030\020 " + - "\001(\0132\032.google.protobuf.Timestamp\022\023\n\006sourc" + - "e\030\021 \001(\tH\t\210\001\001\"\362\001\n\004Type\022\014\n\010PURCHASE\020\000\022\010\n\004S" + - "ALE\020\001\022\024\n\020INBOUND_DELIVERY\020\002\022\025\n\021OUTBOUND_" + - "DELIVERY\020\003\022\025\n\021SECURITY_TRANSFER\020\004\022\021\n\rCAS" + - "H_TRANSFER\020\005\022\013\n\007DEPOSIT\020\006\022\013\n\007REMOVAL\020\007\022\014" + - "\n\010DIVIDEND\020\010\022\014\n\010INTEREST\020\t\022\023\n\017INTEREST_C" + - "HARGE\020\n\022\007\n\003TAX\020\013\022\016\n\nTAX_REFUND\020\014\022\007\n\003FEE\020" + - "\r\022\016\n\nFEE_REFUND\020\016B\n\n\010_accountB\014\n\n_portfo" + - "lioB\017\n\r_otherAccountB\021\n\017_otherPortfolioB" + - "\014\n\n_otherUuidB\021\n\017_otherUpdatedAtB\t\n\007_sha" + - "resB\007\n\005_noteB\013\n\t_securityB\t\n\007_source\"\335\003\n" + - "\017PInvestmentPlan\022\014\n\004name\030\001 \001(\t\022\021\n\004note\030\002" + - " \001(\tH\000\210\001\001\022\025\n\010security\030\003 \001(\tH\001\210\001\001\022\026\n\tport" + - "folio\030\004 \001(\tH\002\210\001\001\022\024\n\007account\030\005 \001(\tH\003\210\001\001\0225" + - "\n\nattributes\030\006 \003(\0132!.name.abuchen.portfo" + - "lio.PKeyValue\022\024\n\014autoGenerate\030\007 \001(\010\022\014\n\004d" + - "ate\030\010 \001(\003\022\020\n\010interval\030\t \001(\005\022\016\n\006amount\030\n " + - "\001(\003\022\014\n\004fees\030\013 \001(\003\022\024\n\014transactions\030\014 \003(\t\022" + - "\r\n\005taxes\030\r \001(\003\022:\n\004type\030\016 \001(\0162,.name.abuc" + - "hen.portfolio.PInvestmentPlan.Type\"H\n\004Ty" + - "pe\022\030\n\024PURCHASE_OR_DELIVERY\020\000\022\013\n\007DEPOSIT\020" + - "\001\022\013\n\007REMOVAL\020\002\022\014\n\010INTEREST\020\003B\007\n\005_noteB\013\n" + - "\t_securityB\014\n\n_portfolioB\n\n\010_account\"\252\004\n" + - "\tPTaxonomy\022\n\n\002id\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\023\n\006" + - "source\030\003 \001(\tH\000\210\001\001\022\022\n\ndimensions\030\004 \003(\t\022I\n" + - "\017classifications\030\005 \003(\01320.name.abuchen.po" + - "rtfolio.PTaxonomy.Classification\032v\n\nAssi" + - "gnment\022\031\n\021investmentVehicle\030\001 \001(\t\022\016\n\006wei" + - "ght\030\002 \001(\005\022\014\n\004rank\030\003 \001(\005\022/\n\004data\030\004 \003(\0132!." + - "name.abuchen.portfolio.PKeyValue\032\213\002\n\016Cla" + - "ssification\022\n\n\002id\030\001 \001(\t\022\025\n\010parentId\030\002 \001(" + - "\tH\000\210\001\001\022\014\n\004name\030\003 \001(\t\022\021\n\004note\030\004 \001(\tH\001\210\001\001\022" + - "\r\n\005color\030\005 \001(\t\022\016\n\006weight\030\006 \001(\005\022\014\n\004rank\030\007" + - " \001(\005\022/\n\004data\030\010 \003(\0132!.name.abuchen.portfo" + - "lio.PKeyValue\022A\n\013assignments\030\t \003(\0132,.nam" + - "e.abuchen.portfolio.PTaxonomy.Assignment" + - "B\013\n\t_parentIdB\007\n\005_noteB\t\n\007_source\"\357\003\n\nPD" + - "ashboard\022\014\n\004name\030\001 \001(\t\022L\n\rconfiguration\030" + - "\002 \003(\01325.name.abuchen.portfolio.PDashboar" + - "d.ConfigurationEntry\022:\n\007columns\030\003 \003(\0132)." + - "name.abuchen.portfolio.PDashboard.Column" + - "\022\n\n\002id\030\004 \001(\t\032\260\001\n\006Widget\022\014\n\004type\030\001 \001(\t\022\r\n" + - "\005label\030\002 \001(\t\022S\n\rconfiguration\030\003 \003(\0132<.na" + - "me.abuchen.portfolio.PDashboard.Widget.C" + - "onfigurationEntry\0324\n\022ConfigurationEntry\022" + - "\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\032T\n\006Colum" + - "n\022\016\n\006weight\030\001 \001(\005\022:\n\007widgets\030\002 \003(\0132).nam" + - "e.abuchen.portfolio.PDashboard.Widget\0324\n" + + ".google.protobuf.Timestamp\022/\n\006dateEx\030\022 \001" + + "(\0132\032.google.protobuf.TimestampH\006\210\001\001\022\024\n\014c" + + "urrencyCode\030\n \001(\t\022\016\n\006amount\030\013 \001(\003\022\023\n\006sha" + + "res\030\014 \001(\003H\007\210\001\001\022\021\n\004note\030\r \001(\tH\010\210\001\001\022\025\n\010sec" + + "urity\030\016 \001(\tH\t\210\001\001\0227\n\005units\030\017 \003(\0132(.name.a" + + "buchen.portfolio.PTransactionUnit\022-\n\tupd" + + "atedAt\030\020 \001(\0132\032.google.protobuf.Timestamp" + + "\022\023\n\006source\030\021 \001(\tH\n\210\001\001\"\362\001\n\004Type\022\014\n\010PURCHA" + + "SE\020\000\022\010\n\004SALE\020\001\022\024\n\020INBOUND_DELIVERY\020\002\022\025\n\021" + + "OUTBOUND_DELIVERY\020\003\022\025\n\021SECURITY_TRANSFER" + + "\020\004\022\021\n\rCASH_TRANSFER\020\005\022\013\n\007DEPOSIT\020\006\022\013\n\007RE" + + "MOVAL\020\007\022\014\n\010DIVIDEND\020\010\022\014\n\010INTEREST\020\t\022\023\n\017I" + + "NTEREST_CHARGE\020\n\022\007\n\003TAX\020\013\022\016\n\nTAX_REFUND\020" + + "\014\022\007\n\003FEE\020\r\022\016\n\nFEE_REFUND\020\016B\n\n\010_accountB\014" + + "\n\n_portfolioB\017\n\r_otherAccountB\021\n\017_otherP" + + "ortfolioB\014\n\n_otherUuidB\021\n\017_otherUpdatedA" + + "tB\t\n\007_dateExB\t\n\007_sharesB\007\n\005_noteB\013\n\t_sec" + + "urityB\t\n\007_source\"\335\003\n\017PInvestmentPlan\022\014\n\004" + + "name\030\001 \001(\t\022\021\n\004note\030\002 \001(\tH\000\210\001\001\022\025\n\010securit" + + "y\030\003 \001(\tH\001\210\001\001\022\026\n\tportfolio\030\004 \001(\tH\002\210\001\001\022\024\n\007" + + "account\030\005 \001(\tH\003\210\001\001\0225\n\nattributes\030\006 \003(\0132!" + + ".name.abuchen.portfolio.PKeyValue\022\024\n\014aut" + + "oGenerate\030\007 \001(\010\022\014\n\004date\030\010 \001(\003\022\020\n\010interva" + + "l\030\t \001(\005\022\016\n\006amount\030\n \001(\003\022\014\n\004fees\030\013 \001(\003\022\024\n" + + "\014transactions\030\014 \003(\t\022\r\n\005taxes\030\r \001(\003\022:\n\004ty" + + "pe\030\016 \001(\0162,.name.abuchen.portfolio.PInves" + + "tmentPlan.Type\"H\n\004Type\022\030\n\024PURCHASE_OR_DE" + + "LIVERY\020\000\022\013\n\007DEPOSIT\020\001\022\013\n\007REMOVAL\020\002\022\014\n\010IN" + + "TEREST\020\003B\007\n\005_noteB\013\n\t_securityB\014\n\n_portf" + + "olioB\n\n\010_account\"\252\004\n\tPTaxonomy\022\n\n\002id\030\001 \001" + + "(\t\022\014\n\004name\030\002 \001(\t\022\023\n\006source\030\003 \001(\tH\000\210\001\001\022\022\n" + + "\ndimensions\030\004 \003(\t\022I\n\017classifications\030\005 \003" + + "(\01320.name.abuchen.portfolio.PTaxonomy.Cl" + + "assification\032v\n\nAssignment\022\031\n\021investment" + + "Vehicle\030\001 \001(\t\022\016\n\006weight\030\002 \001(\005\022\014\n\004rank\030\003 " + + "\001(\005\022/\n\004data\030\004 \003(\0132!.name.abuchen.portfol" + + "io.PKeyValue\032\213\002\n\016Classification\022\n\n\002id\030\001 " + + "\001(\t\022\025\n\010parentId\030\002 \001(\tH\000\210\001\001\022\014\n\004name\030\003 \001(\t" + + "\022\021\n\004note\030\004 \001(\tH\001\210\001\001\022\r\n\005color\030\005 \001(\t\022\016\n\006we" + + "ight\030\006 \001(\005\022\014\n\004rank\030\007 \001(\005\022/\n\004data\030\010 \003(\0132!" + + ".name.abuchen.portfolio.PKeyValue\022A\n\013ass" + + "ignments\030\t \003(\0132,.name.abuchen.portfolio." + + "PTaxonomy.AssignmentB\013\n\t_parentIdB\007\n\005_no" + + "teB\t\n\007_source\"\357\003\n\nPDashboard\022\014\n\004name\030\001 \001" + + "(\t\022L\n\rconfiguration\030\002 \003(\01325.name.abuchen" + + ".portfolio.PDashboard.ConfigurationEntry" + + "\022:\n\007columns\030\003 \003(\0132).name.abuchen.portfol" + + "io.PDashboard.Column\022\n\n\002id\030\004 \001(\t\032\260\001\n\006Wid" + + "get\022\014\n\004type\030\001 \001(\t\022\r\n\005label\030\002 \001(\t\022S\n\rconf" + + "iguration\030\003 \003(\0132<.name.abuchen.portfolio" + + ".PDashboard.Widget.ConfigurationEntry\0324\n" + "\022ConfigurationEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005valu" + - "e\030\002 \001(\t:\0028\001\"+\n\tPBookmark\022\r\n\005label\030\001 \001(\t\022" + - "\017\n\007pattern\030\002 \001(\t\"\307\001\n\016PAttributeType\022\n\n\002i" + - "d\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\023\n\013columnLabel\030\003 \001" + - "(\t\022\023\n\006source\030\004 \001(\tH\000\210\001\001\022\016\n\006target\030\005 \001(\t\022" + - "\014\n\004type\030\006 \001(\t\022\026\n\016converterClass\030\007 \001(\t\0220\n" + - "\nproperties\030\010 \001(\0132\034.name.abuchen.portfol" + - "io.PMapB\t\n\007_source\"J\n\021PConfigurationSet\022" + - "\013\n\003key\030\001 \001(\t\022\014\n\004uuid\030\002 \001(\t\022\014\n\004name\030\003 \001(\t" + - "\022\014\n\004data\030\004 \001(\t\"\307\001\n\tPSettings\0224\n\tbookmark" + - "s\030\001 \003(\0132!.name.abuchen.portfolio.PBookma" + - "rk\022>\n\016attributeTypes\030\002 \003(\0132&.name.abuche" + - "n.portfolio.PAttributeType\022D\n\021configurat" + - "ionSets\030\003 \003(\0132).name.abuchen.portfolio.P" + - "ConfigurationSet\"\305\005\n\007PClient\022\017\n\007version\030" + - "\001 \001(\005\0225\n\nsecurities\030\002 \003(\0132!.name.abuchen" + - ".portfolio.PSecurity\0222\n\010accounts\030\003 \003(\0132 " + - ".name.abuchen.portfolio.PAccount\0226\n\nport" + - "folios\030\004 \003(\0132\".name.abuchen.portfolio.PP" + - "ortfolio\022:\n\014transactions\030\005 \003(\0132$.name.ab" + - "uchen.portfolio.PTransaction\0226\n\005plans\030\006 " + - "\003(\0132\'.name.abuchen.portfolio.PInvestment" + - "Plan\0226\n\nwatchlists\030\007 \003(\0132\".name.abuchen." + - "portfolio.PWatchlist\0225\n\ntaxonomies\030\010 \003(\013" + - "2!.name.abuchen.portfolio.PTaxonomy\0226\n\nd" + - "ashboards\030\t \003(\0132\".name.abuchen.portfolio" + - ".PDashboard\022C\n\nproperties\030\n \003(\0132/.name.a" + - "buchen.portfolio.PClient.PropertiesEntry" + - "\0223\n\010settings\030\013 \001(\0132!.name.abuchen.portfo" + - "lio.PSettings\022\024\n\014baseCurrency\030\014 \001(\t\022(\n\ne" + - "xtensions\030c \003(\0132\024.google.protobuf.Any\0321\n" + - "\017PropertiesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002" + - " \001(\t:\0028\001\"S\n\rPExchangeRate\022\014\n\004date\030\001 \001(\003\022" + - "4\n\005value\030\002 \001(\0132%.name.abuchen.portfolio." + - "PDecimalValue\"\203\001\n\027PExchangeRateTimeSerie" + - "s\022\024\n\014baseCurrency\030\001 \001(\t\022\024\n\014termCurrency\030" + - "\002 \001(\t\022<\n\rexchangeRates\030\003 \003(\0132%.name.abuc" + - "hen.portfolio.PExchangeRate\"a\n\010PECBData\022" + - "\024\n\014lastModified\030\001 \001(\003\022?\n\006series\030\002 \003(\0132/." + - "name.abuchen.portfolio.PExchangeRateTime" + - "SeriesB7\n%name.abuchen.portfolio.model.p" + - "roto.v1B\014ClientProtosP\001b\006proto3" + "e\030\002 \001(\t:\0028\001\032T\n\006Column\022\016\n\006weight\030\001 \001(\005\022:\n" + + "\007widgets\030\002 \003(\0132).name.abuchen.portfolio." + + "PDashboard.Widget\0324\n\022ConfigurationEntry\022" + + "\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"+\n\tPBook" + + "mark\022\r\n\005label\030\001 \001(\t\022\017\n\007pattern\030\002 \001(\t\"\307\001\n" + + "\016PAttributeType\022\n\n\002id\030\001 \001(\t\022\014\n\004name\030\002 \001(" + + "\t\022\023\n\013columnLabel\030\003 \001(\t\022\023\n\006source\030\004 \001(\tH\000" + + "\210\001\001\022\016\n\006target\030\005 \001(\t\022\014\n\004type\030\006 \001(\t\022\026\n\016con" + + "verterClass\030\007 \001(\t\0220\n\nproperties\030\010 \001(\0132\034." + + "name.abuchen.portfolio.PMapB\t\n\007_source\"J" + + "\n\021PConfigurationSet\022\013\n\003key\030\001 \001(\t\022\014\n\004uuid" + + "\030\002 \001(\t\022\014\n\004name\030\003 \001(\t\022\014\n\004data\030\004 \001(\t\"\307\001\n\tP" + + "Settings\0224\n\tbookmarks\030\001 \003(\0132!.name.abuch" + + "en.portfolio.PBookmark\022>\n\016attributeTypes" + + "\030\002 \003(\0132&.name.abuchen.portfolio.PAttribu" + + "teType\022D\n\021configurationSets\030\003 \003(\0132).name" + + ".abuchen.portfolio.PConfigurationSet\"\305\005\n" + + "\007PClient\022\017\n\007version\030\001 \001(\005\0225\n\nsecurities\030" + + "\002 \003(\0132!.name.abuchen.portfolio.PSecurity" + + "\0222\n\010accounts\030\003 \003(\0132 .name.abuchen.portfo" + + "lio.PAccount\0226\n\nportfolios\030\004 \003(\0132\".name." + + "abuchen.portfolio.PPortfolio\022:\n\014transact" + + "ions\030\005 \003(\0132$.name.abuchen.portfolio.PTra" + + "nsaction\0226\n\005plans\030\006 \003(\0132\'.name.abuchen.p" + + "ortfolio.PInvestmentPlan\0226\n\nwatchlists\030\007" + + " \003(\0132\".name.abuchen.portfolio.PWatchlist" + + "\0225\n\ntaxonomies\030\010 \003(\0132!.name.abuchen.port" + + "folio.PTaxonomy\0226\n\ndashboards\030\t \003(\0132\".na" + + "me.abuchen.portfolio.PDashboard\022C\n\nprope" + + "rties\030\n \003(\0132/.name.abuchen.portfolio.PCl" + + "ient.PropertiesEntry\0223\n\010settings\030\013 \001(\0132!" + + ".name.abuchen.portfolio.PSettings\022\024\n\014bas" + + "eCurrency\030\014 \001(\t\022(\n\nextensions\030c \003(\0132\024.go" + + "ogle.protobuf.Any\0321\n\017PropertiesEntry\022\013\n\003" + + "key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"S\n\rPExchang" + + "eRate\022\014\n\004date\030\001 \001(\003\0224\n\005value\030\002 \001(\0132%.nam" + + "e.abuchen.portfolio.PDecimalValue\"\203\001\n\027PE" + + "xchangeRateTimeSeries\022\024\n\014baseCurrency\030\001 " + + "\001(\t\022\024\n\014termCurrency\030\002 \001(\t\022<\n\rexchangeRat" + + "es\030\003 \003(\0132%.name.abuchen.portfolio.PExcha" + + "ngeRate\"a\n\010PECBData\022\024\n\014lastModified\030\001 \001(" + + "\003\022?\n\006series\030\002 \003(\0132/.name.abuchen.portfol" + + "io.PExchangeRateTimeSeriesB7\n%name.abuch" + + "en.portfolio.model.proto.v1B\014ClientProto" + + "sP\001b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -430,7 +432,7 @@ public static void registerAllExtensions( internal_static_name_abuchen_portfolio_PTransaction_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_name_abuchen_portfolio_PTransaction_descriptor, - new java.lang.String[] { "Uuid", "Type", "Account", "Portfolio", "OtherAccount", "OtherPortfolio", "OtherUuid", "OtherUpdatedAt", "Date", "CurrencyCode", "Amount", "Shares", "Note", "Security", "Units", "UpdatedAt", "Source", "Account", "Portfolio", "OtherAccount", "OtherPortfolio", "OtherUuid", "OtherUpdatedAt", "Shares", "Note", "Security", "Source", }); + new java.lang.String[] { "Uuid", "Type", "Account", "Portfolio", "OtherAccount", "OtherPortfolio", "OtherUuid", "OtherUpdatedAt", "Date", "DateEx", "CurrencyCode", "Amount", "Shares", "Note", "Security", "Units", "UpdatedAt", "Source", "Account", "Portfolio", "OtherAccount", "OtherPortfolio", "OtherUuid", "OtherUpdatedAt", "DateEx", "Shares", "Note", "Security", "Source", }); internal_static_name_abuchen_portfolio_PInvestmentPlan_descriptor = getDescriptor().getMessageTypes().get(13); internal_static_name_abuchen_portfolio_PInvestmentPlan_fieldAccessorTable = new diff --git a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java index 78b5a1a5aa..11dfb0c86c 100644 --- a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java +++ b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java @@ -620,6 +620,32 @@ public com.google.protobuf.TimestampOrBuilder getDateOrBuilder() { return date_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : date_; } + public static final int DATEEX_FIELD_NUMBER = 18; + private com.google.protobuf.Timestamp dateEx_; + /** + * optional .google.protobuf.Timestamp dateEx = 18; + * @return Whether the dateEx field is set. + */ + @java.lang.Override + public boolean hasDateEx() { + return ((bitField0_ & 0x00000040) != 0); + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + * @return The dateEx. + */ + @java.lang.Override + public com.google.protobuf.Timestamp getDateEx() { + return dateEx_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + @java.lang.Override + public com.google.protobuf.TimestampOrBuilder getDateExOrBuilder() { + return dateEx_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; + } + public static final int CURRENCYCODE_FIELD_NUMBER = 10; @SuppressWarnings("serial") private volatile java.lang.Object currencyCode_ = ""; @@ -678,7 +704,7 @@ public long getAmount() { */ @java.lang.Override public boolean hasShares() { - return ((bitField0_ & 0x00000040) != 0); + return ((bitField0_ & 0x00000080) != 0); } /** * optional int64 shares = 12; @@ -698,7 +724,7 @@ public long getShares() { */ @java.lang.Override public boolean hasNote() { - return ((bitField0_ & 0x00000080) != 0); + return ((bitField0_ & 0x00000100) != 0); } /** * optional string note = 13; @@ -745,7 +771,7 @@ public java.lang.String getNote() { */ @java.lang.Override public boolean hasSecurity() { - return ((bitField0_ & 0x00000100) != 0); + return ((bitField0_ & 0x00000200) != 0); } /** * optional string security = 14; @@ -859,7 +885,7 @@ public com.google.protobuf.TimestampOrBuilder getUpdatedAtOrBuilder() { */ @java.lang.Override public boolean hasSource() { - return ((bitField0_ & 0x00000200) != 0); + return ((bitField0_ & 0x00000400) != 0); } /** * optional string source = 17; @@ -944,13 +970,13 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (amount_ != 0L) { output.writeInt64(11, amount_); } - if (((bitField0_ & 0x00000040) != 0)) { + if (((bitField0_ & 0x00000080) != 0)) { output.writeInt64(12, shares_); } - if (((bitField0_ & 0x00000080) != 0)) { + if (((bitField0_ & 0x00000100) != 0)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 13, note_); } - if (((bitField0_ & 0x00000100) != 0)) { + if (((bitField0_ & 0x00000200) != 0)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 14, security_); } for (int i = 0; i < units_.size(); i++) { @@ -959,9 +985,12 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (updatedAt_ != null) { output.writeMessage(16, getUpdatedAt()); } - if (((bitField0_ & 0x00000200) != 0)) { + if (((bitField0_ & 0x00000400) != 0)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 17, source_); } + if (((bitField0_ & 0x00000040) != 0)) { + output.writeMessage(18, getDateEx()); + } getUnknownFields().writeTo(output); } @@ -1008,14 +1037,14 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeInt64Size(11, amount_); } - if (((bitField0_ & 0x00000040) != 0)) { + if (((bitField0_ & 0x00000080) != 0)) { size += com.google.protobuf.CodedOutputStream .computeInt64Size(12, shares_); } - if (((bitField0_ & 0x00000080) != 0)) { + if (((bitField0_ & 0x00000100) != 0)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(13, note_); } - if (((bitField0_ & 0x00000100) != 0)) { + if (((bitField0_ & 0x00000200) != 0)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(14, security_); } for (int i = 0; i < units_.size(); i++) { @@ -1026,9 +1055,13 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(16, getUpdatedAt()); } - if (((bitField0_ & 0x00000200) != 0)) { + if (((bitField0_ & 0x00000400) != 0)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(17, source_); } + if (((bitField0_ & 0x00000040) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(18, getDateEx()); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -1082,6 +1115,11 @@ public boolean equals(final java.lang.Object obj) { if (!getDate() .equals(other.getDate())) return false; } + if (hasDateEx() != other.hasDateEx()) return false; + if (hasDateEx()) { + if (!getDateEx() + .equals(other.getDateEx())) return false; + } if (!getCurrencyCode() .equals(other.getCurrencyCode())) return false; if (getAmount() @@ -1156,6 +1194,10 @@ public int hashCode() { hash = (37 * hash) + DATE_FIELD_NUMBER; hash = (53 * hash) + getDate().hashCode(); } + if (hasDateEx()) { + hash = (37 * hash) + DATEEX_FIELD_NUMBER; + hash = (53 * hash) + getDateEx().hashCode(); + } hash = (37 * hash) + CURRENCYCODE_FIELD_NUMBER; hash = (53 * hash) + getCurrencyCode().hashCode(); hash = (37 * hash) + AMOUNT_FIELD_NUMBER; @@ -1316,6 +1358,7 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { getOtherUpdatedAtFieldBuilder(); getDateFieldBuilder(); + getDateExFieldBuilder(); getUnitsFieldBuilder(); getUpdatedAtFieldBuilder(); } @@ -1341,6 +1384,11 @@ public Builder clear() { dateBuilder_.dispose(); dateBuilder_ = null; } + dateEx_ = null; + if (dateExBuilder_ != null) { + dateExBuilder_.dispose(); + dateExBuilder_ = null; + } currencyCode_ = ""; amount_ = 0L; shares_ = 0L; @@ -1352,7 +1400,7 @@ public Builder clear() { units_ = null; unitsBuilder_.clear(); } - bitField0_ = (bitField0_ & ~0x00004000); + bitField0_ = (bitField0_ & ~0x00008000); updatedAt_ = null; if (updatedAtBuilder_ != null) { updatedAtBuilder_.dispose(); @@ -1393,9 +1441,9 @@ public name.abuchen.portfolio.model.proto.v1.PTransaction buildPartial() { private void buildPartialRepeatedFields(name.abuchen.portfolio.model.proto.v1.PTransaction result) { if (unitsBuilder_ == null) { - if (((bitField0_ & 0x00004000) != 0)) { + if (((bitField0_ & 0x00008000) != 0)) { units_ = java.util.Collections.unmodifiableList(units_); - bitField0_ = (bitField0_ & ~0x00004000); + bitField0_ = (bitField0_ & ~0x00008000); } result.units_ = units_; } else { @@ -1444,31 +1492,37 @@ private void buildPartial0(name.abuchen.portfolio.model.proto.v1.PTransaction re : dateBuilder_.build(); } if (((from_bitField0_ & 0x00000200) != 0)) { - result.currencyCode_ = currencyCode_; + result.dateEx_ = dateExBuilder_ == null + ? dateEx_ + : dateExBuilder_.build(); + to_bitField0_ |= 0x00000040; } if (((from_bitField0_ & 0x00000400) != 0)) { - result.amount_ = amount_; + result.currencyCode_ = currencyCode_; } if (((from_bitField0_ & 0x00000800) != 0)) { - result.shares_ = shares_; - to_bitField0_ |= 0x00000040; + result.amount_ = amount_; } if (((from_bitField0_ & 0x00001000) != 0)) { - result.note_ = note_; + result.shares_ = shares_; to_bitField0_ |= 0x00000080; } if (((from_bitField0_ & 0x00002000) != 0)) { - result.security_ = security_; + result.note_ = note_; to_bitField0_ |= 0x00000100; } - if (((from_bitField0_ & 0x00008000) != 0)) { + if (((from_bitField0_ & 0x00004000) != 0)) { + result.security_ = security_; + to_bitField0_ |= 0x00000200; + } + if (((from_bitField0_ & 0x00010000) != 0)) { result.updatedAt_ = updatedAtBuilder_ == null ? updatedAt_ : updatedAtBuilder_.build(); } - if (((from_bitField0_ & 0x00010000) != 0)) { + if (((from_bitField0_ & 0x00020000) != 0)) { result.source_ = source_; - to_bitField0_ |= 0x00000200; + to_bitField0_ |= 0x00000400; } result.bitField0_ |= to_bitField0_; } @@ -1524,9 +1578,12 @@ public Builder mergeFrom(name.abuchen.portfolio.model.proto.v1.PTransaction othe if (other.hasDate()) { mergeDate(other.getDate()); } + if (other.hasDateEx()) { + mergeDateEx(other.getDateEx()); + } if (!other.getCurrencyCode().isEmpty()) { currencyCode_ = other.currencyCode_; - bitField0_ |= 0x00000200; + bitField0_ |= 0x00000400; onChanged(); } if (other.getAmount() != 0L) { @@ -1537,19 +1594,19 @@ public Builder mergeFrom(name.abuchen.portfolio.model.proto.v1.PTransaction othe } if (other.hasNote()) { note_ = other.note_; - bitField0_ |= 0x00001000; + bitField0_ |= 0x00002000; onChanged(); } if (other.hasSecurity()) { security_ = other.security_; - bitField0_ |= 0x00002000; + bitField0_ |= 0x00004000; onChanged(); } if (unitsBuilder_ == null) { if (!other.units_.isEmpty()) { if (units_.isEmpty()) { units_ = other.units_; - bitField0_ = (bitField0_ & ~0x00004000); + bitField0_ = (bitField0_ & ~0x00008000); } else { ensureUnitsIsMutable(); units_.addAll(other.units_); @@ -1562,7 +1619,7 @@ public Builder mergeFrom(name.abuchen.portfolio.model.proto.v1.PTransaction othe unitsBuilder_.dispose(); unitsBuilder_ = null; units_ = other.units_; - bitField0_ = (bitField0_ & ~0x00004000); + bitField0_ = (bitField0_ & ~0x00008000); unitsBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? getUnitsFieldBuilder() : null; @@ -1576,7 +1633,7 @@ public Builder mergeFrom(name.abuchen.portfolio.model.proto.v1.PTransaction othe } if (other.hasSource()) { source_ = other.source_; - bitField0_ |= 0x00010000; + bitField0_ |= 0x00020000; onChanged(); } this.mergeUnknownFields(other.getUnknownFields()); @@ -1656,27 +1713,27 @@ public Builder mergeFrom( } // case 74 case 82: { currencyCode_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000200; + bitField0_ |= 0x00000400; break; } // case 82 case 88: { amount_ = input.readInt64(); - bitField0_ |= 0x00000400; + bitField0_ |= 0x00000800; break; } // case 88 case 96: { shares_ = input.readInt64(); - bitField0_ |= 0x00000800; + bitField0_ |= 0x00001000; break; } // case 96 case 106: { note_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00001000; + bitField0_ |= 0x00002000; break; } // case 106 case 114: { security_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00002000; + bitField0_ |= 0x00004000; break; } // case 114 case 122: { @@ -1696,14 +1753,21 @@ public Builder mergeFrom( input.readMessage( getUpdatedAtFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x00008000; + bitField0_ |= 0x00010000; break; } // case 130 case 138: { source_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00010000; + bitField0_ |= 0x00020000; break; } // case 138 + case 146: { + input.readMessage( + getDateExFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000200; + break; + } // case 146 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -2479,6 +2543,125 @@ public com.google.protobuf.TimestampOrBuilder getDateOrBuilder() { return dateBuilder_; } + private com.google.protobuf.Timestamp dateEx_; + private com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> dateExBuilder_; + /** + * optional .google.protobuf.Timestamp dateEx = 18; + * @return Whether the dateEx field is set. + */ + public boolean hasDateEx() { + return ((bitField0_ & 0x00000200) != 0); + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + * @return The dateEx. + */ + public com.google.protobuf.Timestamp getDateEx() { + if (dateExBuilder_ == null) { + return dateEx_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; + } else { + return dateExBuilder_.getMessage(); + } + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + public Builder setDateEx(com.google.protobuf.Timestamp value) { + if (dateExBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + dateEx_ = value; + } else { + dateExBuilder_.setMessage(value); + } + bitField0_ |= 0x00000200; + onChanged(); + return this; + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + public Builder setDateEx( + com.google.protobuf.Timestamp.Builder builderForValue) { + if (dateExBuilder_ == null) { + dateEx_ = builderForValue.build(); + } else { + dateExBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000200; + onChanged(); + return this; + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + public Builder mergeDateEx(com.google.protobuf.Timestamp value) { + if (dateExBuilder_ == null) { + if (((bitField0_ & 0x00000200) != 0) && + dateEx_ != null && + dateEx_ != com.google.protobuf.Timestamp.getDefaultInstance()) { + getDateExBuilder().mergeFrom(value); + } else { + dateEx_ = value; + } + } else { + dateExBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000200; + onChanged(); + return this; + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + public Builder clearDateEx() { + bitField0_ = (bitField0_ & ~0x00000200); + dateEx_ = null; + if (dateExBuilder_ != null) { + dateExBuilder_.dispose(); + dateExBuilder_ = null; + } + onChanged(); + return this; + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + public com.google.protobuf.Timestamp.Builder getDateExBuilder() { + bitField0_ |= 0x00000200; + onChanged(); + return getDateExFieldBuilder().getBuilder(); + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + public com.google.protobuf.TimestampOrBuilder getDateExOrBuilder() { + if (dateExBuilder_ != null) { + return dateExBuilder_.getMessageOrBuilder(); + } else { + return dateEx_ == null ? + com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; + } + } + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> + getDateExFieldBuilder() { + if (dateExBuilder_ == null) { + dateExBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>( + getDateEx(), + getParentForChildren(), + isClean()); + dateEx_ = null; + } + return dateExBuilder_; + } + private java.lang.Object currencyCode_ = ""; /** * string currencyCode = 10; @@ -2522,7 +2705,7 @@ public Builder setCurrencyCode( java.lang.String value) { if (value == null) { throw new NullPointerException(); } currencyCode_ = value; - bitField0_ |= 0x00000200; + bitField0_ |= 0x00000400; onChanged(); return this; } @@ -2532,7 +2715,7 @@ public Builder setCurrencyCode( */ public Builder clearCurrencyCode() { currencyCode_ = getDefaultInstance().getCurrencyCode(); - bitField0_ = (bitField0_ & ~0x00000200); + bitField0_ = (bitField0_ & ~0x00000400); onChanged(); return this; } @@ -2546,7 +2729,7 @@ public Builder setCurrencyCodeBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); currencyCode_ = value; - bitField0_ |= 0x00000200; + bitField0_ |= 0x00000400; onChanged(); return this; } @@ -2568,7 +2751,7 @@ public long getAmount() { public Builder setAmount(long value) { amount_ = value; - bitField0_ |= 0x00000400; + bitField0_ |= 0x00000800; onChanged(); return this; } @@ -2577,7 +2760,7 @@ public Builder setAmount(long value) { * @return This builder for chaining. */ public Builder clearAmount() { - bitField0_ = (bitField0_ & ~0x00000400); + bitField0_ = (bitField0_ & ~0x00000800); amount_ = 0L; onChanged(); return this; @@ -2590,7 +2773,7 @@ public Builder clearAmount() { */ @java.lang.Override public boolean hasShares() { - return ((bitField0_ & 0x00000800) != 0); + return ((bitField0_ & 0x00001000) != 0); } /** * optional int64 shares = 12; @@ -2608,7 +2791,7 @@ public long getShares() { public Builder setShares(long value) { shares_ = value; - bitField0_ |= 0x00000800; + bitField0_ |= 0x00001000; onChanged(); return this; } @@ -2617,7 +2800,7 @@ public Builder setShares(long value) { * @return This builder for chaining. */ public Builder clearShares() { - bitField0_ = (bitField0_ & ~0x00000800); + bitField0_ = (bitField0_ & ~0x00001000); shares_ = 0L; onChanged(); return this; @@ -2629,7 +2812,7 @@ public Builder clearShares() { * @return Whether the note field is set. */ public boolean hasNote() { - return ((bitField0_ & 0x00001000) != 0); + return ((bitField0_ & 0x00002000) != 0); } /** * optional string note = 13; @@ -2673,7 +2856,7 @@ public Builder setNote( java.lang.String value) { if (value == null) { throw new NullPointerException(); } note_ = value; - bitField0_ |= 0x00001000; + bitField0_ |= 0x00002000; onChanged(); return this; } @@ -2683,7 +2866,7 @@ public Builder setNote( */ public Builder clearNote() { note_ = getDefaultInstance().getNote(); - bitField0_ = (bitField0_ & ~0x00001000); + bitField0_ = (bitField0_ & ~0x00002000); onChanged(); return this; } @@ -2697,7 +2880,7 @@ public Builder setNoteBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); note_ = value; - bitField0_ |= 0x00001000; + bitField0_ |= 0x00002000; onChanged(); return this; } @@ -2708,7 +2891,7 @@ public Builder setNoteBytes( * @return Whether the security field is set. */ public boolean hasSecurity() { - return ((bitField0_ & 0x00002000) != 0); + return ((bitField0_ & 0x00004000) != 0); } /** * optional string security = 14; @@ -2752,7 +2935,7 @@ public Builder setSecurity( java.lang.String value) { if (value == null) { throw new NullPointerException(); } security_ = value; - bitField0_ |= 0x00002000; + bitField0_ |= 0x00004000; onChanged(); return this; } @@ -2762,7 +2945,7 @@ public Builder setSecurity( */ public Builder clearSecurity() { security_ = getDefaultInstance().getSecurity(); - bitField0_ = (bitField0_ & ~0x00002000); + bitField0_ = (bitField0_ & ~0x00004000); onChanged(); return this; } @@ -2776,7 +2959,7 @@ public Builder setSecurityBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); security_ = value; - bitField0_ |= 0x00002000; + bitField0_ |= 0x00004000; onChanged(); return this; } @@ -2784,9 +2967,9 @@ public Builder setSecurityBytes( private java.util.List units_ = java.util.Collections.emptyList(); private void ensureUnitsIsMutable() { - if (!((bitField0_ & 0x00004000) != 0)) { + if (!((bitField0_ & 0x00008000) != 0)) { units_ = new java.util.ArrayList(units_); - bitField0_ |= 0x00004000; + bitField0_ |= 0x00008000; } } @@ -2936,7 +3119,7 @@ public Builder addAllUnits( public Builder clearUnits() { if (unitsBuilder_ == null) { units_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00004000); + bitField0_ = (bitField0_ & ~0x00008000); onChanged(); } else { unitsBuilder_.clear(); @@ -3013,7 +3196,7 @@ public name.abuchen.portfolio.model.proto.v1.PTransactionUnit.Builder addUnitsBu unitsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< name.abuchen.portfolio.model.proto.v1.PTransactionUnit, name.abuchen.portfolio.model.proto.v1.PTransactionUnit.Builder, name.abuchen.portfolio.model.proto.v1.PTransactionUnitOrBuilder>( units_, - ((bitField0_ & 0x00004000) != 0), + ((bitField0_ & 0x00008000) != 0), getParentForChildren(), isClean()); units_ = null; @@ -3029,7 +3212,7 @@ public name.abuchen.portfolio.model.proto.v1.PTransactionUnit.Builder addUnitsBu * @return Whether the updatedAt field is set. */ public boolean hasUpdatedAt() { - return ((bitField0_ & 0x00008000) != 0); + return ((bitField0_ & 0x00010000) != 0); } /** * .google.protobuf.Timestamp updatedAt = 16; @@ -3054,7 +3237,7 @@ public Builder setUpdatedAt(com.google.protobuf.Timestamp value) { } else { updatedAtBuilder_.setMessage(value); } - bitField0_ |= 0x00008000; + bitField0_ |= 0x00010000; onChanged(); return this; } @@ -3068,7 +3251,7 @@ public Builder setUpdatedAt( } else { updatedAtBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x00008000; + bitField0_ |= 0x00010000; onChanged(); return this; } @@ -3077,7 +3260,7 @@ public Builder setUpdatedAt( */ public Builder mergeUpdatedAt(com.google.protobuf.Timestamp value) { if (updatedAtBuilder_ == null) { - if (((bitField0_ & 0x00008000) != 0) && + if (((bitField0_ & 0x00010000) != 0) && updatedAt_ != null && updatedAt_ != com.google.protobuf.Timestamp.getDefaultInstance()) { getUpdatedAtBuilder().mergeFrom(value); @@ -3087,7 +3270,7 @@ public Builder mergeUpdatedAt(com.google.protobuf.Timestamp value) { } else { updatedAtBuilder_.mergeFrom(value); } - bitField0_ |= 0x00008000; + bitField0_ |= 0x00010000; onChanged(); return this; } @@ -3095,7 +3278,7 @@ public Builder mergeUpdatedAt(com.google.protobuf.Timestamp value) { * .google.protobuf.Timestamp updatedAt = 16; */ public Builder clearUpdatedAt() { - bitField0_ = (bitField0_ & ~0x00008000); + bitField0_ = (bitField0_ & ~0x00010000); updatedAt_ = null; if (updatedAtBuilder_ != null) { updatedAtBuilder_.dispose(); @@ -3108,7 +3291,7 @@ public Builder clearUpdatedAt() { * .google.protobuf.Timestamp updatedAt = 16; */ public com.google.protobuf.Timestamp.Builder getUpdatedAtBuilder() { - bitField0_ |= 0x00008000; + bitField0_ |= 0x00010000; onChanged(); return getUpdatedAtFieldBuilder().getBuilder(); } @@ -3146,7 +3329,7 @@ public com.google.protobuf.TimestampOrBuilder getUpdatedAtOrBuilder() { * @return Whether the source field is set. */ public boolean hasSource() { - return ((bitField0_ & 0x00010000) != 0); + return ((bitField0_ & 0x00020000) != 0); } /** * optional string source = 17; @@ -3190,7 +3373,7 @@ public Builder setSource( java.lang.String value) { if (value == null) { throw new NullPointerException(); } source_ = value; - bitField0_ |= 0x00010000; + bitField0_ |= 0x00020000; onChanged(); return this; } @@ -3200,7 +3383,7 @@ public Builder setSource( */ public Builder clearSource() { source_ = getDefaultInstance().getSource(); - bitField0_ = (bitField0_ & ~0x00010000); + bitField0_ = (bitField0_ & ~0x00020000); onChanged(); return this; } @@ -3214,7 +3397,7 @@ public Builder setSourceBytes( if (value == null) { throw new NullPointerException(); } checkByteStringIsUtf8(value); source_ = value; - bitField0_ |= 0x00010000; + bitField0_ |= 0x00020000; onChanged(); return this; } diff --git a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java index 9873a6b262..a2e736a6a5 100644 --- a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java +++ b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java @@ -145,6 +145,21 @@ public interface PTransactionOrBuilder extends */ com.google.protobuf.TimestampOrBuilder getDateOrBuilder(); + /** + * optional .google.protobuf.Timestamp dateEx = 18; + * @return Whether the dateEx field is set. + */ + boolean hasDateEx(); + /** + * optional .google.protobuf.Timestamp dateEx = 18; + * @return The dateEx. + */ + com.google.protobuf.Timestamp getDateEx(); + /** + * optional .google.protobuf.Timestamp dateEx = 18; + */ + com.google.protobuf.TimestampOrBuilder getDateExOrBuilder(); + /** * string currencyCode = 10; * @return The currencyCode. diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java index 0b0083bd36..16733a644d 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java @@ -1,6 +1,7 @@ package name.abuchen.portfolio.model; import java.time.Instant; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ResourceBundle; @@ -47,6 +48,8 @@ public String toString() private Type type; + private LocalDate dateEx; + public AccountTransaction() { // needed for xstream de-serialization @@ -63,6 +66,13 @@ public AccountTransaction(LocalDateTime date, String currencyCode, long amount, this.type = type; } + public AccountTransaction(LocalDateTime date, LocalDate dateEx, String currencyCode, long amount, Security security, + Type type) + { + new AccountTransaction(date, currencyCode, amount, security, type); + this.dateEx = dateEx; + } + public Type getType() { return type; @@ -74,6 +84,16 @@ public void setType(Type type) setUpdatedAt(Instant.now()); } + public LocalDate getDateEx() + { + return dateEx; + } + + public void setDateEx(LocalDate dateEx) + { + this.dateEx = dateEx; + } + /** * Returns the gross value, i.e. the value before taxes and fees are * applied. See {@link #getGrossValue()}. diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/Client.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/Client.java index eba572579e..908876eb7b 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/Client.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/Client.java @@ -31,7 +31,7 @@ public interface Properties // NOSONAR String WATCHLISTS = "watchlists"; //$NON-NLS-1$ } - public static final int CURRENT_VERSION = 68; + public static final int CURRENT_VERSION = 69; public static final int VERSION_WITH_CURRENCY_SUPPORT = 29; public static final int VERSION_WITH_UNIQUE_FILTER_KEY = 57; diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ClientFactory.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ClientFactory.java index f511f8c73d..2930ed52e9 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ClientFactory.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ClientFactory.java @@ -945,7 +945,8 @@ else if (flags.contains(SaveFlag.COMPRESSED)) fixLogoAttributeName(client); case 67: // NOSONAR removeSourceAttributeFromTaxonomy(client); - + case 68: // NOSONAR + // added exDate date field client.setVersion(Client.CURRENT_VERSION); break; case Client.CURRENT_VERSION: diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java index 1cd3a579b2..72bd8e4e9a 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java @@ -474,6 +474,8 @@ private void loadTransactions(PClient newClient, Lookup lookup) case DIVIDEND: AccountTransaction dividend = new AccountTransaction(newTransaction.getUuid()); dividend.setType(AccountTransaction.Type.DIVIDENDS); + if (newTransaction.hasDateEx()) + dividend.setDateEx(fromTimestamp(newTransaction.getDateEx()).toLocalDate()); loadCommonTransaction(newTransaction, dividend, lookup, false); // If the dividend has no instrument, convert it to an @@ -1126,6 +1128,8 @@ private void addTransaction(PClient.Builder newClient, Account account, AccountT break; case DIVIDENDS: newTransaction.setTypeValue(PTransaction.Type.DIVIDEND_VALUE); + if (t.getDateEx() != null) + newTransaction.setDateEx(asTimestamp(t.getDateEx().atStartOfDay())); break; case FEES: newTransaction.setTypeValue(PTransaction.Type.FEE_VALUE); diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto index d8859030cb..0713d84657 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto @@ -172,6 +172,7 @@ message PTransaction { optional google.protobuf.Timestamp otherUpdatedAt = 8; google.protobuf.Timestamp date = 9; + optional google.protobuf.Timestamp dateEx = 18; string currencyCode = 10; int64 amount = 11; From 6f598eee7998e2b57e9dca5e268a41e60b305aba Mon Sep 17 00:00:00 2001 From: ZfT2 Date: Thu, 5 Feb 2026 22:08:33 +0100 Subject: [PATCH 2/5] Introduce ex-date field for dividend transactions to PP model - PDF Extractor with ex date example --- .../pdf/onvista/OnvistaPDFExtractorTest.java | 33 ++++++++++++++++++- .../datatransfer/pdf/OnvistaPDFExtractor.java | 6 ++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java index 0f087b5137..2a812ce469 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java @@ -40,6 +40,7 @@ import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.junit.Assert.assertNull; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -2053,6 +2054,7 @@ public void testDividende01() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2016-04-21T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2016-04-21"))); assertThat(transaction.getShares(), is(Values.Share.factorize(50))); assertThat(transaction.getSource(), is("Dividende01.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 77110599")); @@ -2113,6 +2115,7 @@ public void testDividende02() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2016-12-16T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2016-12-14"))); assertThat(transaction.getShares(), is(Values.Share.factorize(1.0545))); assertThat(transaction.getSource(), is("Dividende02.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 55746925 | Ertrag für 2016/17")); @@ -2129,6 +2132,7 @@ public void testDividende02() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2016-12-16T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2016-12-14"))); assertThat(transaction.getShares(), is(Values.Share.factorize(1.2879))); assertThat(transaction.getSource(), is("Dividende02.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 97603916 | Ertrag für 2016/17")); @@ -2145,6 +2149,7 @@ public void testDividende02() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2016-12-16T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2016-12-14"))); assertThat(transaction.getShares(), is(Values.Share.factorize(9.9225))); assertThat(transaction.getSource(), is("Dividende02.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 33071326 | Ertrag für 2016")); @@ -2189,6 +2194,7 @@ public void testDividende03() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2019-07-15T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2019-06-27"))); assertThat(transaction.getShares(), is(Values.Share.factorize(100))); assertThat(transaction.getSource(), is("Dividende03.txt")); assertNull(transaction.getNote()); @@ -2234,6 +2240,7 @@ public void testDividende03WithSecurityInEUR() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2019-07-15T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2019-06-27"))); assertThat(transaction.getShares(), is(Values.Share.factorize(100))); assertThat(transaction.getSource(), is("Dividende03.txt")); assertNull(transaction.getNote()); @@ -2285,6 +2292,7 @@ public void testDividende04() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2019-03-26T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2019-03-22"))); assertThat(transaction.getShares(), is(Values.Share.factorize(6))); assertThat(transaction.getSource(), is("Dividende04.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 29013705")); @@ -2329,6 +2337,7 @@ public void testDividende04WithSecurityInEUR() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2019-03-26T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2019-03-22"))); assertThat(transaction.getShares(), is(Values.Share.factorize(6))); assertThat(transaction.getSource(), is("Dividende04.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 29013705")); @@ -2379,6 +2388,7 @@ public void testDividende05() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-02-14T00:00"))); + assertNull(transaction.getDateEx()); assertThat(transaction.getShares(), is(Values.Share.factorize(50))); assertThat(transaction.getSource(), is("Dividende05.txt")); assertNull(transaction.getNote()); @@ -2424,6 +2434,7 @@ public void testDividende06() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2015-03-04T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2015-03-02"))); assertThat(transaction.getShares(), is(Values.Share.factorize(28))); assertThat(transaction.getSource(), is("Dividende06.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 96937413 | Ertrag für 2014")); @@ -2469,6 +2480,7 @@ public void testDividende07() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2016-12-15T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2016-12-15"))); assertThat(transaction.getShares(), is(Values.Share.factorize(5.8192))); assertThat(transaction.getSource(), is("Dividende07.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 14053767 | Ertrag für 2016/17")); @@ -2513,6 +2525,7 @@ public void testDividende08() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2019-02-05T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2019-01-31"))); assertThat(transaction.getShares(), is(Values.Share.factorize(32))); assertThat(transaction.getSource(), is("Dividende08.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 12345 | Ertrag für 2018")); @@ -2557,6 +2570,7 @@ public void testDividende08WithSecurityInEUR() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2019-02-05T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2019-01-31"))); assertThat(transaction.getShares(), is(Values.Share.factorize(32))); assertThat(transaction.getSource(), is("Dividende08.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 12345 | Ertrag für 2018")); @@ -2607,6 +2621,7 @@ public void testDividende09() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2019-09-11T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2019-08-08"))); assertThat(transaction.getShares(), is(Values.Share.factorize(40))); assertThat(transaction.getSource(), is("Dividende09.txt")); assertNull(transaction.getNote()); @@ -2652,6 +2667,7 @@ public void testDividende10() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-11-25T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2020-09-29"))); assertThat(transaction.getShares(), is(Values.Share.factorize(46))); assertThat(transaction.getSource(), is("Dividende10.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 11223344")); @@ -2697,6 +2713,7 @@ public void testDividende10WithSecurityInEUR() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-11-25T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2020-09-29"))); assertThat(transaction.getShares(), is(Values.Share.factorize(46))); assertThat(transaction.getSource(), is("Dividende10.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 11223344")); @@ -2748,6 +2765,7 @@ public void testDividende11() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-11-12T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2020-11-04"))); assertThat(transaction.getShares(), is(Values.Share.factorize(500))); assertThat(transaction.getSource(), is("Dividende11.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 23344420 | Ertrag für 2020")); @@ -2793,6 +2811,7 @@ public void testDividende11WithSecurityInEUR() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2020-11-12T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2020-11-04"))); assertThat(transaction.getShares(), is(Values.Share.factorize(500))); assertThat(transaction.getSource(), is("Dividende11.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 23344420 | Ertrag für 2020")); @@ -2844,6 +2863,7 @@ public void testDividende12() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2010-11-17T00:00"))); + assertNull(transaction.getDateEx()); assertThat(transaction.getShares(), is(Values.Share.factorize(1))); assertThat(transaction.getSource(), is("Dividende12.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 63302459")); @@ -2888,6 +2908,7 @@ public void testDividende13() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-09-15T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2021-09-15"))); assertThat(transaction.getShares(), is(Values.Share.factorize(549))); assertThat(transaction.getSource(), is("Dividende13.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 34091609 | Ertrag für 2021/22")); @@ -2933,6 +2954,7 @@ public void testDividende14() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-12-17T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2021-12-02"))); assertThat(transaction.getShares(), is(Values.Share.factorize(1000))); assertThat(transaction.getSource(), is("Dividende14.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 59788848")); @@ -2978,6 +3000,7 @@ public void testDividende14WithSecurityInEUR() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2021-12-17T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2021-12-02"))); assertThat(transaction.getShares(), is(Values.Share.factorize(1000))); assertThat(transaction.getSource(), is("Dividende14.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 59788848")); @@ -3029,6 +3052,7 @@ public void testDividende15() assertThat(transaction.getType(), is(AccountTransaction.Type.TAXES)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2017-10-20T00:00"))); + assertThat(transaction.getDateEx(), is(LocalDate.parse("2017-10-06"))); assertThat(transaction.getShares(), is(Values.Share.factorize(0.4512))); assertThat(transaction.getSource(), is("Dividende15.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 12345678 | Ertrag für 2017")); @@ -3073,6 +3097,7 @@ public void testDividende16() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2022-09-30T00:00"))); + assertNull(transaction.getDateEx()); assertThat(transaction.getShares(), is(Values.Share.factorize(15))); assertThat(transaction.getSource(), is("Dividende16.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 42739637 | Kapitalrückzahlung")); @@ -3117,6 +3142,7 @@ public void testDividende16WithSecurityInEUR() assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS)); assertThat(transaction.getDateTime(), is(LocalDateTime.parse("2022-09-30T00:00"))); + assertNull(transaction.getDateEx()); assertThat(transaction.getShares(), is(Values.Share.factorize(15))); assertThat(transaction.getSource(), is("Dividende16.txt")); assertThat(transaction.getNote(), is("Abrechnungs-Nr. 42739637 | Kapitalrückzahlung")); @@ -3160,6 +3186,7 @@ public void testDividende17() // check dividends transaction assertThat(results, hasItem(dividend( // hasDate("2019-09-09"), hasShares(60), // + /* hasDateEx("2021-12-02"), */ hasSource("Dividende17.txt"), // hasNote("Abrechnungs-Nr. 26128781"), // hasAmount("EUR", 7.65), hasGrossValue("EUR", 15.73), // @@ -3194,6 +3221,7 @@ public void testDividende17WithSecurityInEUR() // check dividends transaction assertThat(results, hasItem(dividend( // hasDate("2019-09-09"), hasShares(60), // + /* hasDateEx("2021-12-02"), */ hasSource("Dividende17.txt"), hasNote("Abrechnungs-Nr. 26128781"), // hasAmount("EUR", 7.65), hasGrossValue("EUR", 15.73), // hasTaxes("EUR", (39.00 / 9.9148) + 3.93 + 0.22), hasFees("EUR", 0.00), // @@ -3232,8 +3260,10 @@ public void testDividende18() hasCurrencyCode("EUR")))); // check dividends transaction - assertThat(results, hasItem(dividend( // + assertThat(results, hasItem(dividend/* WithExDate */( // + /* asDate("2015-12-15").toLocalDate(), */ hasDate("2015-12-17T00:00"), hasShares(156.729), // + /* hasDateEx("2021-12-02"), */ hasSource("Dividende18.txt"), // hasNote("Abrechnungs-Nr. 70187215 | Ertrag für 2014/15"), // hasAmount("EUR", 7.68), hasGrossValue("EUR", 11.84), // @@ -3278,6 +3308,7 @@ public void testDividendeStorno01() assertThat(((Transaction) cancellation.getSubject()).getDateTime(), is(LocalDateTime.parse("2020-05-15T00:00"))); + assertThat(((AccountTransaction) cancellation.getSubject()).getDateEx(), is(LocalDate.parse("2020-04-29"))); assertThat(((Transaction) cancellation.getSubject()).getShares(), is(Values.Share.factorize(46))); assertThat(((Transaction) cancellation.getSubject()).getSource(), is("DividendeStorno01.txt")); assertThat(((Transaction) cancellation.getSubject()).getNote(), is( diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/OnvistaPDFExtractor.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/OnvistaPDFExtractor.java index 2e0d46bd15..ab90b12930 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/OnvistaPDFExtractor.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/datatransfer/pdf/OnvistaPDFExtractor.java @@ -566,15 +566,17 @@ private void addDividendeTransaction() // STK 50,000 21.04.2016 21.04.2016 EUR 0,200000 // @formatter:on section -> section // - .attributes("name", "isin", "name1", "currency") // + .attributes("dateEx", "name", "isin", "name1", "currency") // .find("Gattungsbezeichnung ISIN") // .match("^(?.*) (?[A-Z]{2}[A-Z0-9]{9}[0-9])$") // .match("^([\\d]{2}\\.[\\d]{2}\\.[\\d]{2,4} )?(?.*)$") // - .match("^STK [\\.,\\d]+ [\\d]{2}\\.[\\d]{2}\\.[\\d]{2,4} [\\d]{2}\\.[\\d]{2}\\.[\\d]{2,4} (?[A-Z]{3}) [\\.,\\d]+$") // + .match("^STK [\\.,\\d]+ (?[\\d]{2}\\.[\\d]{2}\\.[\\d]{2,4}) [\\d]{2}\\.[\\d]{2}\\.[\\d]{2,4} (?[A-Z]{3}) [\\.,\\d]+$") // .assign((t, v) -> { if (!v.get("name1").startsWith("Nominal")) v.put("name", trim(v.get("name")) + " " + trim(v.get("name1"))); + t.setDateEx(asDate(v.get("dateEx")).toLocalDate()); + t.setSecurity(getOrCreateSecurity(v)); }), // @formatter:off From ecd6e923a30264078f7a62a4afe5c35b6b9ffa4c Mon Sep 17 00:00:00 2001 From: ZfT2 Date: Tue, 10 Feb 2026 15:20:04 +0100 Subject: [PATCH 3/5] Introduce ex-date field for dividend transactions to PP model - fixes from PR feedback 1 --- .../client69.binary+pwd.portfolio | Bin 1754 -> 1754 bytes .../fileversions/client69.binary.portfolio | Bin 1737 -> 1726 bytes .../src/fileversions/client69.xml | 11 +- .../datatransfer/ExtractorMatchers.java | 32 +-- .../AccountTransactionDialog.java | 23 ++- .../transactions/AccountTransactionModel.java | 3 +- .../abuchen/portfolio/ui/messages.properties | 2 - .../model/proto/v1/ClientProtos.java | 195 +++++++++--------- .../model/proto/v1/PTransaction.java | 160 +++----------- .../model/proto/v1/PTransactionOrBuilder.java | 10 +- .../portfolio/model/AccountTransaction.java | 8 +- .../portfolio/model/ProtobufWriter.java | 6 +- .../name/abuchen/portfolio/model/client.proto | 2 +- .../abuchen/portfolio/util/ProtobufUtil.java | 12 ++ 14 files changed, 178 insertions(+), 286 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.binary+pwd.portfolio b/name.abuchen.portfolio.tests/src/fileversions/client69.binary+pwd.portfolio index 01fdf247ec11809c9442c088cfc78dbd00557414..d4ea69b60f26d46319677d901ea0960b6b2db910 100644 GIT binary patch literal 1754 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 diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.binary.portfolio b/name.abuchen.portfolio.tests/src/fileversions/client69.binary.portfolio index 02467c0f1aedbab795641e03e10f5882a600ffae..aa150703e4bc65d820a334d1fa7f79c704ebe683 100644 GIT binary patch delta 1666 zcmV-|27UR-4ZaNxP)h>@6aWYa2mq&cN|6mCe-u?5cU#2GSZkeNBx?+tNr4ub&;6L$ zHMQBc3l z&ud8Mvjru`>!zXe1udgtC8J3hS-l_X(6$J`UiUr^_xk?lUw=y+dcThumSt1Hx|QRR zWPqEAWnNdTJTDiJgj7k!vXvi7rnUutYLr${g{n`?WouC59lx#$N* z4Fj}OAD=6iW+&e|yHJ`rSspuY`?kBmoMHx|?apCWa4}_%#$n=`CJ?D&-L-uI`HgXl zIL-czH1l|kTDWeufe$iCMC_G_+pBTVwp45x9%I3W3N z=J_V`GOE`xit-Iq(j!soe@EH0p+1j`j0N7UKL`*7k)(WoIp#qlP$f3ef$`PpLEKvoF0 z?6nPMiWxFo-DuKlrCI7qQcK&MYG3S$a++aXv90I$}?&-Kv2d>#74G%qB`xDTXfH9mQTu zFuUqr)nj+fz%vy+e-G_vosIZB{V z#ln`3B??x0K=C{b=crAOw=v!khgcygi1 zWAxFK7wC0dd}9X$E0`D%YMkO1KoJEFJ8&d?-&D!%?{0sEQ(eEd%Wbg3ZN`JtjqiY2 z$qAbiYGAwfvD>`@cQ}u*$&#zv7{sZ~71z=|{ty;-K(Xl(XZLM_8AQf%0LKHhJ@*L4 z?B3%ju;A8lfBROAq(|WVf%^yzP<=G@d`$Dys(mZLyx<@g+B9tWknp|*Ojc2yhIh}N zyx9j0o)-Po^?pWt2tr^B;k(ao?`~s%9>JC@d@U%7iqsrjoF$FVW>uBf3VDOiSO~7! zRyLE#tEuE1MXrg6$^FoGp0g=-e6IKotW2)RN!(%1e}|o>qRRqQnk&NP{4lp_o3zFi zvy!xNxMk|XY;&6$C8m)(VmT&OI%2IOReMUa9cjKJ&Goc}_rF`kp4%XJ#r6U?e!>Ck zX_}m3$vle*wgB zSPrYQVWwuViTRwOt57h@gfBa&nk?sXR^G_qJVLR8-AME-SdWN0(##_(u#;TpdrG@o zK~uuS=;1fo|4>T@2q1&};V=dO0FVy=08mQ-0u%rg00;;O0H=0JTp)w|;V=dO0FaZA M1~Ue11^@s60J>m4ApigX delta 1696 zcmV;R24DHU4ap4+P)h>@6aWYa2mnH+MUf37f7?_XC+${(DW#YprXaK^>b7popZTy8 zRI0SiMz?B2ZP!ghXgu4`iQCvtpP&0RRhqcK01Y%D1`G*KJ4{G$;=&GyX(!--IB?;H z#4ZRfoRB8*x05tZmv!wlX;S6B{6Bv0_y2l+E|<$=b5gv-t}sKghBR4`RnAOnGMCYj zf5@rnG(6;NCX-Xs5;AZiHSXFrCTkjU7Lvtd$w{Y*G)%bS0=2M{borBfs<(7%y3jvS z5=C)*?1UtW(pVoX_=(clo^ttmtUrF|-%CIB4Sx9FM}PDrCYhmJUR1GRh@7NpSuP_< znA5b3!Q~VcsaX}9W-iAL7}k#~xJ+Koa+;xQTwYD9SWc^AT2eMc9o`lJ*z3+`!Cv40{Oj+r!=LmpLy~03STnO6 z5_NDhu*7Mynd7895|JWGSTb{i@x->^kN3qd{PNZ9-P1u_Xa0Ho%?t1UeK9e=f48U+ ztXCc1sd(H;!Y8G?3<;H0vaNcpG4a^oZ#`kM)}Da%v+d=+aQPOL9E;T%vp*)7apoD* za*(5Aeic<+m)BjJ<*Ss|y@DXzf29%@eV1b4Jhk)%OlDSX&8@8i2;(|SmPZk9U^d(G zUS3}2+j7D4^(qEvyEZygDo&5TdTy>bb*eOS-tsJGojJ|)huf`Thj%b#k40gkng$T5 zV9l{S9(naqlh}>64mGoQg_^i#w15vXaYU@8klPDU(3Vta8XjlZdEcX$f0{w4$>eZp z_UIut6LpE`1^Ca^iECQ5W>f)6Yf}NDaUH{3##)%teI3z6G_B1m%z*6@$Ab2uhy+|u zMO`{|0{odifCw{K_lZSUXD}jqbsBqqjfP2C8KtXrJW`yRI^c!67PAqCg#-}l3Q!_*&Q_jjZ=Y9hewqL%*{vj>n33xz*3l;nLOD-onxK`Qv)oQEF4m2$2Z|bf0cq>MT82Y4Q?Z6 zO0(02j)5!_Y+5Vp%mg#2JDT30*G#k6k))=!G1Z>X73B=WI>|l--bP(vx(!T%+1|kCTKJnSnu2CqwmV`^v)wAb73r!20n7$U zLn#C0#_`*t@fLt7*2y6ZdiVKced zjmd#65zDRL51Y%SZd_j45^)l|J!)fzmVw5@CiG>D>4g>hfBZ4*A)79^@M3VnIZ6)C zmZlFSdf}N0Odg<*CR|^u;lj&1AXvskhft#wuL4En+id^Q;C)jeH^0641x|GQ+Ag<& zHn%AkQa8E-W<@(_PN;$9Y+~291Xnwku<@d!Ss28Lja90td+;GF?0{m!CCcvW7&CzM zMIVj_YPrr)e~j6^Cy;N#t>fm6DoGB*`2+V6>Z97B#FG)tBdhj}81s~k9B9*^I5%Yt`EmgFkoFx^IfHq*j2p91s_?QX%UZdRk*gh#L^=X=cM&F))OE1Fv@)kMFA*i z!`IBBf9GN9&4CyW%OOQll{7Xmmz6aI3T7Jc!3R~7q-@sA>1mupC{nQNv91N{5>Z>4 zzHbF~lIvVoX=f{_a*!A;_(=O7P)i30${OC1I|cv%rw;%CP)h*<6aW+e2nYxOLZ(Gr q${OC1I|cv%rw;%C4gdfE000000000000000lb8k|26qMk0002GsU%YX diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.xml b/name.abuchen.portfolio.tests/src/fileversions/client69.xml index 252b9ee609..bbb7e2bffb 100644 --- a/name.abuchen.portfolio.tests/src/fileversions/client69.xml +++ b/name.abuchen.portfolio.tests/src/fileversions/client69.xml @@ -13,7 +13,6 @@ - false 2026-02-04T21:30:37.744832272Z @@ -37,16 +36,10 @@ 2019-05-24_Wertpapierertrag 24.05.2019_DE000CBK1001.pdf - - - - - - - + - 2026-02-04T22:54:03.661392364Z + 2026-02-10T13:50:10.694859420Z DIVIDENDS 2019-05-23 diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java index 8b40821c2c..f69506e0bc 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/ExtractorMatchers.java @@ -134,14 +134,6 @@ public AccountTransactionMatcher(String label, AccountTransaction.Type type, Mat && tx.getSubject() instanceof AccountTransaction atx && atx.getType() == type ? atx : null, properties); } - - public AccountTransactionMatcher(String label, AccountTransaction.Type type, LocalDate dateEx, - Matcher[] properties) - { - super(label, item -> item instanceof TransactionItem tx // - && tx.getSubject() instanceof AccountTransaction atx && atx.getType() == type - && atx.getDateEx() == dateEx ? atx : null, properties); - } } private static class TransactionSecurityMatcher extends TypeSafeDiagnosingMatcher @@ -262,12 +254,6 @@ public static Matcher dividend(Matcher... propertie return new AccountTransactionMatcher("dividend", AccountTransaction.Type.DIVIDENDS, properties); //$NON-NLS-1$ } - @SafeVarargs - public static Matcher dividendWithExDate(LocalDate dateEx, Matcher... properties) - { - return new AccountTransactionMatcher("dividend", AccountTransaction.Type.DIVIDENDS, dateEx, properties); //$NON-NLS-1$ - } - @SafeVarargs public static Matcher interest(Matcher... properties) { @@ -410,16 +396,14 @@ public static Matcher hasDate(String dateString) Transaction::getDateTime); } - // public static Matcher hasDateEx(String dateString) - // { - // //LocalDate expectecd = LocalDate.parse(dateString); - // - // return new AccountTransactionMatcher("dividends", - // AccountTransaction.Type.DIVIDENDS, dateString, properties); //$NON-NLS-1$ - // - //// return new PropertyMatcher<>("dateEx", //$NON-NLS-1$ expectecd, // - //// null ); - // } + public static Matcher hasDateEx(String dateString) + { + var expected = LocalDate.parse(dateString); + + return new PropertyMatcher<>("exDate", //$NON-NLS-1$ + expected, // + t -> ((AccountTransaction) t).getDateEx()); + } public static Matcher hasShares(double value) { diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java index 7805bcdc2b..60f1f8fc99 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionDialog.java @@ -123,13 +123,17 @@ protected void createFormElements(Composite editArea) // NOSONAR dateTime.bindTime(Properties.time.name()); dateTime.bindButton(() -> model().getTime(), time -> model().setTime(time)); - Label lblDateEx = new Label(editArea, SWT.RIGHT); - lblDateEx.setText(Messages.ColumnExDate); - DatePicker dateEx = new DatePicker(editArea); - IObservableValue targetDate = new SimpleDateTimeDateSelectionProperty().observe(dateEx.getControl()); - IObservableValue modelDate = BeanProperties.value(Properties.dateEx.name()).observe(model); - context.bindValue(targetDate, modelDate); - // dateEx.setSelection(null); + Label lblDateEx = null; + DatePicker dateEx = null; + if (model().supportsShares()) + { + lblDateEx = new Label(editArea, SWT.RIGHT); + lblDateEx.setText(Messages.ColumnExDate); + dateEx = new DatePicker(editArea); + IObservableValue targetDate = new SimpleDateTimeDateSelectionProperty().observe(dateEx.getControl()); + IObservableValue modelDate = BeanProperties.value(Properties.dateEx.name()).observe(model); + context.bindValue(targetDate, modelDate); + } // shares @@ -261,7 +265,10 @@ public void widgetSelected(SelectionEvent e) startingWith(dateTime.date.getControl()).thenRight(dateTime.time).thenRight(dateTime.button, 0); - startingWith(dateTime.button).thenRight(lblDateEx).thenRight(dateEx.getControl()); + if (model().supportsShares()) + { + startingWith(dateTime.button).thenRight(lblDateEx).thenRight(dateEx.getControl()); + } // shares [- amount per share] forms.thenBelow(shares.value).width(amountWidth).label(shares.label).suffix(btnShares) // diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java index 5b10e165db..cf64ed0da8 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/dialogs/transactions/AccountTransactionModel.java @@ -235,6 +235,7 @@ public void presetFromSource(Account account, AccountTransaction transaction) LocalDateTime transactionDate = transaction.getDateTime(); this.date = transactionDate.toLocalDate(); this.time = transactionDate.toLocalTime(); + this.dateEx = transaction.getDateEx(); this.shares = transaction.getShares(); this.total = transaction.getAmount(); @@ -457,7 +458,7 @@ public LocalDate getDateEx() public void setDateEx(LocalDate dateEx) { - this.dateEx = dateEx; + firePropertyChange(Properties.dateEx.name(), this.dateEx, this.dateEx = dateEx); // NOSONAR } public long getShares() diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties index 63801d5cd0..edbe04c4e4 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties @@ -346,8 +346,6 @@ ColumnDataSeries = Data Series ColumnDate = Date -ColumnDateEx = Ex-Date - ColumnDateFirstHistoricalQuote = First historical (Date) ColumnDateFirstHistoricalQuote_MenuLabel = Date of first historical quote diff --git a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java index fc13b760f7..74a2dbafc5 100644 --- a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java +++ b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/ClientProtos.java @@ -242,7 +242,7 @@ public static void registerAllExtensions( "xRateToBase\030\006 \001(\0132%.name.abuchen.portfol" + "io.PDecimalValueH\002\210\001\001\")\n\004Type\022\017\n\013GROSS_V" + "ALUE\020\000\022\007\n\003TAX\020\001\022\007\n\003FEE\020\002B\013\n\t_fxAmountB\021\n" + - "\017_fxCurrencyCodeB\017\n\r_fxRateToBase\"\324\007\n\014PT" + + "\017_fxCurrencyCodeB\017\n\r_fxRateToBase\"\270\007\n\014PT" + "ransaction\022\014\n\004uuid\030\001 \001(\t\0227\n\004type\030\002 \001(\0162)" + ".name.abuchen.portfolio.PTransaction.Typ" + "e\022\024\n\007account\030\003 \001(\tH\000\210\001\001\022\026\n\tportfolio\030\004 \001" + @@ -250,103 +250,102 @@ public static void registerAllExtensions( "herPortfolio\030\006 \001(\tH\003\210\001\001\022\026\n\totherUuid\030\007 \001" + "(\tH\004\210\001\001\0227\n\016otherUpdatedAt\030\010 \001(\0132\032.google" + ".protobuf.TimestampH\005\210\001\001\022(\n\004date\030\t \001(\0132\032" + - ".google.protobuf.Timestamp\022/\n\006dateEx\030\022 \001" + - "(\0132\032.google.protobuf.TimestampH\006\210\001\001\022\024\n\014c" + - "urrencyCode\030\n \001(\t\022\016\n\006amount\030\013 \001(\003\022\023\n\006sha" + - "res\030\014 \001(\003H\007\210\001\001\022\021\n\004note\030\r \001(\tH\010\210\001\001\022\025\n\010sec" + - "urity\030\016 \001(\tH\t\210\001\001\0227\n\005units\030\017 \003(\0132(.name.a" + - "buchen.portfolio.PTransactionUnit\022-\n\tupd" + - "atedAt\030\020 \001(\0132\032.google.protobuf.Timestamp" + - "\022\023\n\006source\030\021 \001(\tH\n\210\001\001\"\362\001\n\004Type\022\014\n\010PURCHA" + - "SE\020\000\022\010\n\004SALE\020\001\022\024\n\020INBOUND_DELIVERY\020\002\022\025\n\021" + - "OUTBOUND_DELIVERY\020\003\022\025\n\021SECURITY_TRANSFER" + - "\020\004\022\021\n\rCASH_TRANSFER\020\005\022\013\n\007DEPOSIT\020\006\022\013\n\007RE" + - "MOVAL\020\007\022\014\n\010DIVIDEND\020\010\022\014\n\010INTEREST\020\t\022\023\n\017I" + - "NTEREST_CHARGE\020\n\022\007\n\003TAX\020\013\022\016\n\nTAX_REFUND\020" + - "\014\022\007\n\003FEE\020\r\022\016\n\nFEE_REFUND\020\016B\n\n\010_accountB\014" + - "\n\n_portfolioB\017\n\r_otherAccountB\021\n\017_otherP" + - "ortfolioB\014\n\n_otherUuidB\021\n\017_otherUpdatedA" + - "tB\t\n\007_dateExB\t\n\007_sharesB\007\n\005_noteB\013\n\t_sec" + - "urityB\t\n\007_source\"\335\003\n\017PInvestmentPlan\022\014\n\004" + - "name\030\001 \001(\t\022\021\n\004note\030\002 \001(\tH\000\210\001\001\022\025\n\010securit" + - "y\030\003 \001(\tH\001\210\001\001\022\026\n\tportfolio\030\004 \001(\tH\002\210\001\001\022\024\n\007" + - "account\030\005 \001(\tH\003\210\001\001\0225\n\nattributes\030\006 \003(\0132!" + - ".name.abuchen.portfolio.PKeyValue\022\024\n\014aut" + - "oGenerate\030\007 \001(\010\022\014\n\004date\030\010 \001(\003\022\020\n\010interva" + - "l\030\t \001(\005\022\016\n\006amount\030\n \001(\003\022\014\n\004fees\030\013 \001(\003\022\024\n" + - "\014transactions\030\014 \003(\t\022\r\n\005taxes\030\r \001(\003\022:\n\004ty" + - "pe\030\016 \001(\0162,.name.abuchen.portfolio.PInves" + - "tmentPlan.Type\"H\n\004Type\022\030\n\024PURCHASE_OR_DE" + - "LIVERY\020\000\022\013\n\007DEPOSIT\020\001\022\013\n\007REMOVAL\020\002\022\014\n\010IN" + - "TEREST\020\003B\007\n\005_noteB\013\n\t_securityB\014\n\n_portf" + - "olioB\n\n\010_account\"\252\004\n\tPTaxonomy\022\n\n\002id\030\001 \001" + - "(\t\022\014\n\004name\030\002 \001(\t\022\023\n\006source\030\003 \001(\tH\000\210\001\001\022\022\n" + - "\ndimensions\030\004 \003(\t\022I\n\017classifications\030\005 \003" + - "(\01320.name.abuchen.portfolio.PTaxonomy.Cl" + - "assification\032v\n\nAssignment\022\031\n\021investment" + - "Vehicle\030\001 \001(\t\022\016\n\006weight\030\002 \001(\005\022\014\n\004rank\030\003 " + - "\001(\005\022/\n\004data\030\004 \003(\0132!.name.abuchen.portfol" + - "io.PKeyValue\032\213\002\n\016Classification\022\n\n\002id\030\001 " + - "\001(\t\022\025\n\010parentId\030\002 \001(\tH\000\210\001\001\022\014\n\004name\030\003 \001(\t" + - "\022\021\n\004note\030\004 \001(\tH\001\210\001\001\022\r\n\005color\030\005 \001(\t\022\016\n\006we" + - "ight\030\006 \001(\005\022\014\n\004rank\030\007 \001(\005\022/\n\004data\030\010 \003(\0132!" + - ".name.abuchen.portfolio.PKeyValue\022A\n\013ass" + - "ignments\030\t \003(\0132,.name.abuchen.portfolio." + - "PTaxonomy.AssignmentB\013\n\t_parentIdB\007\n\005_no" + - "teB\t\n\007_source\"\357\003\n\nPDashboard\022\014\n\004name\030\001 \001" + - "(\t\022L\n\rconfiguration\030\002 \003(\01325.name.abuchen" + - ".portfolio.PDashboard.ConfigurationEntry" + - "\022:\n\007columns\030\003 \003(\0132).name.abuchen.portfol" + - "io.PDashboard.Column\022\n\n\002id\030\004 \001(\t\032\260\001\n\006Wid" + - "get\022\014\n\004type\030\001 \001(\t\022\r\n\005label\030\002 \001(\t\022S\n\rconf" + - "iguration\030\003 \003(\0132<.name.abuchen.portfolio" + - ".PDashboard.Widget.ConfigurationEntry\0324\n" + - "\022ConfigurationEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005valu" + - "e\030\002 \001(\t:\0028\001\032T\n\006Column\022\016\n\006weight\030\001 \001(\005\022:\n" + - "\007widgets\030\002 \003(\0132).name.abuchen.portfolio." + - "PDashboard.Widget\0324\n\022ConfigurationEntry\022" + - "\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"+\n\tPBook" + - "mark\022\r\n\005label\030\001 \001(\t\022\017\n\007pattern\030\002 \001(\t\"\307\001\n" + - "\016PAttributeType\022\n\n\002id\030\001 \001(\t\022\014\n\004name\030\002 \001(" + - "\t\022\023\n\013columnLabel\030\003 \001(\t\022\023\n\006source\030\004 \001(\tH\000" + - "\210\001\001\022\016\n\006target\030\005 \001(\t\022\014\n\004type\030\006 \001(\t\022\026\n\016con" + - "verterClass\030\007 \001(\t\0220\n\nproperties\030\010 \001(\0132\034." + - "name.abuchen.portfolio.PMapB\t\n\007_source\"J" + - "\n\021PConfigurationSet\022\013\n\003key\030\001 \001(\t\022\014\n\004uuid" + - "\030\002 \001(\t\022\014\n\004name\030\003 \001(\t\022\014\n\004data\030\004 \001(\t\"\307\001\n\tP" + - "Settings\0224\n\tbookmarks\030\001 \003(\0132!.name.abuch" + - "en.portfolio.PBookmark\022>\n\016attributeTypes" + - "\030\002 \003(\0132&.name.abuchen.portfolio.PAttribu" + - "teType\022D\n\021configurationSets\030\003 \003(\0132).name" + - ".abuchen.portfolio.PConfigurationSet\"\305\005\n" + - "\007PClient\022\017\n\007version\030\001 \001(\005\0225\n\nsecurities\030" + - "\002 \003(\0132!.name.abuchen.portfolio.PSecurity" + - "\0222\n\010accounts\030\003 \003(\0132 .name.abuchen.portfo" + - "lio.PAccount\0226\n\nportfolios\030\004 \003(\0132\".name." + - "abuchen.portfolio.PPortfolio\022:\n\014transact" + - "ions\030\005 \003(\0132$.name.abuchen.portfolio.PTra" + - "nsaction\0226\n\005plans\030\006 \003(\0132\'.name.abuchen.p" + - "ortfolio.PInvestmentPlan\0226\n\nwatchlists\030\007" + - " \003(\0132\".name.abuchen.portfolio.PWatchlist" + - "\0225\n\ntaxonomies\030\010 \003(\0132!.name.abuchen.port" + - "folio.PTaxonomy\0226\n\ndashboards\030\t \003(\0132\".na" + - "me.abuchen.portfolio.PDashboard\022C\n\nprope" + - "rties\030\n \003(\0132/.name.abuchen.portfolio.PCl" + - "ient.PropertiesEntry\0223\n\010settings\030\013 \001(\0132!" + - ".name.abuchen.portfolio.PSettings\022\024\n\014bas" + - "eCurrency\030\014 \001(\t\022(\n\nextensions\030c \003(\0132\024.go" + - "ogle.protobuf.Any\0321\n\017PropertiesEntry\022\013\n\003" + - "key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"S\n\rPExchang" + - "eRate\022\014\n\004date\030\001 \001(\003\0224\n\005value\030\002 \001(\0132%.nam" + - "e.abuchen.portfolio.PDecimalValue\"\203\001\n\027PE" + - "xchangeRateTimeSeries\022\024\n\014baseCurrency\030\001 " + - "\001(\t\022\024\n\014termCurrency\030\002 \001(\t\022<\n\rexchangeRat" + - "es\030\003 \003(\0132%.name.abuchen.portfolio.PExcha" + - "ngeRate\"a\n\010PECBData\022\024\n\014lastModified\030\001 \001(" + - "\003\022?\n\006series\030\002 \003(\0132/.name.abuchen.portfol" + - "io.PExchangeRateTimeSeriesB7\n%name.abuch" + - "en.portfolio.model.proto.v1B\014ClientProto" + - "sP\001b\006proto3" + ".google.protobuf.Timestamp\022\023\n\006dateEx\030\022 \001" + + "(\003H\006\210\001\001\022\024\n\014currencyCode\030\n \001(\t\022\016\n\006amount\030" + + "\013 \001(\003\022\023\n\006shares\030\014 \001(\003H\007\210\001\001\022\021\n\004note\030\r \001(\t" + + "H\010\210\001\001\022\025\n\010security\030\016 \001(\tH\t\210\001\001\0227\n\005units\030\017 " + + "\003(\0132(.name.abuchen.portfolio.PTransactio" + + "nUnit\022-\n\tupdatedAt\030\020 \001(\0132\032.google.protob" + + "uf.Timestamp\022\023\n\006source\030\021 \001(\tH\n\210\001\001\"\362\001\n\004Ty" + + "pe\022\014\n\010PURCHASE\020\000\022\010\n\004SALE\020\001\022\024\n\020INBOUND_DE" + + "LIVERY\020\002\022\025\n\021OUTBOUND_DELIVERY\020\003\022\025\n\021SECUR" + + "ITY_TRANSFER\020\004\022\021\n\rCASH_TRANSFER\020\005\022\013\n\007DEP" + + "OSIT\020\006\022\013\n\007REMOVAL\020\007\022\014\n\010DIVIDEND\020\010\022\014\n\010INT" + + "EREST\020\t\022\023\n\017INTEREST_CHARGE\020\n\022\007\n\003TAX\020\013\022\016\n" + + "\nTAX_REFUND\020\014\022\007\n\003FEE\020\r\022\016\n\nFEE_REFUND\020\016B\n" + + "\n\010_accountB\014\n\n_portfolioB\017\n\r_otherAccoun" + + "tB\021\n\017_otherPortfolioB\014\n\n_otherUuidB\021\n\017_o" + + "therUpdatedAtB\t\n\007_dateExB\t\n\007_sharesB\007\n\005_" + + "noteB\013\n\t_securityB\t\n\007_source\"\335\003\n\017PInvest" + + "mentPlan\022\014\n\004name\030\001 \001(\t\022\021\n\004note\030\002 \001(\tH\000\210\001" + + "\001\022\025\n\010security\030\003 \001(\tH\001\210\001\001\022\026\n\tportfolio\030\004 " + + "\001(\tH\002\210\001\001\022\024\n\007account\030\005 \001(\tH\003\210\001\001\0225\n\nattrib" + + "utes\030\006 \003(\0132!.name.abuchen.portfolio.PKey" + + "Value\022\024\n\014autoGenerate\030\007 \001(\010\022\014\n\004date\030\010 \001(" + + "\003\022\020\n\010interval\030\t \001(\005\022\016\n\006amount\030\n \001(\003\022\014\n\004f" + + "ees\030\013 \001(\003\022\024\n\014transactions\030\014 \003(\t\022\r\n\005taxes" + + "\030\r \001(\003\022:\n\004type\030\016 \001(\0162,.name.abuchen.port" + + "folio.PInvestmentPlan.Type\"H\n\004Type\022\030\n\024PU" + + "RCHASE_OR_DELIVERY\020\000\022\013\n\007DEPOSIT\020\001\022\013\n\007REM" + + "OVAL\020\002\022\014\n\010INTEREST\020\003B\007\n\005_noteB\013\n\t_securi" + + "tyB\014\n\n_portfolioB\n\n\010_account\"\252\004\n\tPTaxono" + + "my\022\n\n\002id\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\023\n\006source\030\003" + + " \001(\tH\000\210\001\001\022\022\n\ndimensions\030\004 \003(\t\022I\n\017classif" + + "ications\030\005 \003(\01320.name.abuchen.portfolio." + + "PTaxonomy.Classification\032v\n\nAssignment\022\031" + + "\n\021investmentVehicle\030\001 \001(\t\022\016\n\006weight\030\002 \001(" + + "\005\022\014\n\004rank\030\003 \001(\005\022/\n\004data\030\004 \003(\0132!.name.abu" + + "chen.portfolio.PKeyValue\032\213\002\n\016Classificat" + + "ion\022\n\n\002id\030\001 \001(\t\022\025\n\010parentId\030\002 \001(\tH\000\210\001\001\022\014" + + "\n\004name\030\003 \001(\t\022\021\n\004note\030\004 \001(\tH\001\210\001\001\022\r\n\005color" + + "\030\005 \001(\t\022\016\n\006weight\030\006 \001(\005\022\014\n\004rank\030\007 \001(\005\022/\n\004" + + "data\030\010 \003(\0132!.name.abuchen.portfolio.PKey" + + "Value\022A\n\013assignments\030\t \003(\0132,.name.abuche" + + "n.portfolio.PTaxonomy.AssignmentB\013\n\t_par" + + "entIdB\007\n\005_noteB\t\n\007_source\"\357\003\n\nPDashboard" + + "\022\014\n\004name\030\001 \001(\t\022L\n\rconfiguration\030\002 \003(\01325." + + "name.abuchen.portfolio.PDashboard.Config" + + "urationEntry\022:\n\007columns\030\003 \003(\0132).name.abu" + + "chen.portfolio.PDashboard.Column\022\n\n\002id\030\004" + + " \001(\t\032\260\001\n\006Widget\022\014\n\004type\030\001 \001(\t\022\r\n\005label\030\002" + + " \001(\t\022S\n\rconfiguration\030\003 \003(\0132<.name.abuch" + + "en.portfolio.PDashboard.Widget.Configura" + + "tionEntry\0324\n\022ConfigurationEntry\022\013\n\003key\030\001" + + " \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\032T\n\006Column\022\016\n\006wei" + + "ght\030\001 \001(\005\022:\n\007widgets\030\002 \003(\0132).name.abuche" + + "n.portfolio.PDashboard.Widget\0324\n\022Configu" + + "rationEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:" + + "\0028\001\"+\n\tPBookmark\022\r\n\005label\030\001 \001(\t\022\017\n\007patte" + + "rn\030\002 \001(\t\"\307\001\n\016PAttributeType\022\n\n\002id\030\001 \001(\t\022" + + "\014\n\004name\030\002 \001(\t\022\023\n\013columnLabel\030\003 \001(\t\022\023\n\006so" + + "urce\030\004 \001(\tH\000\210\001\001\022\016\n\006target\030\005 \001(\t\022\014\n\004type\030" + + "\006 \001(\t\022\026\n\016converterClass\030\007 \001(\t\0220\n\npropert" + + "ies\030\010 \001(\0132\034.name.abuchen.portfolio.PMapB" + + "\t\n\007_source\"J\n\021PConfigurationSet\022\013\n\003key\030\001" + + " \001(\t\022\014\n\004uuid\030\002 \001(\t\022\014\n\004name\030\003 \001(\t\022\014\n\004data" + + "\030\004 \001(\t\"\307\001\n\tPSettings\0224\n\tbookmarks\030\001 \003(\0132" + + "!.name.abuchen.portfolio.PBookmark\022>\n\016at" + + "tributeTypes\030\002 \003(\0132&.name.abuchen.portfo" + + "lio.PAttributeType\022D\n\021configurationSets\030" + + "\003 \003(\0132).name.abuchen.portfolio.PConfigur" + + "ationSet\"\305\005\n\007PClient\022\017\n\007version\030\001 \001(\005\0225\n" + + "\nsecurities\030\002 \003(\0132!.name.abuchen.portfol" + + "io.PSecurity\0222\n\010accounts\030\003 \003(\0132 .name.ab" + + "uchen.portfolio.PAccount\0226\n\nportfolios\030\004" + + " \003(\0132\".name.abuchen.portfolio.PPortfolio" + + "\022:\n\014transactions\030\005 \003(\0132$.name.abuchen.po" + + "rtfolio.PTransaction\0226\n\005plans\030\006 \003(\0132\'.na" + + "me.abuchen.portfolio.PInvestmentPlan\0226\n\n" + + "watchlists\030\007 \003(\0132\".name.abuchen.portfoli" + + "o.PWatchlist\0225\n\ntaxonomies\030\010 \003(\0132!.name." + + "abuchen.portfolio.PTaxonomy\0226\n\ndashboard" + + "s\030\t \003(\0132\".name.abuchen.portfolio.PDashbo" + + "ard\022C\n\nproperties\030\n \003(\0132/.name.abuchen.p" + + "ortfolio.PClient.PropertiesEntry\0223\n\010sett" + + "ings\030\013 \001(\0132!.name.abuchen.portfolio.PSet" + + "tings\022\024\n\014baseCurrency\030\014 \001(\t\022(\n\nextension" + + "s\030c \003(\0132\024.google.protobuf.Any\0321\n\017Propert" + + "iesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001" + + "\"S\n\rPExchangeRate\022\014\n\004date\030\001 \001(\003\0224\n\005value" + + "\030\002 \001(\0132%.name.abuchen.portfolio.PDecimal" + + "Value\"\203\001\n\027PExchangeRateTimeSeries\022\024\n\014bas" + + "eCurrency\030\001 \001(\t\022\024\n\014termCurrency\030\002 \001(\t\022<\n" + + "\rexchangeRates\030\003 \003(\0132%.name.abuchen.port" + + "folio.PExchangeRate\"a\n\010PECBData\022\024\n\014lastM" + + "odified\030\001 \001(\003\022?\n\006series\030\002 \003(\0132/.name.abu" + + "chen.portfolio.PExchangeRateTimeSeriesB7" + + "\n%name.abuchen.portfolio.model.proto.v1B" + + "\014ClientProtosP\001b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, diff --git a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java index 11dfb0c86c..fb43a00493 100644 --- a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java +++ b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransaction.java @@ -621,9 +621,9 @@ public com.google.protobuf.TimestampOrBuilder getDateOrBuilder() { } public static final int DATEEX_FIELD_NUMBER = 18; - private com.google.protobuf.Timestamp dateEx_; + private long dateEx_ = 0L; /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; * @return Whether the dateEx field is set. */ @java.lang.Override @@ -631,19 +631,12 @@ public boolean hasDateEx() { return ((bitField0_ & 0x00000040) != 0); } /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; * @return The dateEx. */ @java.lang.Override - public com.google.protobuf.Timestamp getDateEx() { - return dateEx_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; - } - /** - * optional .google.protobuf.Timestamp dateEx = 18; - */ - @java.lang.Override - public com.google.protobuf.TimestampOrBuilder getDateExOrBuilder() { - return dateEx_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; + public long getDateEx() { + return dateEx_; } public static final int CURRENCYCODE_FIELD_NUMBER = 10; @@ -989,7 +982,7 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) com.google.protobuf.GeneratedMessageV3.writeString(output, 17, source_); } if (((bitField0_ & 0x00000040) != 0)) { - output.writeMessage(18, getDateEx()); + output.writeInt64(18, dateEx_); } getUnknownFields().writeTo(output); } @@ -1060,7 +1053,7 @@ public int getSerializedSize() { } if (((bitField0_ & 0x00000040) != 0)) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(18, getDateEx()); + .computeInt64Size(18, dateEx_); } size += getUnknownFields().getSerializedSize(); memoizedSize = size; @@ -1117,8 +1110,8 @@ public boolean equals(final java.lang.Object obj) { } if (hasDateEx() != other.hasDateEx()) return false; if (hasDateEx()) { - if (!getDateEx() - .equals(other.getDateEx())) return false; + if (getDateEx() + != other.getDateEx()) return false; } if (!getCurrencyCode() .equals(other.getCurrencyCode())) return false; @@ -1196,7 +1189,8 @@ public int hashCode() { } if (hasDateEx()) { hash = (37 * hash) + DATEEX_FIELD_NUMBER; - hash = (53 * hash) + getDateEx().hashCode(); + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getDateEx()); } hash = (37 * hash) + CURRENCYCODE_FIELD_NUMBER; hash = (53 * hash) + getCurrencyCode().hashCode(); @@ -1358,7 +1352,6 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { getOtherUpdatedAtFieldBuilder(); getDateFieldBuilder(); - getDateExFieldBuilder(); getUnitsFieldBuilder(); getUpdatedAtFieldBuilder(); } @@ -1384,11 +1377,7 @@ public Builder clear() { dateBuilder_.dispose(); dateBuilder_ = null; } - dateEx_ = null; - if (dateExBuilder_ != null) { - dateExBuilder_.dispose(); - dateExBuilder_ = null; - } + dateEx_ = 0L; currencyCode_ = ""; amount_ = 0L; shares_ = 0L; @@ -1492,9 +1481,7 @@ private void buildPartial0(name.abuchen.portfolio.model.proto.v1.PTransaction re : dateBuilder_.build(); } if (((from_bitField0_ & 0x00000200) != 0)) { - result.dateEx_ = dateExBuilder_ == null - ? dateEx_ - : dateExBuilder_.build(); + result.dateEx_ = dateEx_; to_bitField0_ |= 0x00000040; } if (((from_bitField0_ & 0x00000400) != 0)) { @@ -1579,7 +1566,7 @@ public Builder mergeFrom(name.abuchen.portfolio.model.proto.v1.PTransaction othe mergeDate(other.getDate()); } if (other.hasDateEx()) { - mergeDateEx(other.getDateEx()); + setDateEx(other.getDateEx()); } if (!other.getCurrencyCode().isEmpty()) { currencyCode_ = other.currencyCode_; @@ -1761,13 +1748,11 @@ public Builder mergeFrom( bitField0_ |= 0x00020000; break; } // case 138 - case 146: { - input.readMessage( - getDateExFieldBuilder().getBuilder(), - extensionRegistry); + case 144: { + dateEx_ = input.readInt64(); bitField0_ |= 0x00000200; break; - } // case 146 + } // case 144 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -2543,124 +2528,45 @@ public com.google.protobuf.TimestampOrBuilder getDateOrBuilder() { return dateBuilder_; } - private com.google.protobuf.Timestamp dateEx_; - private com.google.protobuf.SingleFieldBuilderV3< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> dateExBuilder_; + private long dateEx_ ; /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; * @return Whether the dateEx field is set. */ + @java.lang.Override public boolean hasDateEx() { return ((bitField0_ & 0x00000200) != 0); } /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; * @return The dateEx. */ - public com.google.protobuf.Timestamp getDateEx() { - if (dateExBuilder_ == null) { - return dateEx_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; - } else { - return dateExBuilder_.getMessage(); - } - } - /** - * optional .google.protobuf.Timestamp dateEx = 18; - */ - public Builder setDateEx(com.google.protobuf.Timestamp value) { - if (dateExBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - dateEx_ = value; - } else { - dateExBuilder_.setMessage(value); - } - bitField0_ |= 0x00000200; - onChanged(); - return this; - } - /** - * optional .google.protobuf.Timestamp dateEx = 18; - */ - public Builder setDateEx( - com.google.protobuf.Timestamp.Builder builderForValue) { - if (dateExBuilder_ == null) { - dateEx_ = builderForValue.build(); - } else { - dateExBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000200; - onChanged(); - return this; + @java.lang.Override + public long getDateEx() { + return dateEx_; } /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; + * @param value The dateEx to set. + * @return This builder for chaining. */ - public Builder mergeDateEx(com.google.protobuf.Timestamp value) { - if (dateExBuilder_ == null) { - if (((bitField0_ & 0x00000200) != 0) && - dateEx_ != null && - dateEx_ != com.google.protobuf.Timestamp.getDefaultInstance()) { - getDateExBuilder().mergeFrom(value); - } else { - dateEx_ = value; - } - } else { - dateExBuilder_.mergeFrom(value); - } + public Builder setDateEx(long value) { + + dateEx_ = value; bitField0_ |= 0x00000200; onChanged(); return this; } /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; + * @return This builder for chaining. */ public Builder clearDateEx() { bitField0_ = (bitField0_ & ~0x00000200); - dateEx_ = null; - if (dateExBuilder_ != null) { - dateExBuilder_.dispose(); - dateExBuilder_ = null; - } + dateEx_ = 0L; onChanged(); return this; } - /** - * optional .google.protobuf.Timestamp dateEx = 18; - */ - public com.google.protobuf.Timestamp.Builder getDateExBuilder() { - bitField0_ |= 0x00000200; - onChanged(); - return getDateExFieldBuilder().getBuilder(); - } - /** - * optional .google.protobuf.Timestamp dateEx = 18; - */ - public com.google.protobuf.TimestampOrBuilder getDateExOrBuilder() { - if (dateExBuilder_ != null) { - return dateExBuilder_.getMessageOrBuilder(); - } else { - return dateEx_ == null ? - com.google.protobuf.Timestamp.getDefaultInstance() : dateEx_; - } - } - /** - * optional .google.protobuf.Timestamp dateEx = 18; - */ - private com.google.protobuf.SingleFieldBuilderV3< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> - getDateExFieldBuilder() { - if (dateExBuilder_ == null) { - dateExBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>( - getDateEx(), - getParentForChildren(), - isClean()); - dateEx_ = null; - } - return dateExBuilder_; - } private java.lang.Object currencyCode_ = ""; /** diff --git a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java index a2e736a6a5..24586fcbac 100644 --- a/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java +++ b/name.abuchen.portfolio/protos/name/abuchen/portfolio/model/proto/v1/PTransactionOrBuilder.java @@ -146,19 +146,15 @@ public interface PTransactionOrBuilder extends com.google.protobuf.TimestampOrBuilder getDateOrBuilder(); /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; * @return Whether the dateEx field is set. */ boolean hasDateEx(); /** - * optional .google.protobuf.Timestamp dateEx = 18; + * optional int64 dateEx = 18; * @return The dateEx. */ - com.google.protobuf.Timestamp getDateEx(); - /** - * optional .google.protobuf.Timestamp dateEx = 18; - */ - com.google.protobuf.TimestampOrBuilder getDateExOrBuilder(); + long getDateEx(); /** * string currencyCode = 10; diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java index 16733a644d..431ed02169 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/AccountTransaction.java @@ -66,13 +66,6 @@ public AccountTransaction(LocalDateTime date, String currencyCode, long amount, this.type = type; } - public AccountTransaction(LocalDateTime date, LocalDate dateEx, String currencyCode, long amount, Security security, - Type type) - { - new AccountTransaction(date, currencyCode, amount, security, type); - this.dateEx = dateEx; - } - public Type getType() { return type; @@ -92,6 +85,7 @@ public LocalDate getDateEx() public void setDateEx(LocalDate dateEx) { this.dateEx = dateEx; + setUpdatedAt(Instant.now()); } /** diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java index 72bd8e4e9a..02b7318bac 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java @@ -5,8 +5,10 @@ import static name.abuchen.portfolio.util.ProtobufUtil.asTimestamp; import static name.abuchen.portfolio.util.ProtobufUtil.asUpdatedAtTimestamp; import static name.abuchen.portfolio.util.ProtobufUtil.fromDecimalValue; +import static name.abuchen.portfolio.util.ProtobufUtil.fromLong; import static name.abuchen.portfolio.util.ProtobufUtil.fromTimestamp; import static name.abuchen.portfolio.util.ProtobufUtil.fromUpdatedAtTimestamp; +import static name.abuchen.portfolio.util.ProtobufUtil.toLong; import java.io.IOException; import java.io.InputStream; @@ -475,7 +477,7 @@ private void loadTransactions(PClient newClient, Lookup lookup) AccountTransaction dividend = new AccountTransaction(newTransaction.getUuid()); dividend.setType(AccountTransaction.Type.DIVIDENDS); if (newTransaction.hasDateEx()) - dividend.setDateEx(fromTimestamp(newTransaction.getDateEx()).toLocalDate()); + dividend.setDateEx(fromLong(newTransaction.getDateEx())); loadCommonTransaction(newTransaction, dividend, lookup, false); // If the dividend has no instrument, convert it to an @@ -1129,7 +1131,7 @@ private void addTransaction(PClient.Builder newClient, Account account, AccountT case DIVIDENDS: newTransaction.setTypeValue(PTransaction.Type.DIVIDEND_VALUE); if (t.getDateEx() != null) - newTransaction.setDateEx(asTimestamp(t.getDateEx().atStartOfDay())); + newTransaction.setDateEx(toLong(t.getDateEx())); break; case FEES: newTransaction.setTypeValue(PTransaction.Type.FEE_VALUE); diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto index 0713d84657..dcb6e039e5 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/client.proto @@ -172,7 +172,7 @@ message PTransaction { optional google.protobuf.Timestamp otherUpdatedAt = 8; google.protobuf.Timestamp date = 9; - optional google.protobuf.Timestamp dateEx = 18; + optional int64 dateEx = 18; string currencyCode = 10; int64 amount = 11; diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java index 1abdd52047..6081172429 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java @@ -4,7 +4,9 @@ import java.math.BigInteger; import java.math.MathContext; import java.time.Instant; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZoneOffset; import com.google.protobuf.ByteString; @@ -40,6 +42,16 @@ public static Instant fromUpdatedAtTimestamp(Timestamp ts) return Instant.ofEpochSecond(ts.getSeconds(), ts.getNanos()); } + public static LocalDate fromLong(long longValue) + { + return LocalDate.ofInstant(Instant.ofEpochMilli(longValue), ZoneOffset.UTC); + } + + public static long toLong(LocalDate localDate) + { + return localDate.atStartOfDay(ZoneId.ofOffset("", ZoneOffset.UTC)).toInstant().toEpochMilli(); //$NON-NLS-1$ + } + public static PDecimalValue asDecimalValue(BigDecimal number) { return PDecimalValue.newBuilder().setScale(number.scale()).setPrecision(number.precision()) From 91df47c468a33c22b57442ee5a0d11085937881c Mon Sep 17 00:00:00 2001 From: ZfT2 Date: Tue, 10 Feb 2026 15:20:56 +0100 Subject: [PATCH 4/5] Introduce ex-date field for dividend transactions to PP model - adjusted PDF Extractor with ex date example --- .../datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java index 2a812ce469..502d7c3249 100644 --- a/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java +++ b/name.abuchen.portfolio.tests/src/name/abuchen/portfolio/datatransfer/pdf/onvista/OnvistaPDFExtractorTest.java @@ -8,6 +8,7 @@ import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasAmount; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasCurrencyCode; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasDate; +import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasDateEx; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasFees; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasForexGrossValue; import static name.abuchen.portfolio.datatransfer.ExtractorMatchers.hasGrossValue; @@ -3221,7 +3222,7 @@ public void testDividende17WithSecurityInEUR() // check dividends transaction assertThat(results, hasItem(dividend( // hasDate("2019-09-09"), hasShares(60), // - /* hasDateEx("2021-12-02"), */ + hasDateEx("2019-08-30"), hasSource("Dividende17.txt"), hasNote("Abrechnungs-Nr. 26128781"), // hasAmount("EUR", 7.65), hasGrossValue("EUR", 15.73), // hasTaxes("EUR", (39.00 / 9.9148) + 3.93 + 0.22), hasFees("EUR", 0.00), // @@ -3260,10 +3261,9 @@ public void testDividende18() hasCurrencyCode("EUR")))); // check dividends transaction - assertThat(results, hasItem(dividend/* WithExDate */( // - /* asDate("2015-12-15").toLocalDate(), */ + assertThat(results, hasItem(dividend( hasDate("2015-12-17T00:00"), hasShares(156.729), // - /* hasDateEx("2021-12-02"), */ + hasDateEx("2015-12-15"), hasSource("Dividende18.txt"), // hasNote("Abrechnungs-Nr. 70187215 | Ertrag für 2014/15"), // hasAmount("EUR", 7.68), hasGrossValue("EUR", 11.84), // From 154e4a9cb4d145b7e264ffc6b1df3f64632c6dd5 Mon Sep 17 00:00:00 2001 From: ZfT2 Date: Tue, 10 Feb 2026 16:02:58 +0100 Subject: [PATCH 5/5] Introduce ex-date field for dividend transactions to PP model - fixes from PR feedback 2 --- .../client69.binary+pwd.portfolio | Bin 1754 -> 1738 bytes .../fileversions/client69.binary.portfolio | Bin 1726 -> 1723 bytes .../src/fileversions/client69.xml | 1 + .../portfolio/model/ProtobufWriter.java | 6 ++---- .../abuchen/portfolio/util/ProtobufUtil.java | 12 ------------ 5 files changed, 3 insertions(+), 16 deletions(-) diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.binary+pwd.portfolio b/name.abuchen.portfolio.tests/src/fileversions/client69.binary+pwd.portfolio index d4ea69b60f26d46319677d901ea0960b6b2db910..9d1404f17c37df654d85cadd1f78c2c5c76e6cf9 100644 GIT binary patch literal 1738 zcmV;*1~vImPf}DyPfSTq0lQ3lKW&xC8*YR&bPNnMFbI__gGO=mv&d$=OxIzd9bitz zT;+jnAsu{nRI5yQhL-R|fCo#}x?Ip}<0+eCg28grYfL4qZsa6tsV_TqL0Z7fD#AD! zX<&44?k5=Vo<(1}<0MCSRXxcSP&46?jJ}z*OcApfgIyj=qZ0tz>Hzhlxu%nzFqq3R z^4Ne#;b$tYUckVMZ&2q5w6NGv%HO;&n-0fp1@&58b$QYKU9x_PJQRb>*pAC&d~GMm zzW{OS1e_X}sm^xNLpL;i`h~)QaU~H@;!BdIF zeiUWqR&Pn4U|7LYcq%dt!Khc0rheG>V?jl)fYcFk7AX$v`|rUPHo$3U3rqEZOb`yP zHEj#-`9f=NnOVjEzYKI=;$;AHPsU&>I(tFP<@fZ@DuO%JN-K4;#?q;48;Ch+-|ab# zX-ubmYej!CFFk(I&9n}7asT~tk_Gd4sEoNfUtT&9zaq=5lI2FDU>II^A8ybZbpvz0 zvTHMX#CUR#3b04u<7S=GrnRv7N{c$Cp^e75VLVB6#=Gr0U`NkzHJe_cee)Re)Z zL0WSmU?x^M?r{zwGqV$n-&rt}?<>QZ%BZXqu{Lg&4Q@femKliz+t%uL76?2qBOAu6 zUP}vzmwCw(BX->yqx6?7Vx@OgpQu~iukaj|%^Y5;mAO;)5*`^SOwzx)?so@%t>D)- zX#~7)m(SjPBTf!{|J*2q4{utLcAb#0h2tJ_WAFKWg}@K{!iU=J zuiof~7R4~er<4E{tbBERq)=IXub0rTM0)_IIv0AQmI8dLZo=#DJKJj~WwU=xcP5!+ zR5}?jq8j1UOtfVdsbfVbJevDKa}zX^mL>;`TEGl5yRWmCsQ3L z*95F%J25S}Hv@0*C2shTC_BsQE(~;bg4aXId$^>Kcj+=(X5QjK)#Ifs=SWL({rzPZ z=l5|hiBhUqyu3d(kd^;30^C8K-ncNLc0s)RMNJbRXc`l)n`q}`A<&gb=6Hz6k%*A! zSunl3N?s_g-K)Ii0c@1QP=l!g-x7ObGb-zn9PVvXRP}3wNQCYm?+&KgK70(~Bd%#d z238Cc|1#hT-HiU=qP?C?JNtQVNLO4p4pJsTj&F-EJ g)|OU-jqw=fIlb#=hbc5)=TcB#!a#Jsa8`@Prb`J*e*gdg literal 1754 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 diff --git a/name.abuchen.portfolio.tests/src/fileversions/client69.xml b/name.abuchen.portfolio.tests/src/fileversions/client69.xml index bbb7e2bffb..af93a27157 100644 --- a/name.abuchen.portfolio.tests/src/fileversions/client69.xml +++ b/name.abuchen.portfolio.tests/src/fileversions/client69.xml @@ -13,6 +13,7 @@ + false 2026-02-04T21:30:37.744832272Z diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java index 02b7318bac..e2f5b31dc8 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/model/ProtobufWriter.java @@ -5,10 +5,8 @@ import static name.abuchen.portfolio.util.ProtobufUtil.asTimestamp; import static name.abuchen.portfolio.util.ProtobufUtil.asUpdatedAtTimestamp; import static name.abuchen.portfolio.util.ProtobufUtil.fromDecimalValue; -import static name.abuchen.portfolio.util.ProtobufUtil.fromLong; import static name.abuchen.portfolio.util.ProtobufUtil.fromTimestamp; import static name.abuchen.portfolio.util.ProtobufUtil.fromUpdatedAtTimestamp; -import static name.abuchen.portfolio.util.ProtobufUtil.toLong; import java.io.IOException; import java.io.InputStream; @@ -477,7 +475,7 @@ private void loadTransactions(PClient newClient, Lookup lookup) AccountTransaction dividend = new AccountTransaction(newTransaction.getUuid()); dividend.setType(AccountTransaction.Type.DIVIDENDS); if (newTransaction.hasDateEx()) - dividend.setDateEx(fromLong(newTransaction.getDateEx())); + dividend.setDateEx(LocalDate.ofEpochDay(newTransaction.getDateEx())); loadCommonTransaction(newTransaction, dividend, lookup, false); // If the dividend has no instrument, convert it to an @@ -1131,7 +1129,7 @@ private void addTransaction(PClient.Builder newClient, Account account, AccountT case DIVIDENDS: newTransaction.setTypeValue(PTransaction.Type.DIVIDEND_VALUE); if (t.getDateEx() != null) - newTransaction.setDateEx(toLong(t.getDateEx())); + newTransaction.setDateEx(t.getDateEx().toEpochDay()); break; case FEES: newTransaction.setTypeValue(PTransaction.Type.FEE_VALUE); diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java index 6081172429..1abdd52047 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/util/ProtobufUtil.java @@ -4,9 +4,7 @@ import java.math.BigInteger; import java.math.MathContext; import java.time.Instant; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.ZoneId; import java.time.ZoneOffset; import com.google.protobuf.ByteString; @@ -42,16 +40,6 @@ public static Instant fromUpdatedAtTimestamp(Timestamp ts) return Instant.ofEpochSecond(ts.getSeconds(), ts.getNanos()); } - public static LocalDate fromLong(long longValue) - { - return LocalDate.ofInstant(Instant.ofEpochMilli(longValue), ZoneOffset.UTC); - } - - public static long toLong(LocalDate localDate) - { - return localDate.atStartOfDay(ZoneId.ofOffset("", ZoneOffset.UTC)).toInstant().toEpochMilli(); //$NON-NLS-1$ - } - public static PDecimalValue asDecimalValue(BigDecimal number) { return PDecimalValue.newBuilder().setScale(number.scale()).setPrecision(number.precision())