Browse Source

implemented deletion of positions

feature/document
Stephan Richter 4 months ago
parent
commit
97134694a2
  1. 27
      documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java
  2. 16
      frontend/src/routes/document/Position.svelte
  3. 30
      frontend/src/routes/document/PositionList.svelte

27
documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java

@ -63,14 +63,14 @@ public class DocumentApi extends BaseHandler {
var user = users.loadUser(token); var user = users.loadUser(token);
if (user.isEmpty()) return unauthorized(ex); if (user.isEmpty()) return unauthorized(ex);
var head = path.pop(); var head = path.pop();
return switch (head){ long docId = Long.parseLong(head);
default -> { return switch (path.pop()){
try { case POSITION -> deletePosition(ex,docId,user.get());
yield deleteDocument(ex,Long.parseLong(head),user.get()); case null -> deleteDocument(ex,docId,user.get());
} catch (NumberFormatException ignored) {} default -> super.doDelete(path,ex);
yield super.doDelete(path,ex);
}
}; };
} catch (NumberFormatException ignored) {
return super.doDelete(path,ex);
} catch (UmbrellaException e) { } catch (UmbrellaException e) {
return send(ex,e); return send(ex,e);
} }
@ -84,6 +84,17 @@ public class DocumentApi extends BaseHandler {
return sendContent(ex,db.deleteDoc(docId)); return sendContent(ex,db.deleteDoc(docId));
} }
private boolean deletePosition(HttpExchange ex, long docId, UmbrellaUser user) 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 new UmbrellaException(HTTP_BAD_REQUEST,"This document has already been sent");
var json = json(ex);
if (!(json.has(POSITION) && json.get(POSITION) instanceof Number number)) throw missingFieldException(POSITION);
db.dropPosition(docId,number.longValue());
return send(ex,db.loadDoc(docId).positions());
}
@Override @Override
public boolean doGet(Path path, HttpExchange ex) throws IOException { public boolean doGet(Path path, HttpExchange ex) throws IOException {
addCors(ex); addCors(ex);
@ -301,7 +312,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); var pos = new Position(doc.positions().size()+1,itemCode,amount.doubleValue(),unit,title,description,unitPrice.longValue(),tax,timeId,false);
doc.positions().add(pos); doc.positions().add(pos);
return sendContent(ex,db.save(doc).positions()); return send(ex,db.save(doc).positions());
} }
private boolean postTemplateList(HttpExchange ex, UmbrellaUser user) throws UmbrellaException, IOException { private boolean postTemplateList(HttpExchange ex, UmbrellaUser user) throws UmbrellaException, IOException {

16
frontend/src/routes/document/Position.svelte

@ -5,7 +5,7 @@
import LineEditor from '../../Components/LineEditor.svelte'; import LineEditor from '../../Components/LineEditor.svelte';
import MarkdownEditor from '../../Components/MarkdownEditor.svelte'; import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
import PriceEditor from '../../Components/PriceEditor.svelte'; import PriceEditor from '../../Components/PriceEditor.svelte';
var { currency, editable, pos = $bindable(null), submit = (key,newVal) => {}, movePos = (number,step) => {} } = $props(); var { currency, editable, pos = $bindable(null), submit = (key,newVal) => {}, movePos = (number,step) => {}, drop = (number) => {} } = $props();
let prefix = `pos.${pos.number}` let prefix = `pos.${pos.number}`
function moveup(){ function moveup(){
@ -21,14 +21,14 @@
.move{ .move{
vertical-align: middle; vertical-align: middle;
} }
tr > *:nth-child(1){
text-align: right;
}
</style> </style>
{#if pos} {#if pos}
<tr> <tr>
<td class="move">
{#if editable && pos.number>1}
<span onclick={moveup}>⏫</span>
{/if}
</td>
<td>{pos.number}</td> <td>{pos.number}</td>
<td class="item"> <td class="item">
<LineEditor bind:value={pos.item} editable={editable} onSet={(val) => submit(`${prefix}.item`,val)} /> <LineEditor bind:value={pos.item} editable={editable} onSet={(val) => submit(`${prefix}.item`,val)} />
@ -54,6 +54,10 @@
<tr> <tr>
<td class="move"> <td class="move">
{#if editable} {#if editable}
{#if pos.number>1}
<span onclick={moveup}>⏫</span>
{/if}
<span onclick={() => drop(pos.number)}>❌</span>
<span onclick={movedown}>⏬</span> <span onclick={movedown}>⏬</span>
{/if} {/if}
</td> </td>

30
frontend/src/routes/document/PositionList.svelte

@ -8,6 +8,13 @@
let editable = $derived(document.state == 1); let editable = $derived(document.state == 1);
async function updatePositions(resp){
let json = await resp.json();
document.positions = {};
setTimeout(() => document.positions = json,100)
error = null;
}
async function movePos(number,step){ async function movePos(number,step){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/${document.id}/position`; const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/${document.id}/position`;
const resp = await fetch(url,{ const resp = await fetch(url,{
@ -16,10 +23,21 @@
body:JSON.stringify({position:number,move:step}) body:JSON.stringify({position:number,move:step})
}); });
if (resp.ok){ if (resp.ok){
let json = await resp.json(); updatePositions(resp);
document.positions = {}; } else {
setTimeout(() => document.positions = json,10) error = await resp.text();
error = null; }
}
async function drop(number){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/${document.id}/position`;
const resp = await fetch(url,{
method: 'DELETE',
credentials:'include',
body:JSON.stringify({position:number})
});
if (resp.ok){
updatePositions(resp);
} else { } else {
error = await resp.text(); error = await resp.text();
} }
@ -30,7 +48,6 @@
<table class="positions"> <table class="positions">
<thead> <thead>
<tr> <tr>
<th></th>
<th>{t('document.pos')}</th> <th>{t('document.pos')}</th>
<th>{t('document.code')}</th> <th>{t('document.code')}</th>
<th>{t('document.title_or_desc')}</th> <th>{t('document.title_or_desc')}</th>
@ -43,10 +60,9 @@
</thead> </thead>
<tbody> <tbody>
{#each Object.entries(document.positions) as [id,pos]} {#each Object.entries(document.positions) as [id,pos]}
<Position currency={document.currency} bind:pos={document.positions[id]} editable={editable} {submit} {movePos} /> <Position currency={document.currency} bind:pos={document.positions[id]} editable={editable} {submit} {movePos} {drop} />
{/each} {/each}
<tr class="sums"> <tr class="sums">
<td></td>
<td colspan="2"></td> <td colspan="2"></td>
<td>{t('document.net_sum')}</td> <td>{t('document.net_sum')}</td>
<td>{document.net_sum/100}&nbsp;{document.currency}</td> <td>{document.net_sum/100}&nbsp;{document.currency}</td>

Loading…
Cancel
Save