001package io.konik.csv.converter;
002
003import com.google.common.base.Function;
004import com.google.common.collect.Lists;
005import com.neovisionaries.i18n.CurrencyCode;
006import io.konik.csv.model.Row;
007import io.konik.zugferd.Invoice;
008import io.konik.zugferd.entity.*;
009import io.konik.zugferd.entity.trade.Agreement;
010import io.konik.zugferd.entity.trade.Settlement;
011import io.konik.zugferd.entity.trade.Trade;
012import io.konik.zugferd.entity.trade.item.*;
013
014import javax.annotation.Nullable;
015import java.util.Date;
016import java.util.List;
017import java.util.Objects;
018
019final public class InvoiceToRowConverter {
020
021        public static Row convert(Invoice invoice) {
022                if (invoice == null) {
023                        throw new IllegalArgumentException("Invoice cannot be null");
024                }
025
026                return new Process().run(invoice);
027        }
028
029        private static class Process {
030                public Row run(Invoice invoice) {
031                        Row row = new Row();
032                        row.setHeader(mapHeader(invoice));
033
034                        Trade trade = invoice.getTrade();
035                        if (trade != null) {
036
037                                Agreement agreement = trade.getAgreement();
038                                if (agreement != null) {
039
040                                        if (agreement.getBuyer() != null) {
041                                                row.setRecipient(mapTradeParty(agreement.getBuyer()));
042                                        } else {
043                                                row.setRecipient(new Row.TradeParty());
044                                        }
045
046                                        if (agreement.getSeller() != null) {
047                                                row.setIssuer(mapTradeParty(agreement.getSeller()));
048                                        } else {
049                                                row.setIssuer(new Row.TradeParty());
050                                        }
051                                }
052
053                                Settlement settlement = trade.getSettlement();
054                                if (settlement != null) {
055
056                                        if (settlement.getPaymentMeans() != null && !settlement.getPaymentMeans().isEmpty()) {
057                                                PaymentMeans paymentMeans = settlement.getPaymentMeans().get(0);
058
059                                                if (paymentMeans.getInformations() != null && !paymentMeans.getInformations().isEmpty()) {
060                                                        row.setComments(paymentMeans.getInformations().get(0));
061                                                }
062
063                                                Row.BankInformation bankInformation = new Row.BankInformation();
064                                                if (paymentMeans.getPayeeAccount() != null) {
065                                                        bankInformation.setIban(paymentMeans.getPayeeAccount().getIban());
066                                                }
067
068                                                if (paymentMeans.getPayeeInstitution() != null) {
069                                                        bankInformation.setBankName(paymentMeans.getPayeeInstitution().getName())
070                                                                        .setBic(paymentMeans.getPayeeInstitution().getBic());
071                                                }
072
073                                                row.getIssuer().setBankInfo(bankInformation);
074                                        }
075                                }
076
077                                List<Row.Item> items = Lists.transform(trade.getItems(), new Function<Item, Row.Item>() {
078                                        @Nullable
079                                        @Override
080                                        public Row.Item apply(@Nullable Item item) {
081                                                Row.Item rowItem = new Row.Item();
082                                                if (item != null) {
083                                                        rowItem.setName(item.getProduct() != null ? item.getProduct().getName() : "");
084
085                                                        SpecifiedDelivery delivery = item.getDelivery();
086                                                        if (delivery != null && delivery.getBilled() != null) {
087                                                                rowItem.setQuantity(delivery.getBilled().getValue())
088                                                                                .setUnit(delivery.getBilled().getUnit());
089                                                        }
090
091                                                        SpecifiedAgreement agreement = item.getAgreement();
092                                                        if (agreement != null && agreement.getNetPrice() != null) {
093                                                                rowItem.setUnitPrice(agreement.getNetPrice().getChargeAmount().getValue());
094                                                        }
095
096                                                        SpecifiedSettlement settlement = item.getSettlement();
097                                                        if (settlement != null && settlement.getTradeTax() != null && !settlement.getTradeTax().isEmpty()) {
098                                                                SpecifiedTax tradeTax = settlement.getTradeTax().get(0);
099
100                                                                rowItem.setTaxPercent(tradeTax.getPercentage());
101                                                        }
102                                                }
103                                                return rowItem;
104                                        }
105                                });
106
107                                row.setItems(items);
108                        }
109
110                        return row;
111                }
112
113                private static Row.TradeParty mapTradeParty(TradeParty tradeParty) {
114                        Row.TradeParty rowTradeParty = new Row.TradeParty();
115
116                        rowTradeParty.setName(tradeParty.getName());
117
118                        Address address = tradeParty.getAddress();
119                        if (Objects.nonNull(address)) {
120                                rowTradeParty.setAddressLine1(address.getLineOne())
121                                                .setAddressLine2(address.getLineTwo())
122                                                .setCity(address.getCity())
123                                                .setCountryCode(address.getCountry())
124                                                .setPostcode(address.getPostcode());
125                        }
126
127                        Contact contact = tradeParty.getContact();
128                        if (Objects.nonNull(contact)) {
129                                rowTradeParty.setContactName(contact.getName())
130                                                .setEmail(contact.getEmail());
131                        }
132
133                        List<TaxRegistration> taxRegistrations = tradeParty.getTaxRegistrations();
134                        if (Objects.nonNull(taxRegistrations) && !taxRegistrations.isEmpty()) {
135                                rowTradeParty.setTaxes(Lists.transform(taxRegistrations, new Function<TaxRegistration, Row.Tax>() {
136                                        @Nullable
137                                        @Override
138                                        public Row.Tax apply(TaxRegistration taxRegistration) {
139                                                Row.Tax tax = new Row.Tax();
140                                                if (Objects.nonNull(taxRegistration)) {
141                                                        tax.setNumber(taxRegistration.getTaxNumber())
142                                                                        .setType(taxRegistration.getType());
143                                                }
144                                                return tax;
145                                        }
146                                }));
147                        }
148
149                        return rowTradeParty;
150                }
151
152                private static Row.Header mapHeader(Invoice invoice) {
153                        Header header = invoice.getHeader();
154
155                        if (Objects.nonNull(header)) {
156                                CurrencyCode currencyCode = null;
157                                String paymentReference = null;
158                                String customerNumber = null;
159                                String noteText = null;
160
161                                Trade trade = invoice.getTrade();
162                                if (trade != null) {
163                                        Settlement settlement = trade.getSettlement();
164                                        Agreement agreement = trade.getAgreement();
165
166                                        if (settlement != null) {
167                                                currencyCode = settlement.getCurrency();
168                                                paymentReference = settlement.getPaymentReference();
169                                        }
170
171                                        if (agreement != null) {
172                                                TradeParty buyer = agreement.getBuyer();
173
174                                                if (buyer != null) {
175                                                        customerNumber = buyer.getId();
176                                                }
177                                        }
178                                }
179
180                                if (header.getNotes() != null && !header.getNotes().isEmpty()) {
181                                        Note note = header.getNotes().get(0);
182
183                                        if (note != null && note.getContents() != null && !note.getContents().isEmpty()) {
184                                                noteText = note.getContents().get(0);
185                                        }
186                                }
187
188                                Date issued = header.getIssued() != null ? new Date(header.getIssued().getTime()) : null;
189                                Date dueDate = header.getContractualDueDate() != null ? new Date(header.getContractualDueDate().getTime()) : null;
190
191                                return new Row.Header().setInvoiceNumber(header.getInvoiceNumber())
192                                                .setType(header.getName())
193                                                .setCurrency(currencyCode)
194                                                .setReference(paymentReference)
195                                                .setCustomerNumber(customerNumber)
196                                                .setIssued(issued)
197                                                .setDueDate(dueDate)
198                                                .setNote(noteText);
199                        }
200
201                        return new Row.Header();
202                }
203        }
204}