From 5d10ff33c911a7e1de01555a91c27c9dc4ab4d5b Mon Sep 17 00:00:00 2001 From: elgekko Date: Mon, 24 Apr 2023 17:08:09 +0200 Subject: [PATCH] Added Associate model, invoice fileupload, changes by feedback --- TODO.txt | 21 +++ lis-app/pom.xml | 4 +- .../main/java/hu/user/lis/db/Associate.java | 15 ++ .../main/java/hu/user/lis/db/Currency.java | 2 +- .../src/main/java/hu/user/lis/db/Invoice.java | 2 + .../lis/services/data/AssociateService.java | 23 +++ .../services/data/AssociateServiceImpl.java | 105 ++++++++++++++ .../lis/services/data/InvoiceService.java | 7 +- .../lis/services/data/InvoiceServiceImpl.java | 44 ++++-- .../lis/services/data/PartnerServiceImpl.java | 41 ++++-- .../lis/services/data/ProjectService.java | 7 +- .../lis/services/data/ProjectServiceImpl.java | 35 +++-- .../main/java/hu/user/lis/ui/Constants.java | 9 ++ .../converter/ByteArrayToAMediaConverter.java | 24 ++++ .../java/hu/user/lis/ui/event/EventBus.java | 41 ++++++ .../hu/user/lis/ui/view/AsyncBaseModel.java | 4 - .../hu/user/lis/ui/view/IndexViewModel.java | 55 +++++++- .../user/lis/ui/view/InvoiceEditorModel.java | 66 +++++---- .../user/lis/ui/view/PartnersViewModel.java | 13 +- .../user/lis/ui/view/ProjectEditorModel.java | 86 +++++++++--- .../user/lis/ui/view/ProjectsViewModel.java | 92 ++++++------ .../resources/web/incoming-invoice-editor.zul | 118 ++++++++++++++++ lis-ui/src/main/resources/web/index.zul | 46 +++--- ...nvoice.zul => outgoing-invoice-editor.zul} | 22 ++- .../web/{partner.zul => partner-editor.zul} | 0 .../src/main/resources/web/project-editor.zul | 132 ++++++++++++++++++ lis-ui/src/main/resources/web/project.zul | 6 +- lis-ui/src/main/resources/web/projects.zul | 6 +- pom.xml | 7 +- 29 files changed, 847 insertions(+), 186 deletions(-) create mode 100644 TODO.txt create mode 100644 lis-db/src/main/java/hu/user/lis/db/Associate.java create mode 100644 lis-services/src/main/java/hu/user/lis/services/data/AssociateService.java create mode 100644 lis-services/src/main/java/hu/user/lis/services/data/AssociateServiceImpl.java create mode 100644 lis-ui/src/main/java/hu/user/lis/ui/Constants.java create mode 100644 lis-ui/src/main/java/hu/user/lis/ui/converter/ByteArrayToAMediaConverter.java create mode 100644 lis-ui/src/main/java/hu/user/lis/ui/event/EventBus.java create mode 100644 lis-ui/src/main/resources/web/incoming-invoice-editor.zul rename lis-ui/src/main/resources/web/{invoice.zul => outgoing-invoice-editor.zul} (80%) rename lis-ui/src/main/resources/web/{partner.zul => partner-editor.zul} (100%) create mode 100644 lis-ui/src/main/resources/web/project-editor.zul diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..00757be --- /dev/null +++ b/TODO.txt @@ -0,0 +1,21 @@ +* Projektek táblázat oszlopok sorrendje: Azonosító, Partner (inkább ügyfél), Név (inkább megnevezés), Kapcsolattartó. Értelemszerűen a projekt részletezésben s ügyfél és megnevezés legyen. +* A projekt részletek képernyőn össze lehetne csukni a be és a kimenő számla táblázatokat? +* Számla táblázatban oszlopok: + Bejövő számlák: Szállító (ez most a partner), megnevezés (ez most a leírás), nettó összeg, Pénznem (ez most nincs), Fizetési határidő nem kell. + Kimenő számlák: Vevő (ez most a partner), megnevezés (ez most a leírás), nettó összeg, pénznem (ez most nincs), fizetési határidő nem kell. +* a be és kimenő számlák felviteli képernyőjén be lehessen állítani, hogy ez egy tervezett számla-e. +* számlakép feltöltés/törlés: pdf csatolás +-a dátumformátum: 2023. 04. 23. Nincs hónapnév és értelemszerűen nincs idő sem. +-Összegek: két tizedesre igazítva, magyar számformátum: pl: 100,23 1.543.234,00 2800,05 +-Tervezett szamla esetén a határidők nem ismertek, nem kötelező; áfa deviza esetén nem ismert, nem kötelező +-munkatárs lista és szerkesztő: név, óradíj? +-munkatárs hozzárendelése a projekthez (vagy fordítva) +-munkalap: külön lista xy hány órát (mindenki önköltség) dolgozott melyik projekten + + +- authentikáció: hitelesítés-AD és helyi +- authorizáció: sap s3 autorazition objects leírás!!! -pl. számla: szla szám + művelet : megjelenítésnél elérhető e? +- munkalap rögzítés úgy, hogy raktáron lévő alkatrészt is fel lehessen vinni a munkalapra. +- Kell keresnünk egy nevet a rendszernek, mert szerintem a Leader Information System nem helyes angolul: SLY-CRM +- plugin: gondolnunk kell arra, hogy minden ügyfélnél lehet egyedi testreszabási igény, de ennek valahogy el kell teljesen különülnie a "core" forráskódtól. Pl. javascript motort be lehetne építeni, a szkriptek pedig meghatározott pontokon lehetnének becsatolva a logikába. számla részletezés volt a példa (10000EUR számla 3 részletben forintban, kérdés mennyi pl. az utsó számla összege); 10 custom mező, javascripttel futna a custom mezők módosítására + diff --git a/lis-app/pom.xml b/lis-app/pom.xml index e270057..fe740f3 100644 --- a/lis-app/pom.xml +++ b/lis-app/pom.xml @@ -1,10 +1,10 @@ - 4.0.0 hu.user lis-app - 0.0.4-SNAPSHOT + 0.0.5-SNAPSHOT hu.user lis diff --git a/lis-db/src/main/java/hu/user/lis/db/Associate.java b/lis-db/src/main/java/hu/user/lis/db/Associate.java new file mode 100644 index 0000000..a7b66e8 --- /dev/null +++ b/lis-db/src/main/java/hu/user/lis/db/Associate.java @@ -0,0 +1,15 @@ +package hu.user.lis.db; + +import lombok.*; + +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class Associate { + String id; + String name; + double hourlyRate; + boolean active; +} diff --git a/lis-db/src/main/java/hu/user/lis/db/Currency.java b/lis-db/src/main/java/hu/user/lis/db/Currency.java index 33ff0e3..1b30c93 100644 --- a/lis-db/src/main/java/hu/user/lis/db/Currency.java +++ b/lis-db/src/main/java/hu/user/lis/db/Currency.java @@ -5,7 +5,7 @@ import lombok.Getter; @Getter public enum Currency { - HUF(0), USD(1), EURO(2); + HUF(0), USD(1), EUR(2); final int val; Currency(int val) { diff --git a/lis-db/src/main/java/hu/user/lis/db/Invoice.java b/lis-db/src/main/java/hu/user/lis/db/Invoice.java index 8bf00e1..ba9f723 100644 --- a/lis-db/src/main/java/hu/user/lis/db/Invoice.java +++ b/lis-db/src/main/java/hu/user/lis/db/Invoice.java @@ -22,4 +22,6 @@ public class Invoice { Date completionDate; Date createDate; Date paymentDeadline; + boolean planned; + byte[] file; } diff --git a/lis-services/src/main/java/hu/user/lis/services/data/AssociateService.java b/lis-services/src/main/java/hu/user/lis/services/data/AssociateService.java new file mode 100644 index 0000000..8c82603 --- /dev/null +++ b/lis-services/src/main/java/hu/user/lis/services/data/AssociateService.java @@ -0,0 +1,23 @@ +package hu.user.lis.services.data; + +import hu.user.lis.db.Associate; + +import java.util.List; + +public interface AssociateService { + List getAll(); + + Associate createNew(); + + void add(Associate entity); + + Associate getRandom(); + + Associate copy(Associate sourceEntity); + + void replace(Associate targetEntity, Associate replacementEntity); + + String toString(Associate sourceEntity); + + Associate copy(Associate sourceEntity, String property, Object value); +} diff --git a/lis-services/src/main/java/hu/user/lis/services/data/AssociateServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/AssociateServiceImpl.java new file mode 100644 index 0000000..e112dcd --- /dev/null +++ b/lis-services/src/main/java/hu/user/lis/services/data/AssociateServiceImpl.java @@ -0,0 +1,105 @@ +package hu.user.lis.services.data; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import hu.user.lis.db.Associate; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.RandomUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +@Service +@Log4j2 +public class AssociateServiceImpl implements AssociateService { + @Autowired + ObjectMapper mapper; + @Autowired + DataGeneratorService dataGeneratorService; + private List entities; + + @Override + public List getAll() { + if (entities == null) { + entities = generate(); + } + return entities; + } + + @Override + public Associate createNew() { + String id = RandomStringUtils.random(8, "0123456789abcdef"); + return Associate.builder().id(id).active(true).build(); + } + + @Override + public void add(Associate entity) { + entities.add(entity); + } + + @Override + public void replace(Associate targetEntity, Associate replacementEntity) { + Associate listEntity = entities.stream().filter(p -> p.getId().equals(targetEntity.getId())).findFirst().get(); + entities.remove(listEntity); + entities.add(replacementEntity); + } + + @Override + public Associate getRandom() { + return getAll().get(RandomUtils.nextInt(0, entities.size())); + } + + private List generate() { + List result = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + String id = RandomStringUtils.random(8, "0123456789abcdef"); + String name = dataGeneratorService.faker().name().fullName(); + + Associate entity = Associate.builder().active(true).id(id).name(name).build(); + result.add(entity); + } + return result; + } + + @Override + public Associate copy(Associate sourceEntity) { + Associate result = null; + try { + String json = toString(sourceEntity); + result = mapper.readValue(json, Associate.class); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; + } + + @Override + public String toString(Associate sourceEntity) { + String result = null; + try { + result = mapper.writeValueAsString(sourceEntity); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; + } + + @Override + public Associate copy(Associate sourceEntity, String property, Object value) { + Associate result = copy(sourceEntity); + Field field = null; + try { + field = result.getClass().getDeclaredField(property); + field.setAccessible(true); + field.set(result, value); + } catch (Exception e) { + log.catching(e); + } + return result; + } + +} diff --git a/lis-services/src/main/java/hu/user/lis/services/data/InvoiceService.java b/lis-services/src/main/java/hu/user/lis/services/data/InvoiceService.java index a51a571..973b79e 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/InvoiceService.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/InvoiceService.java @@ -1,6 +1,5 @@ package hu.user.lis.services.data; -import com.fasterxml.jackson.core.JsonProcessingException; import hu.user.lis.db.Invoice; import java.util.List; @@ -12,11 +11,11 @@ public interface InvoiceService { void add(Invoice entity); - Invoice copy(Invoice sourceEntity) throws JsonProcessingException; + Invoice copy(Invoice sourceEntity); - String toString(Invoice sourceEntity) throws JsonProcessingException; + String toString(Invoice sourceEntity); - Invoice copy(Invoice sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException; + Invoice copy(Invoice sourceEntity, String property, Object value); void replace(Invoice targetEntity, Invoice replacementEntity); diff --git a/lis-services/src/main/java/hu/user/lis/services/data/InvoiceServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/InvoiceServiceImpl.java index e2c18c0..3681638 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/InvoiceServiceImpl.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/InvoiceServiceImpl.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import hu.user.lis.db.Currency; import hu.user.lis.db.Invoice; import hu.user.lis.db.Partner; +import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -20,16 +21,17 @@ import java.util.List; import java.util.concurrent.TimeUnit; @Service +@Log4j2 public class InvoiceServiceImpl implements InvoiceService { int GENERATE_COUNT = 1000; - private List incomingEntities; - private List outgoingEntities; @Autowired DataGeneratorService dataGeneratorService; @Autowired PartnerService partnerService; @Autowired ObjectMapper mapper; + private List incomingEntities; + private List outgoingEntities; @Override public List getAll() { @@ -55,7 +57,7 @@ public class InvoiceServiceImpl implements InvoiceService { @Override public Invoice createNew() { String id = RandomStringUtils.random(8, "0123456789abcdef"); - return Invoice.builder().id(id).build(); + return Invoice.builder().id(id).planned(true).build(); } @Override @@ -119,22 +121,40 @@ public class InvoiceServiceImpl implements InvoiceService { } @Override - public Invoice copy(Invoice sourceEntity) throws JsonProcessingException { - String json = toString(sourceEntity); - return mapper.readValue(json, Invoice.class); + public Invoice copy(Invoice sourceEntity) { + Invoice result = null; + try { + String json = toString(sourceEntity); + result = mapper.readValue(json, Invoice.class); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; } @Override - public String toString(Invoice sourceEntity) throws JsonProcessingException { - return mapper.writeValueAsString(sourceEntity); + public String toString(Invoice sourceEntity) { + String result = null; + try { + result = mapper.writeValueAsString(sourceEntity); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; } @Override - public Invoice copy(Invoice sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException { + public Invoice copy(Invoice sourceEntity, String property, Object value) { Invoice result = copy(sourceEntity); - Field field = result.getClass().getDeclaredField(property); - field.setAccessible(true); - field.set(result, value); + Field field = null; + try { + field = result.getClass().getDeclaredField(property); + field.setAccessible(true); + field.set(result, value); + } catch (Exception e) { + log.catching(e); + } return result; } + } diff --git a/lis-services/src/main/java/hu/user/lis/services/data/PartnerServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/PartnerServiceImpl.java index ea4ac67..adfba1c 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/PartnerServiceImpl.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/PartnerServiceImpl.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.javafaker.Address; import hu.user.lis.db.Partner; +import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -14,13 +15,13 @@ import java.util.ArrayList; import java.util.List; @Service +@Log4j2 public class PartnerServiceImpl implements PartnerService { - private List entities; - @Autowired ObjectMapper mapper; @Autowired DataGeneratorService dataGeneratorService; + private List entities; @Override public List getAll() { @@ -72,22 +73,40 @@ public class PartnerServiceImpl implements PartnerService { } @Override - public Partner copy(Partner sourceEntity) throws JsonProcessingException { - String json = toString(sourceEntity); - return mapper.readValue(json, Partner.class); + public Partner copy(Partner sourceEntity) { + Partner result = null; + try { + String json = toString(sourceEntity); + result = mapper.readValue(json, Partner.class); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; } @Override - public String toString(Partner sourceEntity) throws JsonProcessingException { - return mapper.writeValueAsString(sourceEntity); + public String toString(Partner sourceEntity) { + String result = null; + try { + result = mapper.writeValueAsString(sourceEntity); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; } @Override - public Partner copy(Partner sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException { + public Partner copy(Partner sourceEntity, String property, Object value) { Partner result = copy(sourceEntity); - Field field = result.getClass().getDeclaredField(property); - field.setAccessible(true); - field.set(result, value); + Field field = null; + try { + field = result.getClass().getDeclaredField(property); + field.setAccessible(true); + field.set(result, value); + } catch (Exception e) { + log.catching(e); + } return result; } + } diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ProjectService.java b/lis-services/src/main/java/hu/user/lis/services/data/ProjectService.java index 5f5b5ac..d5f1e64 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/ProjectService.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/ProjectService.java @@ -1,6 +1,5 @@ package hu.user.lis.services.data; -import com.fasterxml.jackson.core.JsonProcessingException; import hu.user.lis.db.Project; import java.util.List; @@ -12,13 +11,13 @@ public interface ProjectService { void add(Project entity); - Project copy(Project sourceEntity) throws JsonProcessingException; + Project copy(Project sourceEntity); void replace(Project targetEntity, Project replacementEntity); boolean isInvalid(Project entity); - String toString(Project sourceEntity) throws JsonProcessingException; + String toString(Project sourceEntity); - Project copy(Project sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException; + Project copy(Project sourceEntity, String property, Object value); } diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java index 41b6f41..b450774 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java @@ -100,22 +100,39 @@ public class ProjectServiceImpl implements ProjectService { } @Override - public Project copy(Project sourceEntity) throws JsonProcessingException { - String json = toString(sourceEntity); - return mapper.readValue(json, Project.class); + public Project copy(Project sourceEntity) { + Project result = null; + try { + String json = toString(sourceEntity); + result = mapper.readValue(json, Project.class); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; } @Override - public String toString(Project sourceEntity) throws JsonProcessingException { - return mapper.writeValueAsString(sourceEntity); + public String toString(Project sourceEntity) { + String result = null; + try { + result = mapper.writeValueAsString(sourceEntity); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; } @Override - public Project copy(Project sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException { + public Project copy(Project sourceEntity, String property, Object value) { Project result = copy(sourceEntity); - Field field = result.getClass().getDeclaredField(property); - field.setAccessible(true); - field.set(result, value); + Field field = null; + try { + field = result.getClass().getDeclaredField(property); + field.setAccessible(true); + field.set(result, value); + } catch (Exception e) { + log.catching(e); + } return result; } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/Constants.java b/lis-ui/src/main/java/hu/user/lis/ui/Constants.java new file mode 100644 index 0000000..4294b18 --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/Constants.java @@ -0,0 +1,9 @@ +package hu.user.lis.ui; + +public class Constants { + public static final String SHOW_PROJECT_EDITOR = "SHOW_PROJECT_EDITOR"; + public static final String SHOW_PROJECTS_LIST = "SHOW_PROJECTS_LIST"; + public static final String SET_PROJECT_EDITOR_DATA = "SET_PROJECT_EDITOR_DATA"; + public static final String SET_PROJECTS_LIST_DATA = "SET_PROJECTS_LIST_DATA"; + public static final String PROJECT_EDITOR_QUEUE = "PROJECT_EDITOR_QUEUE"; +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/converter/ByteArrayToAMediaConverter.java b/lis-ui/src/main/java/hu/user/lis/ui/converter/ByteArrayToAMediaConverter.java new file mode 100644 index 0000000..9d600c9 --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/converter/ByteArrayToAMediaConverter.java @@ -0,0 +1,24 @@ +package hu.user.lis.ui.converter; + +import org.zkoss.bind.BindContext; +import org.zkoss.bind.Converter; +import org.zkoss.util.media.AMedia; +import org.zkoss.zul.Iframe; + +import java.util.Objects; + +public class ByteArrayToAMediaConverter implements Converter { + + @Override + public AMedia coerceToUi(byte[] data, Iframe iframe, BindContext bindContext) { + if (Objects.isNull(data)) { + return null; + } + return new AMedia("Számlakép", "pdf", "application/pdf", data); + } + + @Override + public byte[] coerceToBean(AMedia media, Iframe iframe, BindContext bindContext) { + return null; + } +} \ No newline at end of file diff --git a/lis-ui/src/main/java/hu/user/lis/ui/event/EventBus.java b/lis-ui/src/main/java/hu/user/lis/ui/event/EventBus.java new file mode 100644 index 0000000..52b22d2 --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/event/EventBus.java @@ -0,0 +1,41 @@ +package hu.user.lis.ui.event; + +import hu.user.lis.ui.Constants; +import org.springframework.stereotype.Service; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.EventQueue; +import org.zkoss.zk.ui.event.EventQueues; + +@Service +public class EventBus { + private EventQueue queue; + + public EventBus() { + queue = EventQueues.lookup(Constants.PROJECT_EDITOR_QUEUE, EventQueues.APPLICATION, true); + } + + public void register(EventListener listener) { + queue.subscribe(listener); + } + + public void unregister(EventListener listener) { + queue.unsubscribe(listener); + } + + public void showProjectsList(Object data) { + queue.publish(new Event(Constants.SHOW_PROJECTS_LIST, null, data)); + } + + public void showProjectEditor(Object data) { + queue.publish(new Event(Constants.SHOW_PROJECT_EDITOR, null, data)); + } + + public void setProjectEditorData(Object data) { + queue.publish(new Event(Constants.SET_PROJECT_EDITOR_DATA, null, data)); + } + + public void setProjectsListData(Object data) { + queue.publish(new Event(Constants.SET_PROJECTS_LIST_DATA, null, data)); + } +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/AsyncBaseModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/AsyncBaseModel.java index 051ea26..5dd5696 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/AsyncBaseModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/AsyncBaseModel.java @@ -1,7 +1,5 @@ package hu.user.lis.ui.view; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.zkoss.bind.BindUtils; import org.zkoss.bind.annotation.Command; @@ -10,7 +8,6 @@ import java.util.Arrays; import java.util.List; public class AsyncBaseModel { - private static final Logger logger = LogManager.getLogger(); private List uiTasks = new ArrayList<>(); protected void doKeepAlive() { @@ -39,5 +36,4 @@ public class AsyncBaseModel { uiTasks.clear(); } } - } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/IndexViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/IndexViewModel.java index a981068..35b3686 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/IndexViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/IndexViewModel.java @@ -1,38 +1,81 @@ package hu.user.lis.ui.view; +import com.google.common.collect.ImmutableMap; +import hu.user.lis.ui.Constants; +import hu.user.lis.ui.event.EventBus; import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; import org.springframework.boot.info.BuildProperties; +import org.zkoss.bind.BindUtils; +import org.zkoss.bind.annotation.BindingParam; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.Destroy; import org.zkoss.bind.annotation.Init; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.Event; -import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.select.annotation.VariableResolver; import org.zkoss.zk.ui.select.annotation.WireVariable; import javax.servlet.http.HttpServletRequest; +import java.util.Map; @Log4j2 @VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class) @Getter @Setter -public class IndexViewModel { +public class IndexViewModel implements EventListener { + public static final String PROJECT_EDITOR_PAGE = "~./project-editor.zul"; + private static final String PARTNERS_LIST = "~./partners.zul"; + private static final String PROJECTS_LIST = "~./projects.zul"; @WireVariable BuildProperties buildProperties; + @WireVariable + EventBus eventBus; String searchPhrase; - int selectedPage; - + String page; + private Map navigation = ImmutableMap.of( + "/projects", PROJECTS_LIST + ); @Init public void init() { HttpServletRequest nativeRequest = (HttpServletRequest) Executions.getCurrent().getNativeRequest(); String path = (String) Executions.getCurrent().getAttribute("javax.servlet.forward.servlet_path"); - if ("/projects".equals(path)) { - Events.postEvent(new Event("onFulFillProjectsTab")); + if (navigation.containsKey(path)) { + setPage(navigation.get(path)); + } else { + setPage(PARTNERS_LIST); } + eventBus.register(this); log.info("Init {}", path); } + @Command + public void selectPage(@BindingParam("page") String page) { + setPage(page); + BindUtils.postNotifyChange(this, "page"); + } + + @Override + public void onEvent(Event event) { + if (Constants.SHOW_PROJECT_EDITOR.equals(event.getName())) { + selectPage(PROJECT_EDITOR_PAGE); + eventBus.setProjectEditorData(event.getData()); + } + if (Constants.SHOW_PROJECTS_LIST.equals(event.getName())) { + selectPage(PROJECTS_LIST); + if (event.getData() != null) { + eventBus.setProjectsListData(event.getData()); + } + } + } + + @Destroy + public void onDestroy() { + log.info("Destroy {}"); + eventBus.unregister(this); + } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/InvoiceEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/InvoiceEditorModel.java index c98ce12..5d54d10 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/InvoiceEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/InvoiceEditorModel.java @@ -15,10 +15,7 @@ import org.zkoss.bind.annotation.*; import org.zkoss.bind.validator.AbstractValidator; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.event.Event; -import org.zkoss.zk.ui.event.Events; -import org.zkoss.zk.ui.event.InputEvent; -import org.zkoss.zk.ui.event.OpenEvent; +import org.zkoss.zk.ui.event.*; import org.zkoss.zk.ui.select.annotation.VariableResolver; import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zkplus.spring.DelegatingVariableResolver; @@ -86,37 +83,56 @@ public class InvoiceEditorModel extends AbstractValidator { String property = ctx.getProperty().getProperty(); Object value = ctx.getProperty().getValue(); log.info("Validating caused by {} {} {}", target.getId(), property, value); - updateFormInvalid(false); try { Invoice newData = invoiceServiceImpl.copy(formDocument, property, value); - if (!Objects.isNull(origDocument) && invoiceServiceImpl.toString(origDocument).equals(invoiceServiceImpl.toString(newData))) { - log.info("Document not changed"); - updateFormInvalid(true); - return; - } - - if (newData.getNetAmount() <= 0 || - newData.getGrossAmount() <= 0 || - newData.getVatAmount() <= 0 || - StringUtils.isBlank(newData.getTitle()) || - Objects.isNull(newData.getPartner()) || - Objects.isNull(newData.getCompletionDate()) || - Objects.isNull(newData.getCreateDate()) || - Objects.isNull(newData.getPaymentDeadline()) || - newData.getCreateDate().after(newData.getCompletionDate()) || - newData.getCompletionDate().after(newData.getPaymentDeadline()) - ) { - log.info("Document is not valid"); - updateFormInvalid(true); - } + validate(newData); } catch (Exception e) { log.catching(e); } } + private void validate(Invoice newData) { + updateFormInvalid(false); + if (!Objects.isNull(origDocument) && invoiceServiceImpl.toString(origDocument).equals(invoiceServiceImpl.toString(newData))) { + log.info("Document not changed"); + updateFormInvalid(true); + return; + } + + if (newData.getNetAmount() <= 0 || + newData.getGrossAmount() <= 0 || + newData.getVatAmount() <= 0 || + StringUtils.isBlank(newData.getTitle()) || + Objects.isNull(newData.getPartner()) || + Objects.isNull(newData.getCompletionDate()) || + Objects.isNull(newData.getCreateDate()) || + Objects.isNull(newData.getPaymentDeadline()) || + newData.getCreateDate().after(newData.getCompletionDate()) || + newData.getCompletionDate().after(newData.getPaymentDeadline()) + ) { + log.info("Document is not valid"); + updateFormInvalid(true); + } + } + private void updateFormInvalid(boolean invalid) { setFormInvalid(invalid); BindUtils.postNotifyChange(this, "formInvalid"); } + + @Command + public void onUploadFile(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { + UploadEvent evt = (UploadEvent) ctx.getTriggerEvent(); + formDocument.setFile(evt.getMedia().getByteData()); + BindUtils.postNotifyChange(this.formDocument, "file"); + validate(invoiceServiceImpl.copy(formDocument)); + } + + @Command + public void onRemoveFile() { + formDocument.setFile(null); + BindUtils.postNotifyChange(this.formDocument, "file"); + validate(invoiceServiceImpl.copy(formDocument)); + } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/PartnersViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/PartnersViewModel.java index 347ae0e..0ad8556 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/PartnersViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/PartnersViewModel.java @@ -24,18 +24,17 @@ import java.util.Set; @Log4j2 @VariableResolver(DelegatingVariableResolver.class) public class PartnersViewModel extends AsyncBaseModel { - @Getter - private Partner selectedPartner; @WireVariable @Getter PartnersDataModel partnersDataModel; + @Wire + Listbox partnersList; + @Getter + private Partner selectedPartner; private boolean filterShowInActive; private boolean filterShowActive; private boolean filterShowBoth; - @Wire - Listbox partnersList; - @AfterCompose public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) { Selectors.wireComponents(view, this, false); @@ -80,7 +79,7 @@ public class PartnersViewModel extends AsyncBaseModel { @Command public void onAdd() { - String page = "~./partner.zul"; + String page = "~./partner-editor.zul"; Partner newEntity = partnersDataModel.getPartnerService().createNew(); Window editorWindow = (Window) Executions.createComponents(page, null, Collections.singletonMap("formDocument", newEntity)); @@ -108,7 +107,7 @@ public class PartnersViewModel extends AsyncBaseModel { @Command public void onEdit() throws JsonProcessingException { - String page = "~./partner.zul"; + String page = "~./partner-editor.zul"; Partner editEntity = partnersDataModel.getPartnerService().copy(selectedPartner); Map arg = new HashMap<>(); arg.put("origDocument", selectedPartner); diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectEditorModel.java index ffa02f1..d303f7c 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectEditorModel.java @@ -1,11 +1,14 @@ package hu.user.lis.ui.view; import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.collect.ImmutableMap; import hu.user.lis.db.Invoice; import hu.user.lis.db.Project; import hu.user.lis.services.data.InvoiceService; import hu.user.lis.services.data.ProjectService; +import hu.user.lis.ui.Constants; import hu.user.lis.ui.data.PartnerSelectorDataModel; +import hu.user.lis.ui.event.EventBus; import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; @@ -18,12 +21,14 @@ import org.zkoss.bind.validator.AbstractValidator; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.Event; -import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.InputEvent; import org.zkoss.zk.ui.event.OpenEvent; import org.zkoss.zk.ui.select.annotation.VariableResolver; import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zkplus.spring.DelegatingVariableResolver; +import org.zkoss.zul.Center; +import org.zkoss.zul.Panel; import org.zkoss.zul.Window; import java.util.*; @@ -32,7 +37,7 @@ import java.util.*; @Getter @Setter @VariableResolver(DelegatingVariableResolver.class) -public class ProjectEditorModel extends AbstractValidator { +public class ProjectEditorModel extends AbstractValidator implements EventListener { private Project formDocument; private Project origDocument; @WireVariable @@ -41,25 +46,37 @@ public class ProjectEditorModel extends AbstractValidator { private InvoiceService invoiceServiceImpl; @WireVariable private ProjectService projectServiceImpl; + @WireVariable + private EventBus eventBus; private boolean formInvalid = true; private Invoice selectedIncomingInvoice; private Invoice selectedOutgoingInvoice; + public ProjectEditorModel() { + + } + @Init public void init() { + eventBus.register(this); log.info("Initialized"); - origDocument = (Project) Executions.getCurrent().getArg().get("origDocument"); - formDocument = (Project) Executions.getCurrent().getArg().get("formDocument"); - partnerSelectorDataModel.clearSelection(); } + @Command - public void onCloseWindow(@BindingParam("target") Window target, @BindingParam("select") boolean select) { + public void onEndEdit(@BindingParam("target") Window target, @BindingParam("select") boolean select) { if (select && formInvalid) { return; } - Event closeEvent = new Event("onClose", target, select ? formDocument : null); - Events.postEvent(closeEvent); + Map args = null; + if (select) { + if (Objects.isNull(origDocument)) { + args = ImmutableMap.of("formDocument", formDocument); + } else { + args = ImmutableMap.of("origDocument", origDocument, "formDocument", formDocument); + } + } + eventBus.showProjectsList(args); } @Command @@ -106,7 +123,7 @@ public class ProjectEditorModel extends AbstractValidator { } } - private void validate(Project newData) throws JsonProcessingException { + private void validate(Project newData) { updateFormInvalid(false); if (!Objects.isNull(origDocument) && projectServiceImpl.toString(origDocument).equals(projectServiceImpl.toString(newData))) { log.info("Document not changed"); @@ -125,7 +142,7 @@ public class ProjectEditorModel extends AbstractValidator { @Command public void onAddIncoming() { - String page = "~./invoice.zul"; + String page = "~./incoming-invoice-editor.zul"; Invoice editEntity = invoiceServiceImpl.createNew(); editEntity.setIncome(true); Window editorWindow = (Window) Executions.createComponents(page, null, @@ -136,8 +153,7 @@ public class ProjectEditorModel extends AbstractValidator { selectedIncomingInvoice = editEntity; BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); - Project newData = projectServiceImpl.copy(formDocument); - validate(newData); + validate(projectServiceImpl.copy(formDocument)); } }); editorWindow.doModal(); @@ -145,7 +161,7 @@ public class ProjectEditorModel extends AbstractValidator { @Command public void onEditIncoming() throws JsonProcessingException { - String page = "~./invoice.zul"; + String page = "~./incoming-invoice-editor.zul"; Invoice editEntity = invoiceServiceImpl.copy(selectedIncomingInvoice); Map arg = new HashMap<>(); arg.put("origDocument", selectedIncomingInvoice); @@ -161,8 +177,7 @@ public class ProjectEditorModel extends AbstractValidator { selectedIncomingInvoice = modifiedEntity; BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); - Project newData = projectServiceImpl.copy(formDocument); - validate(newData); + validate(projectServiceImpl.copy(formDocument)); } }); editorWindow.doModal(); @@ -177,11 +192,12 @@ public class ProjectEditorModel extends AbstractValidator { selectedIncomingInvoice = null; BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); + validate(projectServiceImpl.copy(formDocument)); } @Command public void onAddOutgoing() { - String page = "~./invoice.zul"; + String page = "~./outgoing-invoice-editor.zul"; Invoice editEntity = invoiceServiceImpl.createNew(); Window editorWindow = (Window) Executions.createComponents(page, null, Collections.singletonMap("formDocument", editEntity)); @@ -191,8 +207,7 @@ public class ProjectEditorModel extends AbstractValidator { selectedOutgoingInvoice = editEntity; BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); - Project newData = projectServiceImpl.copy(formDocument); - validate(newData); + validate(projectServiceImpl.copy(formDocument)); } }); editorWindow.doModal(); @@ -200,7 +215,7 @@ public class ProjectEditorModel extends AbstractValidator { @Command public void onEditOutgoing() throws JsonProcessingException { - String page = "~./invoice.zul"; + String page = "~./outgoing-invoice-editor.zul"; Invoice editEntity = invoiceServiceImpl.copy(selectedOutgoingInvoice); Map arg = new HashMap<>(); arg.put("origDocument", selectedOutgoingInvoice); @@ -216,8 +231,7 @@ public class ProjectEditorModel extends AbstractValidator { selectedOutgoingInvoice = modifiedEntity; BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); - Project newData = projectServiceImpl.copy(formDocument); - validate(newData); + validate(projectServiceImpl.copy(formDocument)); } }); editorWindow.doModal(); @@ -232,10 +246,40 @@ public class ProjectEditorModel extends AbstractValidator { selectedOutgoingInvoice = null; BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); + validate(projectServiceImpl.copy(formDocument)); } private void updateFormInvalid(boolean invalid) { setFormInvalid(invalid); BindUtils.postNotifyChange(this, "formInvalid"); } + + @Override + public void onEvent(Event evt) { + if (Constants.SET_PROJECT_EDITOR_DATA.equals(evt.getName())) { + Map data = (Map) evt.getData(); + origDocument = (Project) data.get("origDocument"); + formDocument = (Project) data.get("formDocument"); + BindUtils.postNotifyChange(this, "formDocument"); + } + } + + @Destroy + public void onDestroy() { + log.info("Destroy {}"); + eventBus.unregister(this); + } + + @Command + public void onOpenInvoicePanel(@BindingParam("parentPanel") Center parentPanel) { + log.info("Invoice panel open/close"); + parentPanel.invalidate(); + } + + @Command + public void onClickInvoicePanel(@BindingParam("parentPanel") Center parentPanel, @BindingParam("panel") Panel panel) { + log.info("Invoice panel click"); + panel.setOpen(!panel.isOpen()); + parentPanel.invalidate(); + } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java index ba355e3..6c27919 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java @@ -1,32 +1,35 @@ package hu.user.lis.ui.view; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.collect.ImmutableMap; import hu.user.lis.db.Project; +import hu.user.lis.ui.Constants; import hu.user.lis.ui.data.ProjectsDataModel; +import hu.user.lis.ui.event.EventBus; import lombok.Getter; import lombok.extern.log4j.Log4j2; import org.zkoss.bind.annotation.*; import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.select.Selectors; import org.zkoss.zk.ui.select.annotation.VariableResolver; import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zkplus.spring.DelegatingVariableResolver; -import org.zkoss.zul.Window; -import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.Set; + @Log4j2 @VariableResolver(DelegatingVariableResolver.class) -public class ProjectsViewModel extends AsyncBaseModel { - @Getter - private Project selectedProject; +public class ProjectsViewModel extends AsyncBaseModel implements EventListener { @WireVariable @Getter ProjectsDataModel projectsDataModel; + @WireVariable + EventBus eventBus; + @Getter + private Project selectedProject; private boolean filterShowInActive; private boolean filterShowActive; private boolean filterShowBoth; @@ -39,8 +42,9 @@ public class ProjectsViewModel extends AsyncBaseModel { @Init public void init() { - log.info("Initialized"); setFilterShowActive(true); + eventBus.register(this); + log.info("Initialized"); } private void refresh() { @@ -73,53 +77,15 @@ public class ProjectsViewModel extends AsyncBaseModel { public void onAdd() { String page = "~./project.zul"; Project newEntity = projectsDataModel.getProjectService().createNew(); - Window partnerWindow = (Window) Executions.createComponents(page, null, - Collections.singletonMap("formDocument", newEntity)); - partnerWindow.addEventListener("onClose", e -> { - if (e.getData() != null) { - log.info("Partner popup result {}", e.getData()); - projectsDataModel.getProjectService().add(newEntity); - projectsDataModel.clearSelection(); - refresh(); - projectsDataModel.addToSelection(newEntity); - selectedProject = newEntity; -// Optional listItem = partnersList.getItems().stream() -// .filter(li -> ((Partner) li.getValue()).getId().equals(editPartner.getId())) -// .findFirst(); -// if (listItem.isPresent()) { -// Clients.scrollIntoView(listItem.get()); -// } -// registerTask(() -> { -// }); - } - }); - partnerWindow.doModal(); + eventBus.showProjectEditor(ImmutableMap.of("formDocument", newEntity)); } @Command - public void onEdit() throws JsonProcessingException { - String page = "~./project.zul"; + public void onEdit() { Project editEntity = projectsDataModel.getProjectService().copy(selectedProject); - Map arg = new HashMap<>(); - arg.put("origDocument", selectedProject); - arg.put("formDocument", editEntity); - - Window partnerWindow = (Window) Executions.createComponents(page, null, arg); - partnerWindow.addEventListener("onClose", e -> { - if (e.getData() != null) { - log.info("Project popup result {}", e.getData()); - Project modifiedEntity = (Project) e.getData(); - projectsDataModel.clearSelection(); - projectsDataModel.getProjectService().replace(selectedProject, modifiedEntity); - refresh(); - projectsDataModel.addToSelection(modifiedEntity); - selectedProject = modifiedEntity; - } - }); - partnerWindow.doModal(); + eventBus.showProjectEditor(ImmutableMap.of("origDocument", selectedProject, "formDocument", editEntity)); } - public boolean isFilterShowInActive() { return filterShowInActive; } @@ -155,4 +121,30 @@ public class ProjectsViewModel extends AsyncBaseModel { this.filterShowBoth = filterShowBoth; refresh(); } + + @Override + public void onEvent(Event event) { + if (Constants.SET_PROJECTS_LIST_DATA.equals(event.getName())) { + log.info("Apply Project edit result"); + projectsDataModel.clearSelection(); + Map args = (Map) event.getData(); + Project formDocument = args.get("formDocument"); + if (args.containsKey("origDocument")) { + Project origDocument = args.get("origDocument"); + projectsDataModel.getProjectService().replace(origDocument, formDocument); + } else { + projectsDataModel.getProjectService().add(formDocument); + } + refresh(); + projectsDataModel.addToSelection(formDocument); + selectedProject = formDocument; + } + } + + @Destroy + public void onDestroy() { + log.info("Destroy {}"); + eventBus.unregister(this); + } + } diff --git a/lis-ui/src/main/resources/web/incoming-invoice-editor.zul b/lis-ui/src/main/resources/web/incoming-invoice-editor.zul new file mode 100644 index 0000000..7a66daa --- /dev/null +++ b/lis-ui/src/main/resources/web/incoming-invoice-editor.zul @@ -0,0 +1,118 @@ + + + + + + import hu.user.lis.db.Currency; + ListModelList currencies = new ListModelList(Currency.values()); + + + +
+ + + + + + + + + + + + + + + + + + +
+