From 7ba25557ffff6e66c4958d56196cd90dbaa6b88f Mon Sep 17 00:00:00 2001 From: elgekko Date: Fri, 21 Apr 2023 16:11:26 +0200 Subject: [PATCH] Validator bug fixed and improved --- lis-app/pom.xml | 2 +- .../main/java/hu/user/lis/db/Currency.java | 13 +- .../src/main/java/hu/user/lis/db/Invoice.java | 8 +- .../src/main/java/hu/user/lis/db/Project.java | 5 + lis-services/pom.xml | 4 - .../lis/services/data/InvoiceService.java | 6 + .../lis/services/data/InvoiceServiceImpl.java | 113 ++++++++++-- .../lis/services/data/PartnerService.java | 4 + .../lis/services/data/PartnerServiceImpl.java | 28 ++- .../lis/services/data/ProjectService.java | 4 +- .../lis/services/data/ProjectServiceImpl.java | 46 +++-- .../ui/{ => config}/ResourceConfigurer.java | 7 +- .../lis/ui/data/PartnerSelectorDataModel.java | 3 + .../hu/user/lis/ui/view/IndexViewModel.java | 21 ++- .../user/lis/ui/view/InvoiceEditorModel.java | 122 +++++++++++++ .../user/lis/ui/view/PartnerEditorModel.java | 32 +++- .../user/lis/ui/view/PartnersViewModel.java | 34 ++-- .../user/lis/ui/view/ProjectEditorModel.java | 166 ++++++++++++++++-- .../user/lis/ui/view/ProjectsViewModel.java | 20 ++- lis-ui/src/main/resources/web/index.zul | 5 +- lis-ui/src/main/resources/web/invoice.zul | 94 ++++++++++ .../main/resources/web/partner-selector.zul | 4 +- lis-ui/src/main/resources/web/partner.zul | 38 ++-- lis-ui/src/main/resources/web/partners.zul | 2 +- lis-ui/src/main/resources/web/project.zul | 138 ++++++++++++--- lis-ui/src/main/resources/web/projects.zul | 9 +- 26 files changed, 786 insertions(+), 142 deletions(-) rename lis-ui/src/main/java/hu/user/lis/ui/{ => config}/ResourceConfigurer.java (67%) create mode 100644 lis-ui/src/main/java/hu/user/lis/ui/view/InvoiceEditorModel.java create mode 100644 lis-ui/src/main/resources/web/invoice.zul diff --git a/lis-app/pom.xml b/lis-app/pom.xml index d6c5c54..e270057 100644 --- a/lis-app/pom.xml +++ b/lis-app/pom.xml @@ -4,7 +4,7 @@ 4.0.0 hu.user lis-app - 0.0.3-SNAPSHOT + 0.0.4-SNAPSHOT hu.user lis 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 ac32550..33ff0e3 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 @@ -1,5 +1,16 @@ package hu.user.lis.db; + +import lombok.Getter; + +@Getter public enum Currency { - HUF, USD, EURO + HUF(0), USD(1), EURO(2); + final int val; + + Currency(int val) { + this.val = 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 851c605..8bf00e1 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 @@ -2,7 +2,7 @@ package hu.user.lis.db; import lombok.*; -import java.time.LocalDate; +import java.util.Date; @Getter @Setter @@ -19,7 +19,7 @@ public class Invoice { double netAmount; double grossAmount; double vatAmount; - LocalDate completionDate; - LocalDate createDate; - LocalDate paymentDeadline; + Date completionDate; + Date createDate; + Date paymentDeadline; } diff --git a/lis-db/src/main/java/hu/user/lis/db/Project.java b/lis-db/src/main/java/hu/user/lis/db/Project.java index 42817d3..66e5bb6 100644 --- a/lis-db/src/main/java/hu/user/lis/db/Project.java +++ b/lis-db/src/main/java/hu/user/lis/db/Project.java @@ -2,6 +2,8 @@ package hu.user.lis.db; import lombok.*; +import java.util.List; + @Getter @Setter @Builder @@ -14,4 +16,7 @@ public class Project { String contactName; Partner partner; boolean active; + List incomingInvoices; + List outgoingInvoices; + } diff --git a/lis-services/pom.xml b/lis-services/pom.xml index da1d43b..cef056e 100644 --- a/lis-services/pom.xml +++ b/lis-services/pom.xml @@ -37,9 +37,5 @@ com.fasterxml.jackson.core jackson-databind - - com.fasterxml.jackson.core - jackson-databind - 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 06eff52..a51a571 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 @@ -14,5 +14,11 @@ public interface InvoiceService { Invoice copy(Invoice sourceEntity) throws JsonProcessingException; + String toString(Invoice sourceEntity) throws JsonProcessingException; + + Invoice copy(Invoice sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException; + void replace(Invoice targetEntity, Invoice replacementEntity); + + List getRandom(boolean income); } 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 b7eaa50..e2c18c0 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 @@ -2,29 +2,54 @@ package hu.user.lis.services.data; import com.fasterxml.jackson.core.JsonProcessingException; 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 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.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; import java.util.List; +import java.util.concurrent.TimeUnit; @Service public class InvoiceServiceImpl implements InvoiceService { - private List entities; + int GENERATE_COUNT = 1000; + private List incomingEntities; + private List outgoingEntities; @Autowired DataGeneratorService dataGeneratorService; - + @Autowired + PartnerService partnerService; @Autowired ObjectMapper mapper; @Override public List getAll() { - if (entities == null) { - entities = generate(); + if (incomingEntities == null) { + try { + incomingEntities = generate(true); + } catch (ParseException e) { + throw new RuntimeException(e); + } } - return entities; + if (outgoingEntities == null) { + try { + outgoingEntities = generate(false); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + ArrayList result = new ArrayList<>(incomingEntities); + result.addAll(outgoingEntities); + return result; } @Override @@ -35,31 +60,81 @@ public class InvoiceServiceImpl implements InvoiceService { @Override public void add(Invoice entity) { - entities.add(entity); - } - - @Override - public Invoice copy(Invoice sourceEntity) throws JsonProcessingException { - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(sourceEntity); - return mapper.readValue(json, Invoice.class); } @Override public void replace(Invoice targetEntity, Invoice replacementEntity) { - Invoice listEntity = entities.stream().filter(p -> p.getId().equals(targetEntity.getId())).findFirst().get(); - entities.remove(listEntity); - entities.add(replacementEntity); } - private List generate() { + private List generate(boolean income) throws ParseException { List result = new ArrayList<>(); - for (int i = 0; i < 100; i++) { + + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + for (int i = 0; i < GENERATE_COUNT; i++) { String id = RandomStringUtils.random(8, "0123456789abcdef"); String title = dataGeneratorService.faker().commerce().productName(); - Invoice entity = Invoice.builder().id(id).title(title).build(); + Partner partner = partnerService.getRandom(); + Date completionDate = dataGeneratorService.faker().date().between(formatter.parse("2010-01-01"), new Date()); + Date createDate = dataGeneratorService.faker().date().past(RandomUtils.nextInt(6, 20), TimeUnit.DAYS, completionDate); + Date paymentDeadline = dataGeneratorService.faker().date().future(1, TimeUnit.DAYS, completionDate); + int currencyIndex = RandomUtils.nextInt(0, 3); + Currency currency = Arrays.stream(Currency.values()) + .filter(p -> p.getVal() == currencyIndex) + .findFirst().get(); + double netAmount = RandomUtils.nextFloat(5000, 1000000); + double grossAmount = netAmount * 1.27; + double vatAmount = grossAmount - netAmount; + Invoice entity = Invoice.builder() + .id(id) + .title(title) + .currency(currency) + .partner(partner) + .completionDate(completionDate) + .createDate(createDate) + .paymentDeadline(paymentDeadline) + .netAmount(netAmount) + .grossAmount(grossAmount) + .vatAmount(vatAmount) + .income(income) + .build(); result.add(entity); } return result; } + + @Override + public List getRandom(boolean income) { + getAll(); + int count = RandomUtils.nextInt(10, 20); + List result = new ArrayList<>(); + for (int i = 0; i < count; i++) { + int index = RandomUtils.nextInt(0, 500); + if (income) { + result.add(incomingEntities.get(index)); + } else { + result.add(outgoingEntities.get(index)); + } + } + return result; + } + + @Override + public Invoice copy(Invoice sourceEntity) throws JsonProcessingException { + String json = toString(sourceEntity); + return mapper.readValue(json, Invoice.class); + } + + @Override + public String toString(Invoice sourceEntity) throws JsonProcessingException { + return mapper.writeValueAsString(sourceEntity); + } + + @Override + public Invoice copy(Invoice sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException { + Invoice result = copy(sourceEntity); + Field field = result.getClass().getDeclaredField(property); + field.setAccessible(true); + field.set(result, value); + return result; + } } diff --git a/lis-services/src/main/java/hu/user/lis/services/data/PartnerService.java b/lis-services/src/main/java/hu/user/lis/services/data/PartnerService.java index 0f1b02a..8743cc2 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/PartnerService.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/PartnerService.java @@ -17,4 +17,8 @@ public interface PartnerService { void replace(Partner targetEntity, Partner replacementEntity); Partner getRandom(); + + String toString(Partner sourceEntity) throws JsonProcessingException; + + Partner copy(Partner sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException; } 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 ae99f3f..ea4ac67 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 @@ -9,6 +9,7 @@ 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; @@ -40,13 +41,6 @@ public class PartnerServiceImpl implements PartnerService { entities.add(entity); } - @Override - public Partner copy(Partner sourceEntity) throws JsonProcessingException { - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(sourceEntity); - return mapper.readValue(json, Partner.class); - } - @Override public void replace(Partner targetEntity, Partner replacementEntity) { Partner listEntity = entities.stream().filter(p -> p.getId().equals(targetEntity.getId())).findFirst().get(); @@ -76,4 +70,24 @@ public class PartnerServiceImpl implements PartnerService { } return result; } + + @Override + public Partner copy(Partner sourceEntity) throws JsonProcessingException { + String json = toString(sourceEntity); + return mapper.readValue(json, Partner.class); + } + + @Override + public String toString(Partner sourceEntity) throws JsonProcessingException { + return mapper.writeValueAsString(sourceEntity); + } + + @Override + public Partner copy(Partner sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException { + Partner result = copy(sourceEntity); + Field field = result.getClass().getDeclaredField(property); + field.setAccessible(true); + field.set(result, value); + 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 c166af5..5f5b5ac 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 @@ -18,5 +18,7 @@ public interface ProjectService { boolean isInvalid(Project entity); - String toString(Project entity); + String toString(Project sourceEntity) throws JsonProcessingException; + + Project copy(Project sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException; } 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 68df25a..41b6f41 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 @@ -10,6 +10,7 @@ import org.apache.commons.lang3.StringUtils; 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; import java.util.Objects; @@ -25,6 +26,9 @@ public class ProjectServiceImpl implements ProjectService { @Autowired PartnerService partnerService; + @Autowired + InvoiceService invoiceService; + @Override public List getAll() { if (entities == null) { @@ -37,7 +41,13 @@ public class ProjectServiceImpl implements ProjectService { public Project createNew() { String id = RandomStringUtils.random(8, "0123456789abcdef"); String humanId = dataGeneratorService.faker().code().isbn13(true); - return Project.builder().id(id).humanId(humanId).active(true).build(); + return Project.builder() + .id(id) + .humanId(humanId) + .incomingInvoices(new ArrayList<>()) + .outgoingInvoices(new ArrayList<>()) + .active(true) + .build(); } @Override @@ -45,13 +55,6 @@ public class ProjectServiceImpl implements ProjectService { entities.add(entity); } - @Override - public Project copy(Project sourceEntity) throws JsonProcessingException { - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(sourceEntity); - return mapper.readValue(json, Project.class); - } - @Override public void replace(Project targetEntity, Project replacementEntity) { Project partnerInList = entities.stream().filter(p -> p.getId().equals(targetEntity.getId())).findFirst().get(); @@ -74,6 +77,8 @@ public class ProjectServiceImpl implements ProjectService { .name(name) .contactName(contactName) .partner(partner) + .incomingInvoices(invoiceService.getRandom(true)) + .outgoingInvoices(invoiceService.getRandom(false)) .build(); result.add(entity); } @@ -95,13 +100,22 @@ public class ProjectServiceImpl implements ProjectService { } @Override - public String toString(Project entity) { - ObjectMapper mapper = new ObjectMapper(); - try { - return mapper.writeValueAsString(entity); - } catch (JsonProcessingException e) { - log.catching(e); - } - return null; + public Project copy(Project sourceEntity) throws JsonProcessingException { + String json = toString(sourceEntity); + return mapper.readValue(json, Project.class); + } + + @Override + public String toString(Project sourceEntity) throws JsonProcessingException { + return mapper.writeValueAsString(sourceEntity); + } + + @Override + public Project copy(Project sourceEntity, String property, Object value) throws JsonProcessingException, NoSuchFieldException, IllegalAccessException { + Project result = copy(sourceEntity); + Field field = result.getClass().getDeclaredField(property); + field.setAccessible(true); + field.set(result, value); + return result; } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/ResourceConfigurer.java b/lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java similarity index 67% rename from lis-ui/src/main/java/hu/user/lis/ui/ResourceConfigurer.java rename to lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java index 745a8af..31b63db 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/ResourceConfigurer.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java @@ -1,4 +1,4 @@ -package hu.user.lis.ui; +package hu.user.lis.ui.config; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -9,4 +9,9 @@ public class ResourceConfigurer { public String admin() { return "admin/index"; } + + @GetMapping("/projects") + public String projects() { + return "index"; + } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/PartnerSelectorDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/PartnerSelectorDataModel.java index efb951a..8c2131a 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/PartnerSelectorDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/PartnerSelectorDataModel.java @@ -5,6 +5,8 @@ import hu.user.lis.services.data.PartnerService; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.zkoss.bind.BindUtils; import org.zkoss.zul.FieldComparator; @@ -15,6 +17,7 @@ import java.util.stream.Collectors; @Component @Log4j2 +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class PartnerSelectorDataModel extends CachedDataModel { static private final int SEARCH_LIMIT = 10; private String partialName; 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 16f8ea2..a981068 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 @@ -5,23 +5,34 @@ import lombok.Setter; import lombok.extern.log4j.Log4j2; import org.springframework.boot.info.BuildProperties; 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.select.annotation.VariableResolver; import org.zkoss.zk.ui.select.annotation.WireVariable; +import javax.servlet.http.HttpServletRequest; + @Log4j2 @VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class) +@Getter +@Setter public class IndexViewModel { - @Getter @WireVariable BuildProperties buildProperties; - - @Getter - @Setter String searchPhrase; + int selectedPage; + @Init public void init() { - log.info("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")); + } + log.info("Init {}", path); } + } 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 new file mode 100644 index 0000000..c98ce12 --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/InvoiceEditorModel.java @@ -0,0 +1,122 @@ +package hu.user.lis.ui.view; + +import hu.user.lis.db.Currency; +import hu.user.lis.db.Invoice; +import hu.user.lis.services.data.InvoiceService; +import hu.user.lis.ui.data.PartnerSelectorDataModel; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.zkoss.bind.BindContext; +import org.zkoss.bind.BindUtils; +import org.zkoss.bind.ValidationContext; +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.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.Objects; + +@Log4j2 +@Getter +@Setter +@VariableResolver(DelegatingVariableResolver.class) +public class InvoiceEditorModel extends AbstractValidator { + private Invoice origDocument; + private Invoice formDocument; + @WireVariable + private PartnerSelectorDataModel partnerSelectorDataModel; + @WireVariable + private InvoiceService invoiceServiceImpl; + private boolean formInvalid = true; + + @Init + public void init() { + log.info("Initialized"); + origDocument = (Invoice) Executions.getCurrent().getArg().get("origDocument"); + formDocument = (Invoice) Executions.getCurrent().getArg().get("formDocument"); + partnerSelectorDataModel.clearSelection(); + } + + @Command + public void onNetAmountChange() { + if (Currency.HUF.equals(formDocument.getCurrency())) { + formDocument.setGrossAmount(formDocument.getNetAmount() * 1.27); + formDocument.setVatAmount(formDocument.getGrossAmount() - formDocument.getNetAmount()); + BindUtils.postNotifyChange(this.formDocument, "grossAmount", "vatAmount"); + } + } + + @Command + public void onCloseWindow(@BindingParam("target") Window target, @BindingParam("select") boolean select) { + if (select && formInvalid) { + return; + } + Event closeEvent = new Event("onClose", target, select ? formDocument : null); + Events.postEvent(closeEvent); + } + + @Command + public void onPartnerBandChanging(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { + InputEvent event = (InputEvent) ctx.getTriggerEvent(); + log.info("onPartnerBandChanging: {}", event.getValue()); + partnerSelectorDataModel.search(event.getValue()); + } + + @Command + public void onPartnerBandOpen(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { + OpenEvent event = (OpenEvent) ctx.getTriggerEvent(); + log.info("onPartnerBandOpen: {}", event.isOpen()); + partnerSelectorDataModel.search(null); + } + + @Override + @NotifyChange("formInvalid") + public void validate(ValidationContext ctx) { + Component target = ctx.getBindContext().getComponent(); + 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); + } + } catch (Exception e) { + log.catching(e); + } + + } + + private void updateFormInvalid(boolean invalid) { + setFormInvalid(invalid); + BindUtils.postNotifyChange(this, "formInvalid"); + } +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/PartnerEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/PartnerEditorModel.java index 8aea7e5..b65c949 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/PartnerEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/PartnerEditorModel.java @@ -1,6 +1,7 @@ package hu.user.lis.ui.view; import hu.user.lis.db.Partner; +import hu.user.lis.services.data.PartnerService; import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; @@ -16,6 +17,7 @@ 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.select.annotation.VariableResolver; +import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zkplus.spring.DelegatingVariableResolver; import org.zkoss.zul.Window; @@ -27,11 +29,15 @@ import java.util.Objects; @VariableResolver(DelegatingVariableResolver.class) public class PartnerEditorModel extends AbstractValidator { private Partner formDocument; - private boolean formInvalid; + private Partner origDocument; + private boolean formInvalid = true; + @WireVariable + PartnerService partnerServiceImpl; @Init public void init() { log.info("Initialized"); + origDocument = (Partner) Executions.getCurrent().getArg().get("origDocument"); formDocument = (Partner) Executions.getCurrent().getArg().get("formDocument"); } @@ -50,7 +56,29 @@ public class PartnerEditorModel extends AbstractValidator { String property = ctx.getProperty().getProperty(); Object value = ctx.getProperty().getValue(); log.info("Validating caused by {} {} {}", target.getId(), property, value); - boolean invalid = Objects.isNull(value) || StringUtils.isBlank(Objects.toString(value)); + updateFormInvalid(false); + try { + Partner newData = partnerServiceImpl.copy(formDocument, property, value); + if (!Objects.isNull(origDocument) && partnerServiceImpl.toString(origDocument).equals(partnerServiceImpl.toString(newData))) { + log.info("Document not changed"); + updateFormInvalid(true); + return; + } + if (StringUtils.isBlank(newData.getName()) || + StringUtils.isBlank(newData.getAddress()) || + StringUtils.isBlank(newData.getVatNr()) + ) { + log.info("Document is not valid"); + updateFormInvalid(true); + } + + + } catch (Exception e) { + log.catching(e); + } + } + + private void updateFormInvalid(boolean invalid) { setFormInvalid(invalid); BindUtils.postNotifyChange(this, "formInvalid"); } 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 c85abbe..347ae0e 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 @@ -17,6 +17,8 @@ import org.zkoss.zul.Listbox; import org.zkoss.zul.Window; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Set; @Log4j2 @@ -77,20 +79,22 @@ public class PartnersViewModel extends AsyncBaseModel { } @Command - public void onAddNew() { + public void onAdd() { String page = "~./partner.zul"; - Partner editPartner = partnersDataModel.getPartnerService().createNew(); - Window partnerWindow = (Window) Executions.createComponents(page, null, - Collections.singletonMap("formDocument", editPartner)); - partnerWindow.addEventListener("onClose", e -> { + Partner newEntity = partnersDataModel.getPartnerService().createNew(); + Window editorWindow = (Window) Executions.createComponents(page, null, + Collections.singletonMap("formDocument", newEntity)); + editorWindow.addEventListener("onClose", e -> { if (e.getData() != null) { log.info("Partner popup result {}", e.getData()); - partnersDataModel.getPartnerService().add(editPartner); + partnersDataModel.getPartnerService().add(newEntity); partnersDataModel.clearSelection(); refresh(); - partnersDataModel.addToSelection(editPartner); + partnersDataModel.addToSelection(newEntity); + selectedPartner = newEntity; + // Optional listItem = partnersList.getItems().stream() -// .filter(li -> ((Partner) li.getValue()).getId().equals(editPartner.getId())) +// .filter(li -> ((Partner) li.getValue()).getId().equals(newEntity.getId())) // .findFirst(); // if (listItem.isPresent()) { // Clients.scrollIntoView(listItem.get()); @@ -99,16 +103,18 @@ public class PartnersViewModel extends AsyncBaseModel { // }); } }); - partnerWindow.doModal(); + editorWindow.doModal(); } @Command public void onEdit() throws JsonProcessingException { String page = "~./partner.zul"; - Partner editPartner = partnersDataModel.getPartnerService().copy(selectedPartner); - Window partnerWindow = (Window) Executions.createComponents(page, null, - Collections.singletonMap("formDocument", editPartner)); - partnerWindow.addEventListener("onClose", e -> { + Partner editEntity = partnersDataModel.getPartnerService().copy(selectedPartner); + Map arg = new HashMap<>(); + arg.put("origDocument", selectedPartner); + arg.put("formDocument", editEntity); + Window editorWindow = (Window) Executions.createComponents(page, null, arg); + editorWindow.addEventListener("onClose", e -> { if (e.getData() != null) { log.info("Partner popup result {}", e.getData()); Partner modifiedEntity = (Partner) e.getData(); @@ -119,7 +125,7 @@ public class PartnersViewModel extends AsyncBaseModel { selectedPartner = modifiedEntity; } }); - partnerWindow.doModal(); + editorWindow.doModal(); } 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 804d145..ffa02f1 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,9 +1,11 @@ package hu.user.lis.ui.view; -import hu.user.lis.db.Partner; +import com.fasterxml.jackson.core.JsonProcessingException; +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.data.PartnerSelectorDataModel; -import hu.user.lis.ui.data.ProjectsDataModel; import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; @@ -24,7 +26,7 @@ import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zkplus.spring.DelegatingVariableResolver; import org.zkoss.zul.Window; -import java.util.Objects; +import java.util.*; @Log4j2 @Getter @@ -32,18 +34,22 @@ import java.util.Objects; @VariableResolver(DelegatingVariableResolver.class) public class ProjectEditorModel extends AbstractValidator { private Project formDocument; - private Partner selectedPartner; + private Project origDocument; @WireVariable private PartnerSelectorDataModel partnerSelectorDataModel; @WireVariable - private ProjectsDataModel projectsDataModel; - private boolean formInvalid; + private InvoiceService invoiceServiceImpl; + @WireVariable + private ProjectService projectServiceImpl; + private boolean formInvalid = true; + private Invoice selectedIncomingInvoice; + private Invoice selectedOutgoingInvoice; @Init public void init() { log.info("Initialized"); + origDocument = (Project) Executions.getCurrent().getArg().get("origDocument"); formDocument = (Project) Executions.getCurrent().getArg().get("formDocument"); - selectedPartner = formDocument.getPartner(); partnerSelectorDataModel.clearSelection(); } @@ -79,26 +85,156 @@ public class ProjectEditorModel extends AbstractValidator { if (e.getData() != null) { partnerSelectorDataModel.clearSelection(); //setSelectedSupplierId(((Supplier) e.getData()).getId()); - BindUtils.postNotifyChange(null, null, this, "selectedSupplierId"); + BindUtils.postNotifyChange(this, "selectedSupplierId"); } }); suppliersWindow.doModal(); } - @NotifyChange({"selectedPartner"}) - public void setSelectedPartner(Partner selectedPartner) { - this.selectedPartner = selectedPartner; - formDocument.setPartner(selectedPartner); - } - @Override public void validate(ValidationContext ctx) { Component target = ctx.getBindContext().getComponent(); String property = ctx.getProperty().getProperty(); Object value = ctx.getProperty().getValue(); log.info("Validating caused by {} {} {}", target.getId(), property, value); - boolean invalid = Objects.isNull(value) || StringUtils.isBlank(Objects.toString(value)); + try { + Project newData = projectServiceImpl.copy(formDocument, property, value); + validate(newData); + } catch (Exception e) { + log.catching(e); + } + } + + private void validate(Project newData) throws JsonProcessingException { + updateFormInvalid(false); + if (!Objects.isNull(origDocument) && projectServiceImpl.toString(origDocument).equals(projectServiceImpl.toString(newData))) { + log.info("Document not changed"); + updateFormInvalid(true); + return; + } + + if (StringUtils.isBlank(newData.getName()) || + StringUtils.isBlank(newData.getContactName()) || + Objects.isNull(newData.getPartner()) + ) { + log.info("Document is not valid"); + updateFormInvalid(true); + } + } + + @Command + public void onAddIncoming() { + String page = "~./invoice.zul"; + Invoice editEntity = invoiceServiceImpl.createNew(); + editEntity.setIncome(true); + Window editorWindow = (Window) Executions.createComponents(page, null, + Collections.singletonMap("formDocument", editEntity)); + editorWindow.addEventListener("onClose", e -> { + if (e.getData() != null) { + formDocument.getIncomingInvoices().add(editEntity); + selectedIncomingInvoice = editEntity; + BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); + Project newData = projectServiceImpl.copy(formDocument); + validate(newData); + } + }); + editorWindow.doModal(); + } + + @Command + public void onEditIncoming() throws JsonProcessingException { + String page = "~./invoice.zul"; + Invoice editEntity = invoiceServiceImpl.copy(selectedIncomingInvoice); + Map arg = new HashMap<>(); + arg.put("origDocument", selectedIncomingInvoice); + arg.put("formDocument", editEntity); + Window editorWindow = (Window) Executions.createComponents(page, null, arg); + editorWindow.addEventListener("onClose", e -> { + if (e.getData() != null) { + Invoice modifiedEntity = (Invoice) e.getData(); + List incomingInvoices = formDocument.getIncomingInvoices(); + int index = incomingInvoices.indexOf(selectedIncomingInvoice); + incomingInvoices.remove(selectedIncomingInvoice); + incomingInvoices.add(index, modifiedEntity); + selectedIncomingInvoice = modifiedEntity; + BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); + Project newData = projectServiceImpl.copy(formDocument); + validate(newData); + } + }); + editorWindow.doModal(); + } + + @Command + public void onRemoveIncoming() { + if (selectedIncomingInvoice == null) { + return; + } + formDocument.getIncomingInvoices().remove(selectedIncomingInvoice); + selectedIncomingInvoice = null; + BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); + } + + @Command + public void onAddOutgoing() { + String page = "~./invoice.zul"; + Invoice editEntity = invoiceServiceImpl.createNew(); + Window editorWindow = (Window) Executions.createComponents(page, null, + Collections.singletonMap("formDocument", editEntity)); + editorWindow.addEventListener("onClose", e -> { + if (e.getData() != null) { + formDocument.getOutgoingInvoices().add(editEntity); + selectedOutgoingInvoice = editEntity; + BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); + Project newData = projectServiceImpl.copy(formDocument); + validate(newData); + } + }); + editorWindow.doModal(); + } + + @Command + public void onEditOutgoing() throws JsonProcessingException { + String page = "~./invoice.zul"; + Invoice editEntity = invoiceServiceImpl.copy(selectedOutgoingInvoice); + Map arg = new HashMap<>(); + arg.put("origDocument", selectedOutgoingInvoice); + arg.put("formDocument", editEntity); + Window editorWindow = (Window) Executions.createComponents(page, null, arg); + editorWindow.addEventListener("onClose", e -> { + if (e.getData() != null) { + Invoice modifiedEntity = (Invoice) e.getData(); + List outgoingInvoices = formDocument.getOutgoingInvoices(); + int index = outgoingInvoices.indexOf(selectedOutgoingInvoice); + outgoingInvoices.remove(selectedOutgoingInvoice); + outgoingInvoices.add(index, modifiedEntity); + selectedOutgoingInvoice = modifiedEntity; + BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); + Project newData = projectServiceImpl.copy(formDocument); + validate(newData); + } + }); + editorWindow.doModal(); + } + + @Command + public void onRemoveOutgoing() { + if (selectedOutgoingInvoice == null) { + return; + } + formDocument.getOutgoingInvoices().remove(selectedOutgoingInvoice); + selectedOutgoingInvoice = null; + BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); + } + + private void updateFormInvalid(boolean invalid) { setFormInvalid(invalid); BindUtils.postNotifyChange(this, "formInvalid"); } 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 80ac4fd..ba355e3 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 @@ -15,6 +15,8 @@ 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 @@ -68,18 +70,19 @@ public class ProjectsViewModel extends AsyncBaseModel { } @Command - public void onAddNew() { + public void onAdd() { String page = "~./project.zul"; - Project editEntity = projectsDataModel.getProjectService().createNew(); + Project newEntity = projectsDataModel.getProjectService().createNew(); Window partnerWindow = (Window) Executions.createComponents(page, null, - Collections.singletonMap("formDocument", editEntity)); + Collections.singletonMap("formDocument", newEntity)); partnerWindow.addEventListener("onClose", e -> { if (e.getData() != null) { log.info("Partner popup result {}", e.getData()); - projectsDataModel.getProjectService().add(editEntity); + projectsDataModel.getProjectService().add(newEntity); projectsDataModel.clearSelection(); refresh(); - projectsDataModel.addToSelection(editEntity); + projectsDataModel.addToSelection(newEntity); + selectedProject = newEntity; // Optional listItem = partnersList.getItems().stream() // .filter(li -> ((Partner) li.getValue()).getId().equals(editPartner.getId())) // .findFirst(); @@ -97,8 +100,11 @@ public class ProjectsViewModel extends AsyncBaseModel { public void onEdit() throws JsonProcessingException { String page = "~./project.zul"; Project editEntity = projectsDataModel.getProjectService().copy(selectedProject); - Window partnerWindow = (Window) Executions.createComponents(page, null, - Collections.singletonMap("formDocument", editEntity)); + 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()); diff --git a/lis-ui/src/main/resources/web/index.zul b/lis-ui/src/main/resources/web/index.zul index 100e7ce..e5c2268 100644 --- a/lis-ui/src/main/resources/web/index.zul +++ b/lis-ui/src/main/resources/web/index.zul @@ -32,7 +32,7 @@
- + @@ -41,7 +41,8 @@ - + diff --git a/lis-ui/src/main/resources/web/invoice.zul b/lis-ui/src/main/resources/web/invoice.zul new file mode 100644 index 0000000..f1d97c9 --- /dev/null +++ b/lis-ui/src/main/resources/web/invoice.zul @@ -0,0 +1,94 @@ + + + + + + import hu.user.lis.db.Currency; + ListModelList currencies = new ListModelList(Currency.values()); + + + +
+ + + + + + + + + + + + +
+ + +