From d68dc991d0316720df208509aade84a186477fd1 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Wed, 9 Jul 2025 23:49:01 +0200 Subject: [PATCH] workin on document creation: frontend work --- .../umbrella/documents/Constants.java | 3 +- .../umbrella/documents/DocumentApi.java | 25 +++- .../umbrella/documents/model/Document.java | 4 +- .../src/Components/ContactSelector.svelte | 37 +++++ frontend/src/Components/Menu.svelte | 1 - .../src/routes/document/AddDocument.svelte | 134 +++++++++++++++++- frontend/src/routes/document/List.svelte | 30 +++- .../src/routes/document/TypeSelector.svelte | 33 +++++ frontend/src/routes/search/Search.svelte | 2 - frontend/src/routes/user/ResetPw.svelte | 1 - translations/src/main/resources/de.json | 21 ++- 11 files changed, 271 insertions(+), 20 deletions(-) create mode 100644 frontend/src/Components/ContactSelector.svelte create mode 100644 frontend/src/routes/document/TypeSelector.svelte 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 23af47a..f5e0ee6 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java @@ -10,6 +10,7 @@ public class Constants { private Constants(){} public static final Pattern POST_CODE = compile("(.*\\w+.*)\n(.*\\d+.*)\n(\\d{5}) (\\w+)",DOTALL); + public static final String CONTACTS = "contacts"; public static final String CUSTOMER_NUMBER_PREFIX = "customer_number_prefix"; public static final String DECIMAL_SEPARATOR = "decimal_separator"; @@ -77,7 +78,6 @@ public class Constants { public static final String PATH_ADD_TIME = "add_time"; public static final String PATH_COMPANIES = "companies"; public static final String PATH_COMPANY = "company"; - public static final String PATH_CONTACTS = "contacts"; public static final String PATH_DOCUMENT = "document"; public static final String PATH_PDF = "pdf"; public static final String PATH_POSITIONS = "positions"; @@ -94,4 +94,5 @@ public class Constants { public static final String COMPANIES = "companies"; public static final String COMPANY = "company"; + public static final String CUSTOMERS = "customers"; } 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 5e258ff..89097d9 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java @@ -5,8 +5,7 @@ import static de.srsoftware.tools.MimeType.MIME_FORM_URL; import static de.srsoftware.umbrella.core.Constants.ERROR_MISSING_FIELD; import static de.srsoftware.umbrella.core.Paths.LIST; import static de.srsoftware.umbrella.core.Util.request; -import static de.srsoftware.umbrella.documents.Constants.COMPANIES; -import static de.srsoftware.umbrella.documents.Constants.COMPANY; +import static de.srsoftware.umbrella.documents.Constants.*; import static java.lang.System.Logger.Level.WARNING; import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; @@ -23,6 +22,10 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; + +import de.srsoftware.umbrella.documents.model.Type; +import org.json.JSONArray; import org.json.JSONObject; public class DocumentApi extends BaseHandler { @@ -47,6 +50,8 @@ public class DocumentApi extends BaseHandler { var head = path.pop(); return switch (head){ case COMPANIES -> getCompanies(ex,user.get(),token.orElse(null)); + case CONTACTS -> getContacts(ex,user.get(),token.orElse(null)); + case PATH_TYPES -> getDocTypes(ex); case null, default -> super.doGet(path,ex); }; } catch (UmbrellaException e) { @@ -75,6 +80,15 @@ public class DocumentApi extends BaseHandler { return sendContent(ex,getLegacyCompanies(ex,user,token)); } + private boolean getContacts(HttpExchange ex, UmbrellaUser user, Token token) throws IOException, UmbrellaException { + return sendContent(ex,getLegacyContacts(ex,user,token)); + } + + private boolean getDocTypes(HttpExchange ex) throws UmbrellaException, IOException { + var types = db.listTypes(); + var map = types.values().stream().collect(Collectors.toMap(Type::id, Type::name)); + return sendContent(ex,map); + } private HashMap> getLegacyCompanies(HttpExchange ex, UmbrellaUser umbrellaUser, Token token) throws IOException, UmbrellaException { var location = config.get("company.baseUrl").map(s -> s+"/json").orElseThrow(() -> new UmbrellaException(500,"umbrella.modules.company.baseUrl not configured!")); var resp = request(location, token.asMap(),MIME_FORM_URL,null); @@ -84,6 +98,13 @@ public class DocumentApi extends BaseHandler { return result; } + private JSONArray getLegacyContacts(HttpExchange ex, UmbrellaUser umbrellaUser, Token token) throws IOException, UmbrellaException { + var location = config.get("contact.baseUrl").map(s -> s+"/json").orElseThrow(() -> new UmbrellaException(500,"umbrella.modules.company.baseUrl not configured!")); + var resp = request(location, token.asMap(),MIME_FORM_URL,null); + if (!(resp instanceof String s && s.startsWith("["))) throw new UmbrellaException(500,"{0} did not return JSON Array!",location); + return new JSONArray(s); + } + private boolean listDocuments(HttpExchange ex, UmbrellaUser user, Token token) throws UmbrellaException { try { var json = json(ex); diff --git a/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java b/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java index f975231..f66cfad 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java @@ -264,8 +264,8 @@ public final class Document implements Mappable { return Map.of( ID, id, NUMBER, number, - "type", format("", type.name()), - STATE, Map.of(NAME,format("", state),ID,state.code), + "type", type.name(), + STATE, Map.of(NAME,state.toString(),ID,state.code), DATE, date, FIELD_CURRENCY, currency, FIELD_CUSTOMER, customer.toMap(), diff --git a/frontend/src/Components/ContactSelector.svelte b/frontend/src/Components/ContactSelector.svelte new file mode 100644 index 0000000..49fdf3d --- /dev/null +++ b/frontend/src/Components/ContactSelector.svelte @@ -0,0 +1,37 @@ + + +{#if contacts} + +{:else} +{message} +{/if} + diff --git a/frontend/src/Components/Menu.svelte b/frontend/src/Components/Menu.svelte index 95c5db8..ea73c0a 100644 --- a/frontend/src/Components/Menu.svelte +++ b/frontend/src/Components/Menu.svelte @@ -14,7 +14,6 @@ async function fetchModules(){ if (resp.ok){ const arr = await resp.json(); for (let entry of arr) modules.push({name:t('menu.'+entry.module),url:entry.url}); - console.log(modules); } else { console.log('error'); } diff --git a/frontend/src/routes/document/AddDocument.svelte b/frontend/src/routes/document/AddDocument.svelte index 7f3b273..1ec5231 100644 --- a/frontend/src/routes/document/AddDocument.svelte +++ b/frontend/src/routes/document/AddDocument.svelte @@ -1,13 +1,141 @@ + +
- {t('document.add_new')} - Company: {company_id} + {#if docType} + {t('document.add_new',docType)} + {/if} + {#if error} + {error} + {/if} + {#if company} + Company: {company.name} +
+ {t('document.customer')} + + + + + +
+ {/if} +
+ {t('document.sender')} + + + + +
+
\ No newline at end of file diff --git a/frontend/src/routes/document/List.svelte b/frontend/src/routes/document/List.svelte index cc85401..16e5895 100644 --- a/frontend/src/routes/document/List.svelte +++ b/frontend/src/routes/document/List.svelte @@ -2,18 +2,20 @@ import { useTinyRouter } from 'svelte-tiny-router'; import { onMount } from 'svelte'; import { t } from '../../translations.svelte.js'; + import TypeSelector from './TypeSelector.svelte'; let error = null; let companies = {}; let documents = null; let selected_company = null; let router = useTinyRouter(); + let docType = 0; + async function loadCompanies(){ const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/companies`; var resp = await fetch(url,{ credentials: 'include'}); if (resp.ok){ companies = await resp.json(); - console.log(companies); } else { error = await resp.text(); } @@ -29,18 +31,20 @@ }); if (resp.ok){ documents = await resp.json(); - console.log(documents); } else { error = await resp.text(); } + } + function createDoc(){ + router.navigate(`/document/add?company_id=${selected_company.id}&document_type=${docType}`) } onMount(loadCompanies);
- {name ? t( 'document.list_of',name) : t('document.list')} + {selected_company ? t( 'document.list_of',selected_company.name) : t('document.list')} {#if error}
{error}
{/if} @@ -51,19 +55,31 @@ {/each} {#if documents} - - + + + + + + + + + - {#each Object.entries(documents) as [id,document]} + {#each Object.entries(documents).reverse() as [id,document]} - + + {/each} diff --git a/frontend/src/routes/document/TypeSelector.svelte b/frontend/src/routes/document/TypeSelector.svelte new file mode 100644 index 0000000..d14513a --- /dev/null +++ b/frontend/src/routes/document/TypeSelector.svelte @@ -0,0 +1,33 @@ + + +{#if types} + +{:else} +{message} +{/if} + diff --git a/frontend/src/routes/search/Search.svelte b/frontend/src/routes/search/Search.svelte index 1bccced..834acc6 100644 --- a/frontend/src/routes/search/Search.svelte +++ b/frontend/src/routes/search/Search.svelte @@ -21,10 +21,8 @@ } onMount(() => { - console.log(location.search); let params = new URLSearchParams(location.search); key = params.get('key'); - console.log({param:key}); if (key) doSearch(); }); diff --git a/frontend/src/routes/user/ResetPw.svelte b/frontend/src/routes/user/ResetPw.svelte index da762fd..8c109ac 100644 --- a/frontend/src/routes/user/ResetPw.svelte +++ b/frontend/src/routes/user/ResetPw.svelte @@ -25,7 +25,6 @@ async function checkToken(){ const urlParams = new URLSearchParams(window.location.search); const token = urlParams.get('token'); - console.log({token:token,params:urlParams}); if (token) { const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/user/validate/${token}`; const resp = await fetch(url,{ diff --git a/translations/src/main/resources/de.json b/translations/src/main/resources/de.json index 04784e8..367af8c 100644 --- a/translations/src/main/resources/de.json +++ b/translations/src/main/resources/de.json @@ -1,8 +1,27 @@ { "document": { + "actions": "Aktionen", + "add_new": "{0} anlegen", + "create_new": "neues Dokument", + "customer": "Kunde", + "date": "Datum", + "gross_sum": "Brutto-Summe", "list": "Dokumente", "list_of": "Dokumente von {0}", - "select_company" : "Wählen Sie eine ihrer Firmen:" + "number": "Nummer", + "select_company" : "Wählen Sie eine ihrer Firmen:", + "select customer": "Kunde auswählen", + "sender": "Absender", + "state": "Status", + "state_declined": "abgelehnt", + "state_new":"neu", + "state_payed": "bezahlt", + "state_sent": "versendet", + "type": "Dokumententyp", + "type_confirmation": "Bestätigung", + "type_invoice": "Rechnung", + "type_offer": "Angebot", + "type_reminder": "Erinnerung" }, "footer": { "message" : "Umbrella ist ein Produkt von {0}."
{t('document.number')}{t('document.date')}{t('document.customer')}{t('document.gross_sum')}{t('document.type')}{t('document.state')} + {t('document.actions')} + {docType} + +
{id} {document.number} {document.date} {document.customer.name.split('\n')[0]} {document.sum/100 + document.currency}{t('document.type_'+document.type)}{t('document.state_'+document.state.name)}