From 31916d83df59fd20bab25a0d2f9013a53c62b8dd Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Tue, 15 Jul 2025 22:24:05 +0200 Subject: [PATCH] implemented adding positions to document Signed-off-by: Stephan Richter --- .../umbrella/documents/DocumentApi.java | 29 +++++++++++++++---- .../routes/document/PositionSelector.svelte | 15 +++++----- frontend/src/routes/document/View.svelte | 1 + translations/src/main/resources/de.json | 1 + 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java index 29b795d..a814f7f 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java @@ -14,6 +14,7 @@ import static de.srsoftware.umbrella.documents.model.Document.State.NEW; import static java.lang.System.Logger.Level.DEBUG; import static java.lang.System.Logger.Level.WARNING; import static java.net.HttpURLConnection.*; +import static java.util.stream.Collectors.toMap; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; @@ -30,6 +31,7 @@ import de.srsoftware.umbrella.documents.model.*; import java.io.IOException; import java.time.LocalDate; import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -165,7 +167,7 @@ public class DocumentApi extends BaseHandler { } private boolean getDocStates(HttpExchange ex) throws IOException { - var map = Stream.of(Document.State.values()).collect(Collectors.toMap(Document.State::code, Document.State::name)); + var map = Stream.of(Document.State.values()).collect(toMap(Document.State::code, Document.State::name)); return sendContent(ex,map); } @@ -173,7 +175,7 @@ public class DocumentApi extends BaseHandler { private boolean getDocTypes(HttpExchange ex) throws UmbrellaException, IOException { var types = db.listTypes(); - var map = types.values().stream().collect(Collectors.toMap(Type::id, Type::name)); + var map = types.values().stream().collect(toMap(Type::id, Type::name)); return sendContent(ex,map); } @@ -255,8 +257,25 @@ public class DocumentApi extends BaseHandler { return sendContent(ex,saved.toMap()); } - private boolean postDocumentPosition(long docId, HttpExchange ex, UmbrellaUser user) throws IOException { - return notImplemented(ex,"postDocumentPosition",this); + private boolean postDocumentPosition(long docId, HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { + var doc = db.loadDoc(docId); + 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); + if (!(json.has(FIELD_AMOUNT) && json.get(FIELD_AMOUNT) instanceof Number amount)) throw missingFieldException(FIELD_AMOUNT); + if (!(json.has(DESCRIPTION) && json.get(DESCRIPTION) instanceof String description)) throw missingFieldException(DESCRIPTION); + if (!(json.has(FIELD_ITEM_CODE) && json.get(FIELD_ITEM_CODE) instanceof String itemCode)) throw missingFieldException(FIELD_ITEM_CODE); + if (!(json.has(TITLE) && json.get(TITLE) instanceof String title)) throw missingFieldException(TITLE); + if (!(json.has(FIELD_UNIT) && json.get(FIELD_UNIT) instanceof String unit)) throw missingFieldException(FIELD_UNIT); + var unitPrice =json.has(FIELD_UNIT_PRICE) && json.get(FIELD_UNIT_PRICE) instanceof Number num ? num : 0L; + int tax = json.has(FIELD_TAX) && json.get(FIELD_TAX) instanceof Number t ? t.intValue() : 19; // TODO should not be hard-coded + Long timeId = json.has(FIELD_TIME_ID) && json.get(FIELD_TIME_ID) instanceof Number t ? t.longValue() : null; + var pos = new Position(doc.positions().size()+1,itemCode,amount.doubleValue(),unit,title,description,unitPrice.longValue(),tax,timeId,false); + doc.positions().add(pos); + + return sendContent(ex,db.save(doc).positions().entrySet().stream().collect(toMap(Map.Entry::getKey,entry -> entry.getValue().renderToMap()))); } private boolean postTemplateList(HttpExchange ex, UmbrellaUser user) throws UmbrellaException, IOException { @@ -269,7 +288,7 @@ public class DocumentApi extends BaseHandler { } - private boolean postToDocument(HttpExchange ex, Path path, UmbrellaUser user, long docId) throws IOException { + private boolean postToDocument(HttpExchange ex, Path path, UmbrellaUser user, long docId) throws IOException, UmbrellaException { var head = path.pop(); return switch (head){ case POSITION -> postDocumentPosition(docId,ex,user); diff --git a/frontend/src/routes/document/PositionSelector.svelte b/frontend/src/routes/document/PositionSelector.svelte index 2848529..6d25ff4 100644 --- a/frontend/src/routes/document/PositionSelector.svelte +++ b/frontend/src/routes/document/PositionSelector.svelte @@ -15,18 +15,18 @@ function estimateSelected(estimate){ select({ - code:t('estimated_time'), - subject:estimate.name, + item_code:t('estimated_time'), + title:estimate.name, description:estimate.description.source, amount:estimate.estimated_time, - unit:doc.currency+"/h" + unit:t('document.hours') }); } function itemSelected(item){ select({ - code:item.code, - subject:item.name, + item_code:item.code, + title:item.name, description:item.description.source, amount:1, unit:item.unit, @@ -37,11 +37,12 @@ function timeSelected(time){ select({ - code:t('document.timetrack'), + item_code:t('document.timetrack'), title:time.subject, description:time.description.source, amount:time.duration, - unit:doc.currency+"/h" + unit:t('document.hours'), + time_id:time.id }); } diff --git a/frontend/src/routes/document/View.svelte b/frontend/src/routes/document/View.svelte index f73156e..0ad7ba8 100644 --- a/frontend/src/routes/document/View.svelte +++ b/frontend/src/routes/document/View.svelte @@ -71,6 +71,7 @@ body:JSON.stringify(selected) }); if (resp.ok){ + doc.positions = await resp.json(); } else { error = await resp.text(); } diff --git a/translations/src/main/resources/de.json b/translations/src/main/resources/de.json index 1d5dea1..8e3a83d 100644 --- a/translations/src/main/resources/de.json +++ b/translations/src/main/resources/de.json @@ -23,6 +23,7 @@ "footer": "Fuß-Text", "gross_sum": "Brutto-Summe", "head": "Kopf-Text", + "hours": "Stunden", "items": "Artikel", "list": "Dokumente", "list_of": "Dokumente von {0}",