preparing to render document
This commit is contained in:
17
core/src/main/java/de/srsoftware/umbrella/core/Tuple.java
Normal file
17
core/src/main/java/de/srsoftware/umbrella/core/Tuple.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package de.srsoftware.umbrella.core;
|
||||||
|
|
||||||
|
import de.srsoftware.umbrella.core.model.Company;
|
||||||
|
|
||||||
|
public class Tuple<A,B>{
|
||||||
|
public final A a;
|
||||||
|
public final B b;
|
||||||
|
|
||||||
|
public Tuple(A a, B b){
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <A, B> Tuple<A,B> of(A a, B b) {
|
||||||
|
return new Tuple<>(a,b);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,5 +3,11 @@ description = "Umbrella : Documents"
|
|||||||
dependencies{
|
dependencies{
|
||||||
implementation(project(":company"))
|
implementation(project(":company"))
|
||||||
implementation(project(":core"))
|
implementation(project(":core"))
|
||||||
|
|
||||||
|
implementation("de.srsoftware:document.api:1.0.1")
|
||||||
|
implementation("de.srsoftware:document.file:1.0.0")
|
||||||
|
implementation("de.srsoftware:document.processor:1.0.2")
|
||||||
|
implementation("de.srsoftware:document.zugferd:1.0.3")
|
||||||
|
|
||||||
implementation("de.srsoftware:tools.mime:1.1.2")
|
implementation("de.srsoftware:tools.mime:1.1.2")
|
||||||
}
|
}
|
||||||
@@ -19,10 +19,12 @@ import static java.util.stream.Collectors.toMap;
|
|||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import de.srsoftware.configuration.Configuration;
|
import de.srsoftware.configuration.Configuration;
|
||||||
|
import de.srsoftware.document.api.DocumentRegistry;
|
||||||
import de.srsoftware.tools.Pair;
|
import de.srsoftware.tools.Pair;
|
||||||
import de.srsoftware.tools.Path;
|
import de.srsoftware.tools.Path;
|
||||||
import de.srsoftware.tools.SessionToken;
|
import de.srsoftware.tools.SessionToken;
|
||||||
import de.srsoftware.umbrella.core.BaseHandler;
|
import de.srsoftware.umbrella.core.BaseHandler;
|
||||||
|
import de.srsoftware.umbrella.core.Tuple;
|
||||||
import de.srsoftware.umbrella.core.api.CompanyService;
|
import de.srsoftware.umbrella.core.api.CompanyService;
|
||||||
import de.srsoftware.umbrella.core.api.UserService;
|
import de.srsoftware.umbrella.core.api.UserService;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
@@ -35,12 +37,14 @@ import java.time.LocalDate;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class DocumentApi extends BaseHandler {
|
public class DocumentApi extends BaseHandler {
|
||||||
|
private static final Predicate<de.srsoftware.document.api.Document> ZUGFERD_FILTER = document -> document.id().equals("Zugferd");
|
||||||
|
private final DocumentRegistry registry = new DocumentRegistry();
|
||||||
|
|
||||||
private final CompanyService companies;
|
private final CompanyService companies;
|
||||||
private final Configuration config;
|
private final Configuration config;
|
||||||
@@ -110,18 +114,25 @@ public class DocumentApi extends BaseHandler {
|
|||||||
case STATES -> getDocStates(ex);
|
case STATES -> getDocStates(ex);
|
||||||
case null -> super.doGet(path,ex);
|
case null -> super.doGet(path,ex);
|
||||||
default -> {
|
default -> {
|
||||||
try {
|
var docId = Long.parseLong(head);
|
||||||
var docId = Long.parseLong(head);
|
head = path.pop();
|
||||||
yield getDocument(ex,docId,user.get());
|
yield switch (head){
|
||||||
} catch (NumberFormatException ignored) {}
|
case null -> getDocument(ex,docId,user.get());
|
||||||
yield super.doGet(path,ex);
|
case PATH_PDF -> getRenderedDocument(ex,docId,user.get());
|
||||||
|
default -> super.doGet(path,ex);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
return super.doGet(path,ex);
|
||||||
} catch (UmbrellaException e) {
|
} catch (UmbrellaException e) {
|
||||||
return send(ex,e);
|
return send(ex,e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean doOptions(Path path, HttpExchange ex) throws IOException {
|
public boolean doOptions(Path path, HttpExchange ex) throws IOException {
|
||||||
return sendEmptyResponse(HTTP_OK,addCors(ex));
|
return sendEmptyResponse(HTTP_OK,addCors(ex));
|
||||||
@@ -197,18 +208,46 @@ public class DocumentApi extends BaseHandler {
|
|||||||
return sendContent(ex,map);
|
return sendContent(ex,map);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean getDocument(HttpExchange ex, long docId, UmbrellaUser user) throws IOException, UmbrellaException {
|
private Tuple<Document,Company> getDocument(long docId, UmbrellaUser user) throws UmbrellaException {
|
||||||
var doc = db.loadDoc(docId);
|
var doc = db.loadDoc(docId);
|
||||||
var companyId = doc.companyId();
|
var companyId = doc.companyId();
|
||||||
var company = companies.get(companyId);
|
var company = companies.get(companyId);
|
||||||
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
|
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
|
||||||
|
return Tuple.of(doc,company);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Document getDocumentWithCompanyData(long docId, UmbrellaUser user) throws UmbrellaException {
|
||||||
|
var tuple = getDocument(docId,user);
|
||||||
|
|
||||||
|
var company = tuple.b;
|
||||||
var sep = company.decimalSeparator();
|
var sep = company.decimalSeparator();
|
||||||
|
|
||||||
|
var doc = tuple.a;
|
||||||
if (sep != null) doc.setDecimalSeparator(sep);
|
if (sep != null) doc.setDecimalSeparator(sep);
|
||||||
doc.setCompanyName(company.name());
|
doc.setCompanyName(company.name());
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getDocument(HttpExchange ex, long docId, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||||
|
var doc = getDocumentWithCompanyData(docId,user);
|
||||||
return sendContent(ex,doc.renderToMap());
|
return sendContent(ex,doc.renderToMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean getRenderedDocument(HttpExchange ex, long docId, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||||
|
var document = getDocumentWithCompanyData(docId,user);
|
||||||
|
var template = document.template().name();
|
||||||
|
var templateName = template+".html.pdf";
|
||||||
|
var type = document.type().name();
|
||||||
|
var zugferd = "invoice".equals(type);
|
||||||
|
Predicate<de.srsoftware.document.api.Document> filter = zugferd ? ZUGFERD_FILTER : doc -> doc.name().equals(templateName);
|
||||||
|
var optDoc = registry.documents()
|
||||||
|
.filter(filter)
|
||||||
|
.findAny();
|
||||||
|
if (optDoc.isEmpty()) throw new UmbrellaException(404,"Cannot render {0} {1}: Missing template \"{2}\"",type,document.number(),template);
|
||||||
|
|
||||||
|
return sendContent(ex,document.renderToMap());
|
||||||
|
}
|
||||||
|
|
||||||
private JSONArray getLegacyContacts(HttpExchange ex, UmbrellaUser umbrellaUser, Token token) throws IOException, UmbrellaException {
|
private JSONArray getLegacyContacts(HttpExchange ex, UmbrellaUser umbrellaUser, Token token) throws IOException, UmbrellaException {
|
||||||
var location = config.get("umbrella.modules.contact.baseUrl").map(s -> s+"/json").orElseThrow(() -> new UmbrellaException(500,"umbrella.modules.contact.baseUrl not configured!"));
|
var location = config.get("umbrella.modules.contact.baseUrl").map(s -> s+"/json").orElseThrow(() -> new UmbrellaException(500,"umbrella.modules.contact.baseUrl not configured!"));
|
||||||
var resp = request(location, token.asMap(),MIME_FORM_URL,null);
|
var resp = request(location, token.asMap(),MIME_FORM_URL,null);
|
||||||
@@ -234,9 +273,7 @@ public class DocumentApi extends BaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean patchDocument(long docId, UmbrellaUser user, HttpExchange ex) throws UmbrellaException, IOException {
|
private boolean patchDocument(long docId, UmbrellaUser user, HttpExchange ex) throws UmbrellaException, IOException {
|
||||||
var doc = db.loadDoc(docId);
|
var doc = getDocument(docId,user).a;
|
||||||
var companyId = doc.companyId();
|
|
||||||
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",doc.companyId());
|
|
||||||
doc.patch(json(ex));
|
doc.patch(json(ex));
|
||||||
db.save(doc);
|
db.save(doc);
|
||||||
return ok(ex);
|
return ok(ex);
|
||||||
@@ -247,9 +284,7 @@ public class DocumentApi extends BaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean patchDocumentPosition(long docId, UmbrellaUser user, HttpExchange ex) throws UmbrellaException, IOException {
|
private boolean patchDocumentPosition(long docId, UmbrellaUser user, HttpExchange ex) throws UmbrellaException, IOException {
|
||||||
var doc = db.loadDoc(docId);
|
var doc = getDocument(docId,user).a;
|
||||||
var companyId = doc.companyId();
|
|
||||||
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",doc.companyId());
|
|
||||||
if (doc.state() != NEW) throw forbidden("Document has already been send and is write-protected!");
|
if (doc.state() != NEW) throw forbidden("Document has already been send and is write-protected!");
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
var step = json.has(MOVE) && json.get(MOVE) instanceof Number num ? num.intValue() : 0;
|
var step = json.has(MOVE) && json.get(MOVE) instanceof Number num ? num.intValue() : 0;
|
||||||
@@ -295,10 +330,7 @@ public class DocumentApi extends BaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean postDocumentPosition(long docId, HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
|
private boolean postDocumentPosition(long docId, HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||||
var doc = db.loadDoc(docId);
|
var doc = getDocument(docId,user).a;
|
||||||
var companyId = doc.companyId();
|
|
||||||
var company = companies.get(companyId);
|
|
||||||
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
|
|
||||||
|
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
if (!(json.has(FIELD_AMOUNT) && json.get(FIELD_AMOUNT) instanceof Number amount)) throw missingFieldException(FIELD_AMOUNT);
|
if (!(json.has(FIELD_AMOUNT) && json.get(FIELD_AMOUNT) instanceof Number amount)) throw missingFieldException(FIELD_AMOUNT);
|
||||||
|
|||||||
@@ -79,6 +79,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function render(){
|
||||||
|
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/${doc.id}/pdf`;
|
||||||
|
const resp = fetch(url,{credentials:'include'});
|
||||||
|
if (resp.ok){
|
||||||
|
error = null;
|
||||||
|
} else {
|
||||||
|
error = await resp.text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMount(loadDoc);
|
onMount(loadDoc);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -199,6 +209,7 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{t('document.actions')}</legend>
|
<legend>{t('document.actions')}</legend>
|
||||||
|
<button onclick={render}>{t('document.create_pdf')}</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>TODO</legend>
|
<legend>TODO</legend>
|
||||||
|
|||||||
Reference in New Issue
Block a user