001package io.konik.sdk.invoice;
002
003import com.google.api.client.http.HttpResponseException;
004import com.google.api.client.util.Maps;
005import io.konik.InvoiceTransformer;
006import io.konik.sdk.http.InsufficientCreditsAmountException;
007import io.konik.sdk.http.ZinvoiceHttpClient;
008import io.konik.zugferd.Invoice;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012import java.io.InputStream;
013import java.io.UnsupportedEncodingException;
014import java.net.URLEncoder;
015import java.nio.charset.Charset;
016import java.util.Map;
017
018
019public class RestInvoiceApi implements InvoiceApi {
020
021        private static final Logger log = LoggerFactory.getLogger(RestInvoiceApi.class);
022
023        private final ZinvoiceHttpClient httpClient;
024
025        private final InvoiceTransformer invoiceTransformer;
026
027        public RestInvoiceApi(ZinvoiceHttpClient zinvoiceHttpClient) {
028                this.httpClient = zinvoiceHttpClient;
029                this.invoiceTransformer = new InvoiceTransformer();
030        }
031
032        public RestInvoiceApi(ZinvoiceHttpClient zinvoiceHttpClient, InvoiceTransformer invoiceTransformer) {
033                this.httpClient = zinvoiceHttpClient;
034                this.invoiceTransformer = invoiceTransformer;
035        }
036
037        @Override
038        public InvoiceDocument getInvoice(String id) {
039                InvoiceDocument.Response response = httpClient.get("/invoice/" + id, InvoiceDocument.Response.class);
040                if (response != null) {
041                        return response.getDocument();
042                }
043                return null;
044        }
045
046        @Override
047        public InvoiceResponse createInvoice(Invoice invoice) {
048                byte[] invoiceXml = invoiceTransformer.fromModel(invoice);
049                return httpClient.post("/invoice", invoiceXml, "application/xml", InvoiceResponse.class);
050        }
051
052        @Override
053        public InvoiceResponse createDraftInvoice(Invoice invoice) {
054                byte[] invoiceXml = invoiceTransformer.fromModel(invoice);
055                return httpClient.post("/invoice/draft", invoiceXml, "application/xml", InvoiceResponse.class);
056        }
057
058        @Override
059        public InvoiceResponse updateInvoice(String invoiceId, Invoice invoice) {
060                byte[] invoiceXml = invoiceTransformer.fromModel(invoice);
061                return httpClient.put("/invoice/" + invoiceId, invoiceXml, "application/xml", InvoiceResponse.class);
062        }
063
064        @Override
065        public InvoiceResponse updateDraftInvoice(String invoiceId, Invoice invoice) {
066                byte[] invoiceXml = invoiceTransformer.fromModel(invoice);
067                return httpClient.put("/invoice/draft/" + invoiceId, invoiceXml, "application/xml", InvoiceResponse.class);
068        }
069
070        @Override
071        public InputStream downloadInvoiceAsPDF(String invoiceId) {
072                try {
073                        return httpClient.download("/invoice/" + invoiceId + "/pdf");
074                } catch (RuntimeException e) {
075                        if (e.getCause() instanceof HttpResponseException) {
076                                HttpResponseException responseException = (HttpResponseException) e.getCause();
077                                if (responseException.getStatusCode() == 409) {
078                                        throw new InsufficientCreditsAmountException();
079                                }
080                        }
081                        throw e;
082                }
083        }
084
085        @Override
086        public void deleteInvoice(String invoiceId) {
087                httpClient.delete("/invoice/"+invoiceId);
088        }
089
090        @Override
091        public boolean sendInvoice(String invoiceId, String email, String message) {
092                try {
093                        String encodedMessage = URLEncoder.encode(message, "UTF-8");
094                        String json = "{\"recipient\":\""+email+"\", \"message\":\""+encodedMessage+"\"}";
095
096                        InvoiceResponse createdInvoice = httpClient.post("/invoice/"+invoiceId+"/pdf/send", json.getBytes(Charset.forName("UTF-8")), "application/json", InvoiceResponse.class);
097
098                        return createdInvoice != null && createdInvoice.getInvoiceId() != null;
099                } catch (RuntimeException e) {
100                        if (e.getCause() instanceof HttpResponseException) {
101                                HttpResponseException responseException = (HttpResponseException) e.getCause();
102                                if (responseException.getStatusCode() == 409) {
103                                        throw new InsufficientCreditsAmountException();
104                                }
105                        }
106                        throw e;
107                } catch (UnsupportedEncodingException e) {
108                        throw new RuntimeException(e);
109                }
110        }
111
112        @Override
113        public boolean sendInvoice(String invoiceId, String email) {
114                return sendInvoice(invoiceId, email, "");
115        }
116
117        @Override
118        public InvoiceResponse uploadInvoice(InputStream pdf, InvoiceDocument.Type type) {
119                Map<String, InputStream> files = Maps.newHashMap();
120                files.put("pdf", pdf);
121                return httpClient.upload(String.format("/invoice/pdf?type=%s", type.toString()), files, InvoiceResponse.class);
122        }
123
124        @Override
125        public StatusResponse updateStatus(String invoiceId, Status status) {
126                try {
127                        String json = String.format("{\"status\": \"%s\"}", status.toString());
128                        String url = String.format("/invoice/%s/status", invoiceId);
129
130                        log.debug("Updating status of the invoice with id {}: {}", invoiceId, json);
131
132                        StatusResponse response = httpClient.post(url, json.getBytes("UTF-8"), "application/json", StatusResponse.class);
133
134                        log.debug("Change status response = {}", response);
135
136                        return response;
137                } catch (Exception e) {
138                        log.warn("Caught exception {}: {}", e.getClass().getSimpleName(), e.getMessage());
139                        throw new RuntimeException(e);
140                }
141        }
142}