diff --git a/documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java b/documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java index a1cfe7b..43ce91f 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java @@ -68,6 +68,7 @@ public class Constants { public static final String FIELD_TYPE_SUFFIX = "type_suffix"; public static final String FIELD_UNIT = "unit"; public static final String FIELD_UNIT_PRICE = "unit_price"; + public static final String MOVE = "move"; public static final String PATH_ADD_ITEM = "add_item"; public static final String PATH_ADD_TASK = "add_task"; 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 a814f7f..b54b300 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java @@ -2,6 +2,7 @@ package de.srsoftware.umbrella.documents; import static de.srsoftware.tools.MimeType.MIME_FORM_URL; +import static de.srsoftware.tools.Optionals.isSet; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Paths.LIST; @@ -18,6 +19,7 @@ import static java.util.stream.Collectors.toMap; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; +import de.srsoftware.tools.Pair; import de.srsoftware.tools.Path; import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; @@ -123,7 +125,12 @@ public class DocumentApi extends BaseHandler { if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); var docId = Long.parseLong(head); - return patchDocument(docId,user.get(),ex); + head = path.pop(); + return switch (head){ + case POSITION -> patchDocumentPosition(docId,user.get(),ex); + case null -> patchDocument(docId,user.get(),ex); + default -> super.doPatch(path,ex); + }; } catch (NumberFormatException n){ return sendContent(ex,HTTP_UNPROCESSABLE,"Invalid document id"); } catch (UmbrellaException e) { @@ -219,16 +226,35 @@ public class DocumentApi extends BaseHandler { var doc = db.loadDoc(docId); var companyId = doc.companyId(); if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",doc.companyId()); - var json = json(ex); - for (var key : json.keySet()){ - var value = json.get(key); - LOG.log(WARNING,"{0} : {1}",key,value); - } - doc.patch(json); + doc.patch(json(ex)); db.save(doc); return ok(ex); } + private boolean send(HttpExchange ex,PositionList positions) throws IOException { + return sendContent(ex,positions.entrySet().stream().collect(toMap(Map.Entry::getKey,entry -> entry.getValue().renderToMap()))); + } + + private boolean patchDocumentPosition(long docId, UmbrellaUser user, HttpExchange ex) throws UmbrellaException, IOException { + var doc = db.loadDoc(docId); + 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!"); + var json = json(ex); + var step = json.has(MOVE) && json.get(MOVE) instanceof Number num ? num.intValue() : 0; + Integer number = json.has(POSITION) && json.get(POSITION) instanceof Number num ? num.intValue() : null; + if (isSet(number) && step != 0) { + var pos2 = number+step; + if (number >0 && pos2>0 && number <=doc.positions().size() && pos2<=doc.positions().size()){ + db.switchPositions(docId,new Pair<>(number,pos2)); + doc = db.loadDoc(docId); + } + } + + return send(ex,db.save(doc).positions()); + } + + private boolean postDocument(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { var json = json(ex); if (!(json.has(SENDER) && json.get(SENDER) instanceof JSONObject senderData)) throw missingFieldException(SENDER); @@ -254,7 +280,7 @@ public class DocumentApi extends BaseHandler { var doc = new Document(0,companyId.longValue(),nextNumber,type, LocalDate.now(), NEW,template,null,lastHead,lastFooter,currency,sep,sender,customer,new PositionList()); var saved = db.save(doc); db.step(companySettings); - return sendContent(ex,saved.toMap()); + return sendContent(ex,saved); } private boolean postDocumentPosition(long docId, HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { @@ -275,7 +301,7 @@ public class DocumentApi extends BaseHandler { 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()))); + return sendContent(ex,db.save(doc).positions()); } private boolean postTemplateList(HttpExchange ex, UmbrellaUser user) throws UmbrellaException, IOException { diff --git a/frontend/src/routes/document/Position.svelte b/frontend/src/routes/document/Position.svelte index bfe4808..3827493 100644 --- a/frontend/src/routes/document/Position.svelte +++ b/frontend/src/routes/document/Position.svelte @@ -5,11 +5,30 @@ import LineEditor from '../../Components/LineEditor.svelte'; import MarkdownEditor from '../../Components/MarkdownEditor.svelte'; import PriceEditor from '../../Components/PriceEditor.svelte'; - var { currency, editable, pos = $bindable(null), submit = (key,newVal) => {} } = $props(); + var { currency, editable, pos = $bindable(null), submit = (key,newVal) => {}, movePos = (number,step) => {} } = $props(); let prefix = `pos.${pos.number}` + + function moveup(){ + movePos(pos.number,-1); + } + + function movedown(){ + movePos(pos.number,1); + } + + {#if pos}
| {t('document.pos')} | {t('document.code')} | {t('document.title_or_desc')} | @@ -25,9 +43,10 @@||
|---|---|---|---|---|
| {t('document.net_sum')} | {document.net_sum/100} {document.currency} | diff --git a/frontend/src/routes/document/View.svelte b/frontend/src/routes/document/View.svelte index 0ad7ba8..bdb9ad3 100644 --- a/frontend/src/routes/document/View.svelte +++ b/frontend/src/routes/document/View.svelte @@ -22,6 +22,7 @@ const resp = await fetch(url,{credentials:'include'}); if (resp.ok){ doc = await resp.json(); + error = null; } else { error = await resp.text(); } @@ -72,6 +73,7 @@ }); if (resp.ok){ doc.positions = await resp.json(); + error = null; } else { error = await resp.text(); } @@ -189,7 +191,7 @@ {/if} -|||