Sort and cache
authorelgekko <vasary@elgekko.net>
Thu, 6 Jul 2023 15:35:57 +0000 (17:35 +0200)
committerelgekko <vasary@elgekko.net>
Thu, 6 Jul 2023 15:35:57 +0000 (17:35 +0200)
51 files changed:
KB.md
TODO.txt
lis-app/src/main/resources/application.yaml
lis-db/src/main/java/hu/user/lis/db/Invoice.java
lis-db/src/main/java/hu/user/lis/db/Project.java
lis-db/src/main/java/hu/user/lis/db/Treasury.java
lis-db/src/main/java/hu/user/lis/db/repository/AssociateRepositorySearchImpl.java
lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepositorySearch.java
lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepositorySearchImpl.java
lis-db/src/main/java/hu/user/lis/db/repository/ProjectAssociateRepository.java
lis-db/src/main/java/hu/user/lis/db/repository/ProjectRepository.java
lis-db/src/main/java/hu/user/lis/db/repository/ProjectRepositorySearchImpl.java
lis-db/src/main/java/hu/user/lis/db/repository/ProjectStatusRepository.java
lis-db/src/main/java/hu/user/lis/db/repository/ServiceRecordRepositorySearchImpl.java
lis-services/src/main/java/hu/user/lis/services/api/DbApi.java
lis-services/src/main/java/hu/user/lis/services/api/GenerateApi.java
lis-services/src/main/java/hu/user/lis/services/api/ProjectApi.java
lis-services/src/main/java/hu/user/lis/services/data/InvoiceService.java
lis-services/src/main/java/hu/user/lis/services/data/InvoiceServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/TreasuryService.java
lis-services/src/main/java/hu/user/lis/services/data/TreasuryServiceImpl.java
lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java
lis-ui/src/main/java/hu/user/lis/ui/converter/ProjectStatusConverter.java
lis-ui/src/main/java/hu/user/lis/ui/data/CachedDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/CachedSpringDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/data/PartnerSelectorDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/PartnersDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectAssociatesDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectStatusDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectsDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/ServiceRecordsDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/TreasuryDataModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/editor/PartnerEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/event/EventBus.java
lis-ui/src/main/java/hu/user/lis/ui/view/IndexViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/LoginViewModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java
lis-ui/src/main/resources/metainfo/zk/zk.xml
lis-ui/src/main/resources/web/index.zul
lis-ui/src/main/resources/web/login.zul
lis-ui/src/main/resources/web/project-editor.zul
lis-ui/src/main/resources/web/projects.zul
lis-ui/src/main/resources/web/service-records.zul
lis-ui/src/main/resources/web/settings.zul
lis-ui/src/main/resources/web/static/css/webclient.css

diff --git a/KB.md b/KB.md
index 4aa1b8fdadd866a48ff3742dc5f4d64d0e780b7c..51658e8fffe64c32cb42faa55e8b78c1661a6ba7 100644 (file)
--- a/KB.md
+++ b/KB.md
@@ -60,6 +60,7 @@ https://www.zkoss.org/wiki/ZK_Spring_Essentials/Working_with_ZK_Spring/Working_w
 (To enable remove @SpringBootApplication with exludes and @ComponentScan)
 https://www.baeldung.com/get-user-in-spring-security
 https://www.baeldung.com/spring-security-authentication-provider
+https://www.zkoss.org/wiki/ZK_Developer%27s_Reference/Security_Tips/SSO_Redirect_Handling
 
 ##### ZK Style
 
index c64c8209f960d61fd177aa932ab95f865b2b10b7..5e7706ecc2c6cf811a1c7817a67dedc17816fe1e 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
     A jobb oldalon pedig legyen látható a projekt árrése.
     Az árrés annyi sorból áll ahány devizanem van a projekt számláiban. Egy adott devizanem esetén a számolás:
     Kimenő - Bejövő - Treasury eladás + Treasury vétel
+* auth/ldap ldap:fds.in.useribm.hu:389,ldaps:fds.useribm.hu:636
 
-
-db persist
-- servicerecord:
-    project generalas
-    generalas
-    project szuro
-
-auth/ldap
 autorizacio
 nav
 szamla erkeztetes camunda: egy felasznalohoz jon be, projekthez lehessen csatolni, projektszanot ellenorizze
@@ -81,11 +74,5 @@ szamla erkeztetes camunda: egy felasznalohoz jon be, projekthez lehessen csatoln
 - Plugin: 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.
 
 
-fds.in.useribm.hu
-389
-
-ldaps
-fds.useribm.hu
-636
 
 
index 3f2d8e42464d0269190e5976d4bfb41242a1769a..507a9d2586a38e4450d5dad9c7446fdca441bcb8 100644 (file)
@@ -9,7 +9,7 @@ spring:
   jpa:
     hibernate:
       use-new-id-generator-mappings: false
-    show-sql: true
+    show-sql: false
     properties:
       hibernate:
         format_sql: true
index 0b9eccdb3779a639d96f5ba9746ec10323eed661..4ee7af12b71e0d99ec10d33b72e5860c562388b3 100644 (file)
@@ -1,5 +1,6 @@
 package hu.user.lis.db;
 
+import com.fasterxml.jackson.annotation.JsonIncludeProperties;
 import lombok.*;
 
 import javax.persistence.*;
@@ -19,9 +20,11 @@ public class Invoice {
     String title;
     @OneToOne
     @JoinColumn(name = "partner_id")
+    @JsonIncludeProperties({"id"})
     Partner partner;
     @ManyToOne
     @JoinColumn(name = "project_id")
+    @JsonIncludeProperties({"id"})
     Project project;
     boolean income;
     Currency currency;
index 16cea0763944b803dbcaeea1049a97d18bf8a432..ff1d8dacc86db7e4283c592d6584bf2aecb9a970 100644 (file)
@@ -1,9 +1,10 @@
 package hu.user.lis.db;
 
+import com.fasterxml.jackson.annotation.JsonIncludeProperties;
 import lombok.*;
 
 import javax.persistence.*;
-import java.util.List;
+import java.util.Set;
 
 @Getter
 @Setter
@@ -23,12 +24,16 @@ public class Project {
     String contactName;
     @ManyToOne
     @JoinColumn(name = "partner_id")
+    @JsonIncludeProperties({"id"})
     Partner partner;
     boolean active;
-    @OneToMany(mappedBy = "project")
-    List<Invoice> incomingInvoices;
-    @OneToMany(mappedBy = "project")
-    List<Invoice> outgoingInvoices;
-    @OneToMany(mappedBy = "project")
-    List<Treasury> treasuries;
+    @OneToMany(mappedBy = "project", fetch = FetchType.EAGER)
+    @JsonIncludeProperties({"id"})
+    Set<Invoice> incomingInvoices;
+    @OneToMany(mappedBy = "project", fetch = FetchType.EAGER)
+    @JsonIncludeProperties({"id"})
+    Set<Invoice> outgoingInvoices;
+    @OneToMany(mappedBy = "project", fetch = FetchType.EAGER)
+    @JsonIncludeProperties({"id"})
+    Set<Treasury> treasuries;
 }
index 5b2f7ced33acb20dd97a73c919e3f0cd9f8e8598..60114e6699007787b62d730ba8960c7972ec5dd1 100644 (file)
@@ -1,5 +1,6 @@
 package hu.user.lis.db;
 
+import com.fasterxml.jackson.annotation.JsonIncludeProperties;
 import lombok.*;
 
 import javax.persistence.*;
@@ -17,6 +18,7 @@ public class Treasury {
     Long id;
     @ManyToOne
     @JoinColumn(name = "project_id")
+    @JsonIncludeProperties({"id"})
     Project project;
     String humanId;
     double buyAmount;
index 1cafe7550f4e6935f1d3d8cac38e75db05d765d8..90d2dbf77d82bc7a27fe3dfa191ed7824707ef87 100644 (file)
@@ -3,6 +3,7 @@ package hu.user.lis.db.repository;
 import hu.user.lis.db.Associate;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.query.QueryUtils;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.EntityManager;
@@ -41,6 +42,7 @@ public class AssociateRepositorySearchImpl implements AssociateRepositorySearch
         Root<Associate> root = cq.from(Associate.class);
 
         cq.where(getPredicates(cb, root, partialName, filterShowActive, filterShowInActive));
+        cq.orderBy(QueryUtils.toOrders(pageable.getSort(), root, cb));
         TypedQuery<Associate> query = entityManager.createQuery(cq);
         query.setMaxResults(pageable.getPageSize());
         query.setFirstResult(pageable.getPageSize() * pageable.getPageNumber());
index 8ef30ed76b33a29e02ff57a309de64f1a0b96801..9e07be70cb485e951f5ca5e4abc6cc901c5138de 100644 (file)
@@ -6,7 +6,7 @@ import org.springframework.data.domain.Pageable;
 import java.util.List;
 
 public interface PartnerRepositorySearch {
-    List<Partner> search(String partialName, String partialVatNr, String partialAddress, boolean filterShowActive, boolean filterShowInActive, Pageable pageable);
+    List<Partner> search(String partialSearch, boolean filterShowActive, boolean filterShowInActive, Pageable pageable);
 
-    long count(String partialName, String partialVatNr, String partialAddress, boolean filterShowActive, boolean filterShowInActive);
+    long count(String ppartialSearch, boolean filterShowActive, boolean filterShowInActive);
 }
index 7266539a3c878582ad4764e9ee14c07e2c31e842..67e57f01846b1cb04428a6da8b590fbe66e52a8f 100644 (file)
@@ -3,6 +3,7 @@ package hu.user.lis.db.repository;
 import hu.user.lis.db.Partner;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.query.QueryUtils;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.EntityManager;
@@ -20,22 +21,16 @@ public class PartnerRepositorySearchImpl implements PartnerRepositorySearch {
     @PersistenceContext
     EntityManager entityManager;
 
-    Predicate[] getPredicates(CriteriaBuilder cb, Root<Partner> root, String partialName,
-                              String partialVatNr, String partialAddress, boolean filterShowActive, boolean filterShowInActive) {
+    Predicate[] getPredicates(CriteriaBuilder cb, Root<Partner> root, String partialSearch, boolean filterShowActive, boolean filterShowInActive) {
         List<Predicate> predicates = new ArrayList<>();
-        List<Predicate> orPredicates = new ArrayList<>();
-        if (StringUtils.isNotBlank(partialName)) {
-            orPredicates.add(cb.like(root.get("name"), "%" + partialName + "%"));
-        }
-        if (StringUtils.isNotBlank(partialVatNr)) {
-            orPredicates.add(cb.like(root.get("vat_nr"), "%" + partialVatNr + "%"));
-        }
-        if (StringUtils.isNotBlank(partialAddress)) {
-            orPredicates.add(cb.like(root.get("address"), "%" + partialAddress + "%"));
-        }
-        if (orPredicates.size() > 0) {
+        if (StringUtils.isNotBlank(partialSearch)) {
+            List<Predicate> orPredicates = new ArrayList<>();
+            orPredicates.add(cb.like(cb.lower(root.get("name")), "%" + partialSearch.toLowerCase() + "%"));
+            orPredicates.add(cb.like(cb.lower(root.get("vat_nr")), "%" + partialSearch.toLowerCase() + "%"));
+            orPredicates.add(cb.like(cb.lower(root.get("address")), "%" + partialSearch.toLowerCase() + "%"));
             predicates.add(cb.or(orPredicates.toArray(new Predicate[]{})));
         }
+
         if (filterShowActive && !filterShowInActive) {
             predicates.add(cb.isTrue(root.get("active")));
         }
@@ -45,26 +40,14 @@ public class PartnerRepositorySearchImpl implements PartnerRepositorySearch {
         return predicates.toArray(new Predicate[]{});
     }
 
-    Predicate[] getPredicates(CriteriaBuilder cb, Root<Partner> root, String partialName, boolean filterShowActive) {
-        List<Predicate> predicates = new ArrayList<>();
-        if (StringUtils.isNotBlank(partialName)) {
-            predicates.add(cb.like(root.get("name"), "%" + partialName + "%"));
-        }
-        if (filterShowActive) {
-            predicates.add(cb.isTrue(root.get("active")));
-        } else {
-            predicates.add(cb.isFalse(root.get("active")));
-        }
-        return predicates.toArray(new Predicate[]{});
-    }
-
     @Override
-    public List<Partner> search(String partialName, String partialVatNr, String partialAddress, boolean filterShowActive, boolean filterShowInActive, Pageable pageable) {
+    public List<Partner> search(String partialSearch, boolean filterShowActive, boolean filterShowInActive, Pageable pageable) {
         CriteriaBuilder cb = entityManager.getCriteriaBuilder();
         CriteriaQuery<Partner> cq = cb.createQuery(Partner.class);
         Root<Partner> root = cq.from(Partner.class);
 
-        cq.where(getPredicates(cb, root, partialName, partialVatNr, partialAddress, filterShowActive, filterShowInActive));
+        cq.where(getPredicates(cb, root, partialSearch, filterShowActive, filterShowInActive));
+        cq.orderBy(QueryUtils.toOrders(pageable.getSort(), root, cb));
         TypedQuery<Partner> query = entityManager.createQuery(cq);
         query.setMaxResults(pageable.getPageSize());
         query.setFirstResult(pageable.getPageSize() * pageable.getPageNumber());
@@ -72,13 +55,13 @@ public class PartnerRepositorySearchImpl implements PartnerRepositorySearch {
     }
 
     @Override
-    public long count(String partialName, String partialVatNr, String partialAddress, boolean filterShowActive, boolean filterShowInActive) {
+    public long count(String partialSearch, boolean filterShowActive, boolean filterShowInActive) {
         CriteriaBuilder cb = entityManager.getCriteriaBuilder();
         CriteriaQuery<Long> cq = cb.createQuery(Long.class);
         Root<Partner> root = cq.from(Partner.class);
 
         cq.select(cb.count(root));
-        cq.where(getPredicates(cb, root, partialName, partialVatNr, partialAddress, filterShowActive, filterShowInActive));
+        cq.where(getPredicates(cb, root, partialSearch, filterShowActive, filterShowInActive));
         return entityManager.createQuery(cq).getSingleResult();
     }
 
index 721c76c9303278c7477f782c9cf2689554ae5556..eace4a2644a28f2697fc83af190622eb100a0dc9 100644 (file)
@@ -1,12 +1,12 @@
 package hu.user.lis.db.repository;
 
 import hu.user.lis.db.ProjectAssociate;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 
+import java.util.List;
+
 public interface ProjectAssociateRepository extends JpaRepository<ProjectAssociate, Long> {
-    Page<ProjectAssociate> findAllByProjectId(Long projectId, Pageable pageable);
+    List<ProjectAssociate> findAllByProjectId(Long projectId);
 
     Long countByProjectId(Long projectId);
 
index a5868eadba800d73c7e48b180c6bedfbbfca8ce7..9fcbfaa1b01f5c2b1b96dc1ee8539fb04c894831 100644 (file)
@@ -3,6 +3,12 @@ package hu.user.lis.db.repository;
 import hu.user.lis.db.Project;
 import org.springframework.data.jpa.repository.JpaRepository;
 
+import java.util.List;
+
 public interface ProjectRepository extends JpaRepository<Project, Long>, ProjectRepositorySearch {
 
+    List<Project> findByHumanIdLikeOrderByHumanIdDesc(String yearSearch);
+
+    Project findFirstByHumanIdLikeOrderByHumanIdDesc(String yearSearch);
+
 }
index 6d7a4efb8b11befd2ad9749a9a5c69c542af1520..9c252ee1db610dbcba78e3b741d50dfc311ab0e3 100644 (file)
@@ -3,6 +3,7 @@ package hu.user.lis.db.repository;
 import hu.user.lis.db.Project;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.query.QueryUtils;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.EntityManager;
@@ -46,6 +47,7 @@ public class ProjectRepositorySearchImpl implements ProjectRepositorySearch {
         Root<Project> root = cq.from(Project.class);
 
         cq.where(getPredicates(cb, root, partialSearch, filterShowActive, filterShowInActive));
+        cq.orderBy(QueryUtils.toOrders(pageable.getSort(), root, cb));
         TypedQuery<Project> query = entityManager.createQuery(cq);
         query.setMaxResults(pageable.getPageSize());
         query.setFirstResult(pageable.getPageSize() * pageable.getPageNumber());
index 471419de9c4b8e17270ca8b2fce81a654405765d..c3087e4d4791a4823e603098b191694f4a8f0463 100644 (file)
@@ -10,4 +10,6 @@ public interface ProjectStatusRepository extends JpaRepository<ProjectStatus, Lo
     List<ProjectStatus> findByActiveIsTrue(Sort sort);
 
     long countByActiveIsTrue();
+
+    ProjectStatus findByOrder(int order);
 }
index 8d89ebe9ddd2f52ef4130ae723105f16c0481ea9..e330623bce576cf38deddf8d7a87eb2781de2cf6 100644 (file)
@@ -1,7 +1,9 @@
 package hu.user.lis.db.repository;
 
 import hu.user.lis.db.ServiceRecord;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.query.QueryUtils;
 
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
@@ -14,6 +16,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
+@Log4j2
 public class ServiceRecordRepositorySearchImpl implements ServiceRecordRepositorySearch {
     @PersistenceContext
     EntityManager entityManager;
@@ -21,10 +24,10 @@ public class ServiceRecordRepositorySearchImpl implements ServiceRecordRepositor
     Predicate[] getPredicates(CriteriaBuilder cb, Root<ServiceRecord> root, Long filterProjectId, Long filterAssociateId) {
         List<Predicate> predicates = new ArrayList<>();
         if (Objects.nonNull(filterProjectId)) {
-            predicates.add(cb.equal(root.join("project").get("id"), filterProjectId));
+            predicates.add(cb.equal(root.get("project"), filterProjectId));
         }
         if (Objects.nonNull(filterAssociateId)) {
-            predicates.add(cb.equal(root.join("associate").get("id"), filterAssociateId));
+            predicates.add(cb.equal(root.get("associate"), filterAssociateId));
         }
         return predicates.toArray(new Predicate[]{});
     }
@@ -36,6 +39,7 @@ public class ServiceRecordRepositorySearchImpl implements ServiceRecordRepositor
         Root<ServiceRecord> root = cq.from(ServiceRecord.class);
 
         cq.where(getPredicates(cb, root, filterProjectId, filterAssociateId));
+        cq.orderBy(QueryUtils.toOrders(pageable.getSort(), root, cb));
         TypedQuery<ServiceRecord> query = entityManager.createQuery(cq);
         query.setMaxResults(pageable.getPageSize());
         query.setFirstResult(pageable.getPageSize() * pageable.getPageNumber());
index b7280b3561277f81fb54828615c5a894a9bf2192..e8ddd6e38b2010f702f8e468afc8d6dcdf0108ed 100644 (file)
@@ -1,6 +1,8 @@
 package hu.user.lis.services.api;
 
 import hu.user.lis.services.data.DataService;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -9,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 
 import java.util.List;
 
+
 public abstract class DbApi<T, R extends JpaRepository<T, Long>, S extends DataService<T>> {
 
     protected abstract S getService();
@@ -20,6 +23,11 @@ public abstract class DbApi<T, R extends JpaRepository<T, Long>, S extends DataS
         return getRepository().findAll();
     }
 
+    @GetMapping("/page")
+    public Page<T> page(Pageable pageable) {
+        return getRepository().findAll(pageable);
+    }
+
     @GetMapping("/get/{id}")
     public T get(@PathVariable long id) {
         return getRepository().findById(id).orElse(null);
@@ -37,7 +45,12 @@ public abstract class DbApi<T, R extends JpaRepository<T, Long>, S extends DataS
 
     @GetMapping("/generate")
     public List<T> generate() {
-        deleteAll();
-        return getRepository().saveAll(getService().getAll());
+        List<T> result = getRepository().saveAll(getService().getAll());
+        afterSave(result);
+        return result;
+    }
+
+    protected void afterSave(List<T> entities) {
+
     }
 }
index 01e9383a3bfac188ce1293298ab23d07a6cd27b5..41267454f0aef4fd2b60e599ae449406e8542a23 100644 (file)
@@ -29,6 +29,15 @@ public class GenerateApi {
 
     @GetMapping("/all")
     public String list() {
+        serviceRecordApi.deleteAll();
+        projectAssociateApi.deleteAll();
+        treasuryApi.deleteAll();
+        invoiceApi.deleteAll();
+        associateApi.deleteAll();
+        projectApi.deleteAll();
+        partnerApi.deleteAll();
+        projectStatusApi.deleteAll();
+        
         log.info("projectStatus");
         projectStatusApi.generate();
         log.info("partner");
index a57f17976fecce64d256b4f73dd35a5a39d5f488..2baadf56252e185ce445ea721193b1109cfc03a4 100644 (file)
@@ -1,13 +1,21 @@
 package hu.user.lis.services.api;
 
+import hu.user.lis.db.Invoice;
 import hu.user.lis.db.Project;
+import hu.user.lis.db.Treasury;
+import hu.user.lis.db.repository.InvoiceRepository;
 import hu.user.lis.db.repository.ProjectRepository;
+import hu.user.lis.db.repository.TreasuryRepository;
 import hu.user.lis.services.data.ProjectService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
 @Log4j2
 @RestController
 @RequestMapping("/api/project")
@@ -16,6 +24,10 @@ public class ProjectApi extends DbApi<Project, ProjectRepository, ProjectService
     ProjectRepository projectRepository;
     @Autowired
     ProjectService projectService;
+    @Autowired
+    private TreasuryRepository treasuryRepository;
+    @Autowired
+    private InvoiceRepository invoiceRepository;
 
     @Override
     protected ProjectService getService() {
@@ -26,4 +38,32 @@ public class ProjectApi extends DbApi<Project, ProjectRepository, ProjectService
     protected ProjectRepository getRepository() {
         return projectRepository;
     }
+
+    @Override
+    protected void afterSave(List<Project> entities) {
+        entities.forEach(p -> {
+            Set<Invoice> incomingInvoices = p.getIncomingInvoices();
+            if (Objects.nonNull(incomingInvoices)) {
+                incomingInvoices.forEach(i -> {
+                    i.setProject(p);
+                    invoiceRepository.save(i);
+                });
+            }
+
+            Set<Invoice> outgoingInvoices = p.getOutgoingInvoices();
+            if (Objects.nonNull(outgoingInvoices)) {
+                outgoingInvoices.forEach(i -> {
+                    i.setProject(p);
+                    invoiceRepository.save(i);
+                });
+            }
+
+            Set<Treasury> treasuries = p.getTreasuries();
+            treasuries.forEach(t -> {
+                t.setProject(p);
+                treasuryRepository.save(t);
+            });
+        });
+    }
+
 }
index cacadd42e00410a1d674b356e718eee801b4573f..a2043c901f6df4322c9f322fecc337775c42530b 100644 (file)
@@ -3,6 +3,7 @@ package hu.user.lis.services.data;
 import hu.user.lis.db.Invoice;
 
 import java.util.List;
+import java.util.Set;
 
 public interface InvoiceService extends DataService<Invoice> {
     void setAll(List<Invoice> entities);
@@ -13,11 +14,11 @@ public interface InvoiceService extends DataService<Invoice> {
 
     void replace(Invoice targetEntity, Invoice replacementEntity);
 
-    List<Invoice> getRandom(boolean income);
+    Set<Invoice> getRandom(boolean income);
 
     Invoice getById(String id);
 
     Invoice getByHumanId(String id);
 
-    List<Invoice> getByHumanIds(String[] ids);
+    Set<Invoice> getByHumanIds(String[] ids);
 }
index b7d64856b7802a7ccd6b5945d648bdbe440cb4f6..1c6cc2ed415286d7982d3807d58ab7a5ca05b205 100644 (file)
@@ -1,6 +1,5 @@
 package hu.user.lis.services.data;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import hu.user.lis.db.Currency;
 import hu.user.lis.db.Invoice;
 import hu.user.lis.db.Partner;
@@ -12,10 +11,7 @@ import org.springframework.stereotype.Service;
 import java.text.DateFormat;
 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.*;
 import java.util.concurrent.TimeUnit;
 
 @Service
@@ -26,8 +22,7 @@ public class InvoiceServiceImpl extends DataServiceImpl<Invoice> implements Invo
     DataGeneratorService dataGeneratorService;
     @Autowired
     PartnerService partnerService;
-    @Autowired
-    ObjectMapper mapper;
+
     private List<Invoice> incomingEntities;
     private List<Invoice> outgoingEntities;
 
@@ -765,8 +760,8 @@ public class InvoiceServiceImpl extends DataServiceImpl<Invoice> implements Invo
     }
 
     @Override
-    public List<Invoice> getByHumanIds(String[] ids) {
-        List<Invoice> result = new ArrayList<>();
+    public Set<Invoice> getByHumanIds(String[] ids) {
+        Set<Invoice> result = new HashSet<>();
 
         for (String i : ids) {
             result.add(getByHumanId(i));
@@ -777,10 +772,10 @@ public class InvoiceServiceImpl extends DataServiceImpl<Invoice> implements Invo
 
 
     @Override
-    public List<Invoice> getRandom(boolean income) {
+    public Set<Invoice> getRandom(boolean income) {
         getAll();
         int count = RandomUtils.nextInt(2, 5);
-        List<Invoice> result = new ArrayList<>();
+        Set<Invoice> result = new HashSet<>();
         for (int i = 0; i < count; i++) {
             if (income) {
                 int index = RandomUtils.nextInt(0, incomingEntities.size());
index 091f07e9fc4ec4bf4ede806e06a8faf4aaa94057..e099ccc0e8723c6752518234a9850bd87391c089 100644 (file)
@@ -12,6 +12,7 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -58,14 +59,13 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
 
     @Override
     public Project createNew() {
-        String humanId = dataGeneratorService.faker().code().isbn13(true);
+//        String humanId = dataGeneratorService.faker().code().isbn13(true);
         ProjectStatus projectStatus = projectStatusService.getAll().get(0);
         return Project.builder()
                 .projectStatus(projectStatus)
-                .humanId(humanId)
-                .incomingInvoices(new ArrayList<>())
-                .outgoingInvoices(new ArrayList<>())
-                .treasuries(new ArrayList<>())
+                .incomingInvoices(new HashSet<>())
+                .outgoingInvoices(new HashSet<>())
+                .treasuries(new HashSet<>())
                 .active(true)
                 .build();
     }
@@ -106,7 +106,7 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
                     .partner(partner)
                     .incomingInvoices(invoiceService.getRandom(true))
                     .outgoingInvoices(invoiceService.getRandom(false))
-                    .treasuries(new ArrayList<>())
+                    .treasuries(new HashSet<>())
                     .build();
             result.add(entity);
         }
@@ -131,7 +131,7 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
                 .partner(partner)
                 .incomingInvoices(invoiceService.getByHumanIds(new String[]{"VSz-2023/00070-"}))   // VSz-2023/00070-
                 .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"USER-2023-7"}))  // USER-2023-7
-                .treasuries(new ArrayList<>())
+                .treasuries(new HashSet<>())
                 .build();
         result.add(entity);
 
@@ -182,7 +182,7 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
                 .partner(partner)
                 .incomingInvoices(invoiceService.getByHumanIds(new String[]{"17356/23"}))   // 17356/23
                 .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-53"}))  // E-USER-2023-53
-                .treasuries(new ArrayList<>())
+                .treasuries(new HashSet<>())
                 .build();
         result.add(entity);
 
index 8b9788514f36aa40c71fe4d8017d18deeb1b9228..c91e7bce7c001655abf48152e74a32605ae78694 100644 (file)
@@ -3,6 +3,7 @@ package hu.user.lis.services.data;
 import hu.user.lis.db.Treasury;
 
 import java.util.List;
+import java.util.Set;
 
 public interface TreasuryService extends DataService<Treasury> {
     Treasury createNew();
@@ -11,5 +12,5 @@ public interface TreasuryService extends DataService<Treasury> {
 
     Treasury getByHumanId(String id);
 
-    List<Treasury> getByHumanIds(String[] ids);
+    Set<Treasury> getByHumanIds(String[] ids);
 }
index 12702c2ba5e43782125424ff05bbd3d5e11c4159..7b8d1dacce268f06e173ff47fe337b7c863861c0 100644 (file)
@@ -11,10 +11,7 @@ import org.springframework.stereotype.Service;
 
 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.*;
 import java.util.concurrent.TimeUnit;
 
 @Service
@@ -373,8 +370,8 @@ public class TreasuryServiceImpl extends DataServiceImpl<Treasury> implements Tr
     }
 
     @Override
-    public List<Treasury> getByHumanIds(String[] ids) {
-        List<Treasury> result = new ArrayList<>();
+    public Set<Treasury> getByHumanIds(String[] ids) {
+        Set<Treasury> result = new HashSet<>();
 
         for (String i : ids) {
             result.add(getByHumanId(i));
index bde12a7df1a64e0421a3b5c7b90897ef0892e8a0..8fb3891426e07cb0a742fcb922152d7e8ebeaabc 100644 (file)
@@ -9,6 +9,8 @@ import org.springframework.security.config.annotation.authentication.builders.Au
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 
 import static hu.user.lis.ui.view.IndexViewModel.NAVIGATION;
 
@@ -17,11 +19,11 @@ import static hu.user.lis.ui.view.IndexViewModel.NAVIGATION;
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
     public static final String ZUL_FILES = "/zkau/web/**/*.zul";
-
-    public static final String[] ZK_RESOURCES = {"/zkau/web/**/js/**", "/zkau/web/**/zul/css/**", "/zkau/web/**/img/**"};
-
     // allow desktop cleanup after logout or when reloading login page
     public static final String REMOVE_DESKTOP_REGEX = "/zkau\\?dtid=.*&cmd_0=rmDesktop&.*";
+
+
+    public static final String[] ZK_RESOURCES = {"/zkau/web/**/js/**", "/zkau/web/**/zul/css/**", "/zkau/web/**/img/**", "/zkau/web/**/static/**"};
     @Autowired
     LocalAuthProvider localAuthProvider;
 
@@ -37,14 +39,19 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers(HttpMethod.GET, ZK_RESOURCES).permitAll() // allow zk resources
                 .regexMatchers(HttpMethod.GET, REMOVE_DESKTOP_REGEX).permitAll() // allow desktop cleanup
                 .requestMatchers(req -> "rmDesktop".equals(req.getParameter("cmd_0"))).permitAll() // allow desktop cleanup from ZATS
-                .mvcMatchers("/", "/login", "/logout").permitAll()
+                .mvcMatchers("/", "/login", "/logout", "/api/**").permitAll()
                 //mvcMatchers(navigation).hasRole("USER")
                 .anyRequest().authenticated()
                 .and()
                 .formLogin()
                 .loginPage("/login").defaultSuccessUrl("/partners")
                 .and()
-                .logout().logoutUrl("/logout").logoutSuccessUrl("/");
+                .logout().logoutUrl("/logout").logoutSuccessUrl("/")
+                .and()
+                .exceptionHandling()
+                .defaultAuthenticationEntryPointFor(
+                        new Http403ForbiddenEntryPoint(),
+                        new AntPathRequestMatcher("/zkau", "POST"));
     }
 
     @Autowired
index 88b44f820cc31b38524c7e0b6e8088101a6cab26..75b10f8bb59bc0f22c489e321f6ace82dd5750da 100644 (file)
@@ -1,7 +1,7 @@
 package hu.user.lis.ui.converter;
 
 import hu.user.lis.db.ProjectStatus;
-import hu.user.lis.services.data.ProjectStatusService;
+import hu.user.lis.db.repository.ProjectStatusRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.zkoss.bind.BindContext;
@@ -15,7 +15,7 @@ import java.util.Objects;
 @Component
 public class ProjectStatusConverter implements Converter<Object, ProjectStatus, Selectbox> {
     @Autowired
-    ProjectStatusService projectStatusService;
+    ProjectStatusRepository projectStatusRepository;
 
     @Override
     public Object coerceToUi(ProjectStatus projectStatus, Selectbox box, BindContext bindContext) {
@@ -35,6 +35,6 @@ public class ProjectStatusConverter implements Converter<Object, ProjectStatus,
 
     @Override
     public ProjectStatus coerceToBean(Object order, Selectbox bandbox, BindContext bindContext) {
-        return projectStatusService.getAll().get((Integer) order);
+        return projectStatusRepository.findByOrder((Integer) order + 1);
     }
 }
\ No newline at end of file
index 2704ac1b59ec45bfb87b3a5e49cb0a00f020acab..2e151140bedbe7eaabf1586b223a09f8beb8174a 100644 (file)
@@ -17,7 +17,7 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
     public static final String NATURAL = "natural";
     public static final String ASCENDING = "ascending";
     public static final String DESCENDING = "descending";
-    private int cacheSize = 100;
+    private int CACHE_SIZE = 100;
     private int cacheStart;
     private int cacheEnd;
     private int resultSetSize = -1;
@@ -83,14 +83,12 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
         return this.resultSetSize;
     }
 
-//    private void loadCache(int forIndex) {
+//    protected void loadCache(int forIndex) {
 //        try {
-//            int halfSize = this.cacheSize / 2;
-//            int rowLimit = this.cacheSize; // 200
+//            int halfSize = this.CACHE_SIZE / 2;
+//            int rowLimit = this.CACHE_SIZE;
 //            int startPos = 0;
-//            if ((forIndex - halfSize) > 0) { // forIndex=60 startPos=0
-//                // cache=0-200, forIndex=150
-//                // startPos=50 cache=50-250
+//            if ((forIndex - halfSize) > 0) {
 //                startPos = (forIndex - halfSize);
 //            }
 //
@@ -103,21 +101,19 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
 //                log.info("Result item count is {}", resultSetSize);
 //            }
 //
-//            log.info("Query result from {} to {}", startPos, endPos);
-//
 //            int limit = endPos - startPos;
-//            int page = (int) Math.ceil(this.resultSetSize / limit);
+//
+//            // (int) Math.ceil(this.resultSetSize / limit);
+//            int page = forIndex == 0 ? 0 : (int) Math.ceil(limit / forIndex);
+//            log.info("Query result from {} to {} for item {} | page {} pageSize {}", startPos, endPos, forIndex, page, limit);
 //            List<T> resList = getResultSet(page, limit, sortComparator);
 //
 //            if (resList != null) {
 //                log.info("Got {} records", resList.size());
 //                for (int c = 0; c < resList.size(); c++) {
 //                    cache.put(startPos + c, resList.get(c));
-//                    // logger.debug("CachedListMode.cached idx: " +
-//                    // (startPos + c));
 //                }
 //            }
-//            // logger.debug("CachedListMode.cacheSize: " + cache.size());
 //
 //            cacheStart = startPos + 1;
 //            cacheEnd = cacheStart + (cache.size() == 0 ? 0 : (cache.size() - 1));
@@ -126,45 +122,26 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
 //        }
 //    }
 
-    private void loadCache(int forIndex) {
-        try {
-            int halfSize = this.cacheSize / 2;
-            int rowLimit = this.cacheSize; // 200
-            int startPos = 0;
-            if ((forIndex - halfSize) > 0) { // forIndex=60 startPos=0
-                // cache=0-200, forIndex=150
-                // startPos=50 cache=50-250
-                startPos = (forIndex - halfSize);
-            }
-
-            int endPos = (startPos + rowLimit);
-            endPos = ((this.resultSetSize < 0) || (endPos <= this.resultSetSize)) ? endPos : this.resultSetSize;
-
 
+    protected void loadCache(int forIndex) {
+        try {
+            int page = forIndex == 0 ? 0 : (int) Math.ceil(forIndex / CACHE_SIZE);
+            log.info("{} query result for item {} | page {} pageSize {}", getClass().getSimpleName(), forIndex, page, CACHE_SIZE);
             if (this.resultSetSize < 0) {
                 this.resultSetSize = getResultSetCount();
-                log.info("Result item count is {}", resultSetSize);
+                log.info("Result item total count is {}", resultSetSize);
             }
-
-            int limit = endPos - startPos;
-
-            // (int) Math.ceil(this.resultSetSize / limit);
-            int page = forIndex == 0 ? 0 : (int) Math.ceil(limit / forIndex);
-            log.info("Query result from {} to {} | page {} pageSize {}", startPos, endPos, page, limit);
-            List<T> resList = getResultSet(page, limit, sortComparator);
+            List<T> resList = getResultSet(page, CACHE_SIZE, sortComparator);
 
             if (resList != null) {
                 log.info("Got {} records", resList.size());
+                cacheStart = forIndex;
                 for (int c = 0; c < resList.size(); c++) {
-                    cache.put(startPos + c, resList.get(c));
-                    // logger.debug("CachedListMode.cached idx: " +
-                    // (startPos + c));
+                    cache.put(forIndex + c, resList.get(c));
+                    cacheEnd++;
                 }
             }
-            // logger.debug("CachedListMode.cacheSize: " + cache.size());
 
-            cacheStart = startPos + 1;
-            cacheEnd = cacheStart + (cache.size() == 0 ? 0 : (cache.size() - 1));
         } catch (Exception e) {
             log.error("", e);
         }
@@ -187,7 +164,7 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
     @Override
     public void sort(Comparator<T> cmpr, boolean ascending) {
         sortComparator = (FieldComparator) cmpr;
-        log.info("Sort {} {}", sortComparator.getOrderBy(), ascending);
+//        log.info("Sort {} {}", sortComparator.getOrderBy(), ascending);
         reset();
     }
 }
index 632204f014aa680dab0a0df35f6eed6f558cfb44..0fc115371226055f61e1e6cbef1576b8fac16f0b 100644 (file)
@@ -21,7 +21,9 @@ public abstract class CachedSpringDataModel<T> extends CachedDataModel<T> {
             Sort.Direction direction = sortComparator.isAscending() ? Sort.Direction.ASC : Sort.Direction.DESC;
             pageable = PageRequest.of(page, pageSize, Sort.by(direction, orderBy));
         }
+        log.info("{} {}", getClass().getSimpleName(), pageable);
         return pageable;
     }
+
 }
 
index 1d2deb573a27fa732e981d741dd3637027501634..e674fd5916bc83ec4f0dd6277c1e54fe66637b2e 100644 (file)
@@ -20,21 +20,21 @@ public class IncomeMarginsDataModel extends ArrayList<IncomeMargin> {
     public void recalculate(Project project) {
         clear();
         Map<Currency, Double> balances = new HashMap<>();
-        List<Invoice> outgoingInvoices = project.getOutgoingInvoices();
+        Set<Invoice> outgoingInvoices = project.getOutgoingInvoices();
         if (Objects.nonNull(outgoingInvoices)) {
             for (Invoice invoice : outgoingInvoices) {
                 addBalance(balances, invoice.getCurrency(), invoice.getNetAmount());
             }
         }
 
-        List<Invoice> incomingInvoices = project.getIncomingInvoices();
+        Set<Invoice> incomingInvoices = project.getIncomingInvoices();
         if (Objects.nonNull(incomingInvoices)) {
             for (Invoice invoice : incomingInvoices) {
                 substractBalance(balances, invoice.getCurrency(), invoice.getNetAmount());
             }
         }
 
-        List<Treasury> treasuries = project.getTreasuries();
+        Set<Treasury> treasuries = project.getTreasuries();
         if (Objects.nonNull(treasuries)) {
             for (Treasury treasury : treasuries) {
                 substractBalance(balances, treasury.getSellCurrency(), treasury.getSellAmount());
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java
new file mode 100644 (file)
index 0000000..53cbd05
--- /dev/null
@@ -0,0 +1,31 @@
+package hu.user.lis.ui.data;
+
+import hu.user.lis.db.Invoice;
+import hu.user.lis.db.Project;
+import hu.user.lis.db.repository.InvoiceRepository;
+import hu.user.lis.services.data.InvoiceService;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.persistence.EntityExistsException;
+
+@Component
+@Log4j2
+public class InvoiceDataModel {
+
+    @Autowired
+    InvoiceService invoiceService;
+    @Autowired
+    InvoiceRepository invoiceRepository;
+
+    public Invoice copy(Invoice entity) {
+        return invoiceRepository.findById(entity.getId()).orElseThrow(EntityExistsException::new);
+    }
+
+    public Invoice createNew(Project formDocument) {
+        Invoice result = invoiceService.createNew();
+        result.setProject(formDocument);
+        return result;
+    }
+}
index 689b750dcbeb40b401c15a8797ece9347aa4d152..8149566d482968334c379428e54b1664d8bb3cd6 100644 (file)
@@ -22,28 +22,28 @@ public class PartnerSelectorDataModel extends CachedSpringDataModel<Partner> {
     @Autowired
     PartnerRepository partnerRepository;
 
-    private String partialName;
+    private String partialSearch;
 
     @Override
     public List<Partner> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
         Pageable pageable = createPageable(page, pageSize, sortComparator);
-        List<Partner> result = StringUtils.isBlank(partialName) ? partnerRepository.findAll() :
-                partnerRepository.search(partialName, partialName, partialName, true, false, pageable);
+        List<Partner> result = StringUtils.isBlank(partialSearch) ? partnerRepository.findAll() :
+                partnerRepository.search(partialSearch, true, false, pageable);
         return result;
     }
 
 
     @Override
     public int getResultSetCount() {
-        int result = StringUtils.isBlank(partialName) ?
+        int result = StringUtils.isBlank(partialSearch) ?
                 (int) partnerRepository.count() :
-                (int) partnerRepository.count(partialName, partialName, partialName, true, false);
+                (int) partnerRepository.count(partialSearch, true, false);
         return result > SEARCH_LIMIT ? SEARCH_LIMIT : result;
     }
 
     public void search(String partialName) {
         log.info("Searching partner using filter {}", partialName);
-        this.partialName = partialName;
+        this.partialSearch = partialName;
         super.reset();
     }
 }
index 23b3e2ca385097e81781be79a445f18fa90ddc15..c5f62c3ce1e06988b40b9fdcfd8c5936cbb43307 100644 (file)
@@ -23,11 +23,7 @@ public class PartnersDataModel extends CachedSpringDataModel<Partner> {
     @Autowired
     PartnerService partnerService;
 
-    private String partialName;
-
-    private String partialAddress;
-
-    private String partialVatNr;
+    private String partialSearch;
 
     private boolean listAll;
 
@@ -40,24 +36,22 @@ public class PartnersDataModel extends CachedSpringDataModel<Partner> {
     public List<Partner> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
         Pageable pageable = createPageable(page, pageSize, sortComparator);
         List<Partner> result = listAll ? partnerRepository.findAll() :
-                partnerRepository.search(partialName, partialVatNr, partialAddress, filterShowActive, filterShowInActive, pageable);
+                partnerRepository.search(partialSearch, filterShowActive, filterShowInActive, pageable);
         return result;
     }
 
     @Override
     public int getResultSetCount() {
         long result = listAll ? partnerRepository.count() :
-                partnerRepository.count(partialName, partialVatNr, partialAddress, filterShowActive, filterShowInActive);
+                partnerRepository.count(partialSearch, filterShowActive, filterShowInActive);
         return (int) result;
     }
 
-    public void search(String partialName, String partialVatNr, String partialAddress) {
-        log.info("Searching partner using filters: name LIKE {}, VAT number LIKE {}, Address LIKE {}",
-                partialName, partialVatNr, partialAddress);
+    public void search(String partialSearch) {
+        log.info("Searching partner using filters: name or VAT number or Address LIKE {}",
+                partialSearch);
         listAll = false;
-        this.partialName = partialName;
-        this.partialVatNr = partialVatNr;
-        this.partialAddress = partialAddress;
+        this.partialSearch = partialSearch;
         super.reset();
     }
 
index b9498e7a39de5ecd27794925e029f7126e4419da..afb8a1cd288c7e6c0da15e013568b015169fec11 100644 (file)
@@ -2,48 +2,27 @@ package hu.user.lis.ui.data;
 
 import hu.user.lis.db.ProjectAssociate;
 import hu.user.lis.db.repository.ProjectAssociateRepository;
-import hu.user.lis.services.data.ProjectAssociateService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.ConfigurableBeanFactory;
-import org.springframework.context.annotation.Scope;
-import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Component;
-import org.zkoss.zul.FieldComparator;
 
 import java.util.List;
+import java.util.Objects;
 
 @Component
 @Log4j2
-@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
-public class ProjectAssociatesDataModel extends CachedSpringDataModel<ProjectAssociate> {
+public class ProjectAssociatesDataModel {
 
     @Autowired
     ProjectAssociateRepository projectAssociateRepository;
 
-    @Autowired
-    ProjectAssociateService projectAssociateService;
-
-    private Long projectId;
-
-
-    @Override
-    public List<ProjectAssociate> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
-        Pageable pageable = createPageable(page, pageSize, sortComparator);
-        List<ProjectAssociate> result = projectAssociateRepository.findAllByProjectId(projectId, pageable).getContent();
+    public List<ProjectAssociate> search(Long projectId) {
+        List<ProjectAssociate> result = null;
+        if (Objects.nonNull(projectId)) {
+            log.info("Searching project associate using filter: projectId LIKE {}", projectId);
+            result = projectAssociateRepository.findAllByProjectId(projectId);
+        }
         return result;
     }
 
-    @Override
-    public int getResultSetCount() {
-        long result = projectAssociateRepository.countByProjectId(projectId);
-        return (int) result;
-    }
-
-    public void search(Long projectId) {
-        log.info("Searching project associate using filter: projectId LIKE {}", projectId);
-        this.projectId = projectId;
-        super.reset();
-    }
-
 }
index f1ce273d7ea19a08ba7b96776c38ab2ba9ccabd5..abf2ce680e4fdc2378990055f7f51f02498230e7 100644 (file)
@@ -86,4 +86,8 @@ public class ProjectStatusDataModel extends CachedSpringDataModel<ProjectStatus>
     public void save(ProjectStatus entity) {
         projectStatusRepository.save(entity);
     }
+
+    public ProjectStatus getDefault() {
+        return projectStatusRepository.findByOrder(1);
+    }
 }
index 8f6a15bedf4ab2b7106d3145cac91d500679d3a1..4869f7869696258fbcfacaf5a6ee6334f2865344 100644 (file)
@@ -1,8 +1,8 @@
 package hu.user.lis.ui.data;
 
 import hu.user.lis.db.Project;
+import hu.user.lis.db.ProjectStatus;
 import hu.user.lis.db.repository.ProjectRepository;
-import hu.user.lis.services.data.ProjectService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@@ -11,7 +11,13 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Component;
 import org.zkoss.zul.FieldComparator;
 
+import javax.persistence.EntityNotFoundException;
+import java.lang.reflect.Field;
+import java.text.DecimalFormat;
+import java.time.Year;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 
 @Component
 @Log4j2
@@ -21,7 +27,7 @@ public class ProjectsDataModel extends CachedSpringDataModel<Project> {
     ProjectRepository projectRepository;
 
     @Autowired
-    ProjectService projectService;
+    ProjectStatusDataModel projectStatusDataModel;
 
     private String partialName;
 
@@ -70,18 +76,54 @@ public class ProjectsDataModel extends CachedSpringDataModel<Project> {
     }
 
     public Project createNew() {
-        return projectService.createNew();
+        String yearSearch = String.format("%s-%%", Year.now().getValue());
+        Project lastInYear = projectRepository.findFirstByHumanIdLikeOrderByHumanIdDesc(yearSearch);
+        int sortOrder = Integer.parseInt(lastInYear.getHumanId().split("-")[1]);
+        DecimalFormat decFormat = new DecimalFormat("0000");
+        String humanId = String.format("%s-%s", Year.now().getValue(), decFormat.format(++sortOrder));
+        ProjectStatus projectStatus = projectStatusDataModel.getDefault();
+        return Project.builder()
+                .projectStatus(projectStatus)
+                .humanId(humanId)
+                .incomingInvoices(new HashSet<>())
+                .outgoingInvoices(new HashSet<>())
+                .treasuries(new HashSet<>())
+                .active(true)
+                .build();
     }
 
     public void addNew(Project entity) {
         projectRepository.save(entity);
     }
 
-    public Project copy(Project selectedEntity) {
-        return projectService.copy(selectedEntity);
+    public Project copy(Project entity) {
+        return projectRepository.findById(entity.getId()).orElseThrow(EntityNotFoundException::new);
+    }
+
+    public Project copy(Project entity, String property, Object value) {
+        Project result = copy(entity);
+        setPropertyValue(result, property, value);
+        return result;
+    }
+
+    public void setPropertyValue(Project entity, String property, Object value) {
+        if (Objects.isNull(property)) {
+            return;
+        }
+        try {
+            Field field = entity.getClass().getDeclaredField(property);
+            field.setAccessible(true);
+            field.set(entity, value);
+        } catch (Exception e) {
+            log.catching(e);
+        }
     }
 
     public Project save(Project selectedEntity) {
         return projectRepository.save(selectedEntity);
     }
+
+    public Project getById(Long id) {
+        return projectRepository.findById(id).orElseThrow(EntityNotFoundException::new);
+    }
 }
index 62e8f863de73a541a12e01e031148b17d91b00c6..9476356f0a464ea08e6967b0d12b8f92852c3808 100644 (file)
@@ -19,6 +19,7 @@ import javax.persistence.EntityNotFoundException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Component
 @Log4j2
@@ -41,6 +42,9 @@ public class ServiceRecordsDataModel extends CachedSpringDataModel<ServiceRecord
 
     @Override
     public List<ServiceRecord> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
+        if (groupByAssociate) {
+            return getGroupedServiceRecords().values().stream().collect(Collectors.toList());
+        }
         Pageable pageable = createPageable(page, pageSize, sortComparator);
         List<ServiceRecord> result = listAll ? serviceRecordRepository.findAll(pageable).toList() :
                 serviceRecordRepository.search(filterProjectId, filterAssociateId, pageable);
@@ -56,7 +60,7 @@ public class ServiceRecordsDataModel extends CachedSpringDataModel<ServiceRecord
                 serviceRecord.setCost(serviceRecord.getCost() + s.getCost());
                 serviceRecord.setWorkHours(serviceRecord.getWorkHours() + s.getWorkHours());
             } else {
-                ServiceRecord serviceRecord = serviceRecordService.copy(s);
+                ServiceRecord serviceRecord = serviceRecordRepository.findById(s.getId()).orElseThrow(EntityNotFoundException::new);
                 serviceRecord.setWorkDay(null);
                 grouped.put(serviceRecord.getAssociate().getId(), serviceRecord);
             }
@@ -66,6 +70,9 @@ public class ServiceRecordsDataModel extends CachedSpringDataModel<ServiceRecord
 
     @Override
     public int getResultSetCount() {
+        if (groupByAssociate) {
+            return getGroupedServiceRecords().size();
+        }
         long result = listAll ? serviceRecordRepository.count() :
                 serviceRecordRepository.count(filterProjectId, filterAssociateId);
         return (int) result;
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/TreasuryDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/TreasuryDataModel.java
new file mode 100644 (file)
index 0000000..b232010
--- /dev/null
@@ -0,0 +1,32 @@
+package hu.user.lis.ui.data;
+
+import hu.user.lis.db.Project;
+import hu.user.lis.db.Treasury;
+import hu.user.lis.db.repository.TreasuryRepository;
+import hu.user.lis.services.data.TreasuryService;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.persistence.EntityExistsException;
+
+@Component
+@Log4j2
+public class TreasuryDataModel {
+
+    @Autowired
+    TreasuryService treasuryService;
+
+    @Autowired
+    TreasuryRepository treasuryRepository;
+
+    public Treasury copy(Treasury entity) {
+        return treasuryRepository.findById(entity.getId()).orElseThrow(EntityExistsException::new);
+    }
+
+    public Treasury createNew(Project formDocument) {
+        Treasury result = treasuryService.createNew();
+        result.setProject(formDocument);
+        return result;
+    }
+}
index 6cbf94b016c33553bea6021115ef4ebddc856440..1a7dcbb5e2c4a5ee8d186aab8fbe0a29349ee0b5 100644 (file)
@@ -44,11 +44,10 @@ public class PartnerEditorModel extends AbstractValidator {
 
     @Command
     public void onCloseWindow(@BindingParam("target") Window target, @BindingParam("select") boolean select) {
-        if (select && formInvalid) {
-            return;
+        if (select && !formInvalid) {
+            Event closeEvent = new Event("onClose", target, select ? formDocument : null);
+            Events.postEvent(closeEvent);
         }
-        Event closeEvent = new Event("onClose", target, select ? formDocument : null);
-        Events.postEvent(closeEvent);
     }
 
     @Override
index 02820d561d99acead9508f3293cf1c677f012d7e..d231e4d782e2a2f783e99f800d87824a36d01980 100644 (file)
@@ -2,11 +2,9 @@ package hu.user.lis.ui.editor;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.google.common.collect.ImmutableMap;
-import hu.user.lis.db.Associate;
-import hu.user.lis.db.Invoice;
-import hu.user.lis.db.Project;
-import hu.user.lis.db.Treasury;
-import hu.user.lis.services.data.*;
+import hu.user.lis.db.*;
+import hu.user.lis.services.data.ProjectService;
+import hu.user.lis.services.data.ServiceRecordService;
 import hu.user.lis.ui.Constants;
 import hu.user.lis.ui.converter.ProjectStatusConverter;
 import hu.user.lis.ui.data.*;
@@ -44,41 +42,62 @@ import java.util.*;
 public class ProjectEditorModel extends AbstractValidator implements EventListener {
     @WireVariable
     AssociatesDataModel associatesDataModel;
-    @WireVariable
-    ProjectAssociateService projectAssociateServiceImpl;
+
     @WireVariable
     ServiceRecordService serviceRecordServiceImpl;
+
     @WireVariable
     SessionSettings sessionSettings;
-    private Project formDocument;
-    private Project origDocument;
-    private Map<Associate, Boolean> origAssociates;
-    private Map<Associate, Boolean> formAssociates;
+
+    @WireVariable
+    private ProjectsDataModel projectsDataModel;
+
     @WireVariable
     private PartnerSelectorDataModel partnerSelectorDataModel;
+
     @WireVariable
-    private InvoiceService invoiceServiceImpl;
+    private InvoiceDataModel invoiceDataModel;
+
     @WireVariable
-    private ProjectService projectServiceImpl;
+    private TreasuryDataModel treasuryDataModel;
+
     @WireVariable
-    private TreasuryService treasuryServiceImpl;
+    private ProjectService projectServiceImpl;
+
     @WireVariable
     private ServiceRecordsDataModel serviceRecordsDataModel;
+
     @WireVariable
     private ProjectStatusDataModel projectStatusDataModel;
-    @Getter
+
     @WireVariable
-    private ProjectStatusService projectStatusServiceImpl;
+    private IncomeMarginsDataModel incomeMarginsDataModel;
+
     @WireVariable
-    private ProjectStatusConverter projectStatusConverter;
+    private ProjectAssociatesDataModel projectAssociatesDataModel;
+
     @WireVariable
-    private IncomeMarginsDataModel incomeMarginsDataModel;
+    private ProjectStatusConverter projectStatusConverter;
+
     @WireVariable
     private EventBus eventBus;
+
+    private Project formDocument;
+
+    private Project origDocument;
+
+    private Map<Long, Boolean> origAssociates;
+
+    private Map<Long, Boolean> formAssociates;
+
     private boolean formInvalid = true;
+
     private Invoice selectedIncomingInvoice;
+
     private Invoice selectedOutgoingInvoice;
+
     private Treasury selectedTreasury;
+
     private String partialAssociateName;
 
     @Init
@@ -93,31 +112,21 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         if (Constants.SET_PROJECT_EDITOR_DATA.equals(evt.getName())) {
             log.info("Got event {}", Constants.SET_PROJECT_EDITOR_DATA);
             Object data = evt.getData();
-            if (data instanceof Map) {
-                Map<String, Object> mapData = (Map<String, Object>) evt.getData();
-                origDocument = (Project) mapData.get("origDocument");
-                formDocument = (Project) mapData.get("formDocument");
-            }
-
-            if (data instanceof String) {
-                String id = (String) data;
-                log.info("Loading entity {} to editor", id);
-                origDocument = projectServiceImpl.getById(id);
-                formDocument = projectServiceImpl.copy(origDocument);
-            }
-
             if (Objects.isNull(data)) {
-                formDocument = projectServiceImpl.createNew();
+                formDocument = projectsDataModel.createNew();
                 log.info("Loading new entity {} to editor", formDocument.getId());
+            } else {
+                Long id = (Long) data;
+                Clients.evalJavaScript(String.format("pushNav('/project/%d')", id));
+                log.info("Loading entity {} to editor", id);
+                formDocument = projectsDataModel.getById(id);
+                origDocument = projectsDataModel.getById(id);
             }
 
-            if (Objects.nonNull(formDocument)) {
-                Clients.evalJavaScript(String.format("pushNav('/project/%s')", formDocument.getId()));
-                serviceRecordsDataModel.search(formDocument, true);
-                associatesDataModel.listAll();
-                incomeMarginsDataModel.recalculate(formDocument);
-                BindUtils.postNotifyChange(this, "formDocument");
-            }
+            serviceRecordsDataModel.search(formDocument, true);
+            initAssociates();
+            incomeMarginsDataModel.recalculate(formDocument);
+            BindUtils.postNotifyChange(this, "formDocument");
         }
     }
 
@@ -137,20 +146,10 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
 
     @Command
     public void onEndEdit(@BindingParam("target") Window target, @BindingParam("select") boolean select) {
-        if (select && formInvalid) {
-            return;
-        }
-        Map<String, Project> args = null;
-        if (select) {
-            if (Objects.isNull(origDocument)) {
-                args = ImmutableMap.of("formDocument", formDocument);
-            } else {
-                args = ImmutableMap.of("origDocument", origDocument, "formDocument", formDocument);
-            }
-            projectAssociateServiceImpl.update(formDocument, formAssociates);
+        if (select && !formInvalid) {
+            projectsDataModel.save(formDocument);
+            eventBus.showProjectsList(ImmutableMap.of("formDocument", formDocument));
         }
-
-        eventBus.showProjectsList(args);
     }
 
     @Command
@@ -190,17 +189,35 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         Object value = ctx.getProperty().getValue();
         log.info("Validating caused by {} {} {}", target.getId(), property, value);
         try {
-            Project newData = projectServiceImpl.copy(formDocument, property, value);
+
+            Project newData = getEntityToValidate(property, value);
             validate(newData);
         } catch (Exception e) {
             log.catching(e);
         }
     }
 
+    private Project getEntityToValidate() {
+        return getEntityToValidate(null, null);
+    }
+
+    private Project getEntityToValidate(String property, Object value) {
+        Project newData;
+        if (Objects.isNull(origDocument)) {
+            if (Objects.nonNull(property)) {
+                projectsDataModel.setPropertyValue(formDocument, property, value);
+            }
+            newData = formDocument;
+        } else {
+            newData = projectsDataModel.copy(formDocument, property, value);
+        }
+        return newData;
+    }
+
     private void validate(Project newData) {
         incomeMarginsDataModel.recalculate(formDocument);
         updateFormInvalid(false);
-        if (!Objects.isNull(origDocument)) {
+        if (Objects.nonNull(origDocument)) {
             boolean invalid = projectServiceImpl.toString(origDocument).equals(projectServiceImpl.toString(newData))
                     && !isAssociatesChanged();
             updateFormInvalid(invalid);
@@ -219,7 +236,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     @Command
     public void onAddIncoming() {
         String page = "~./incoming-invoice-editor.zul";
-        Invoice editEntity = invoiceServiceImpl.createNew();
+        Invoice editEntity = invoiceDataModel.createNew(formDocument);
         editEntity.setIncome(true);
         Window editorWindow = (Window) Executions.createComponents(page, null,
                 Collections.singletonMap("formDocument", editEntity));
@@ -229,7 +246,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
                 selectedIncomingInvoice = editEntity;
                 BindUtils.postNotifyChange(this, "selectedIncomingInvoice");
                 BindUtils.postNotifyChange(this.formDocument, "incomingInvoices");
-                validate(projectServiceImpl.copy(formDocument));
+                validate(getEntityToValidate());
             }
         });
         editorWindow.doModal();
@@ -239,7 +256,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     @Command
     public void onEditIncoming() throws JsonProcessingException {
         String page = "~./incoming-invoice-editor.zul";
-        Invoice editEntity = invoiceServiceImpl.copy(selectedIncomingInvoice);
+        Invoice editEntity = invoiceDataModel.copy(selectedIncomingInvoice);
         Map<String, Object> arg = new HashMap<>();
         arg.put("origDocument", selectedIncomingInvoice);
         arg.put("formDocument", editEntity);
@@ -247,14 +264,13 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         editorWindow.addEventListener("onClose", e -> {
             if (e.getData() != null) {
                 Invoice modifiedEntity = (Invoice) e.getData();
-                List<Invoice> incomingInvoices = formDocument.getIncomingInvoices();
-                int index = incomingInvoices.indexOf(selectedIncomingInvoice);
+                Set<Invoice> incomingInvoices = formDocument.getIncomingInvoices();
                 incomingInvoices.remove(selectedIncomingInvoice);
-                incomingInvoices.add(index, modifiedEntity);
+                incomingInvoices.add(modifiedEntity);
                 selectedIncomingInvoice = modifiedEntity;
                 BindUtils.postNotifyChange(this, "selectedIncomingInvoice");
                 BindUtils.postNotifyChange(this.formDocument, "incomingInvoices");
-                validate(projectServiceImpl.copy(formDocument));
+                validate(getEntityToValidate());
             }
         });
         editorWindow.doModal();
@@ -270,13 +286,12 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         selectedIncomingInvoice = null;
         BindUtils.postNotifyChange(this, "selectedIncomingInvoice");
         BindUtils.postNotifyChange(this.formDocument, "incomingInvoices");
-        validate(projectServiceImpl.copy(formDocument));
     }
 
     @Command
     public void onAddOutgoing() {
         String page = "~./outgoing-invoice-editor.zul";
-        Invoice editEntity = invoiceServiceImpl.createNew();
+        Invoice editEntity = invoiceDataModel.createNew(formDocument);
         Window editorWindow = (Window) Executions.createComponents(page, null,
                 Collections.singletonMap("formDocument", editEntity));
         editorWindow.addEventListener("onClose", e -> {
@@ -285,7 +300,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
                 selectedOutgoingInvoice = editEntity;
                 BindUtils.postNotifyChange(this, "selectedOutgoingInvoice");
                 BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices");
-                validate(projectServiceImpl.copy(formDocument));
+                validate(getEntityToValidate());
             }
         });
         editorWindow.doModal();
@@ -295,7 +310,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     @Command
     public void onEditOutgoing() throws JsonProcessingException {
         String page = "~./outgoing-invoice-editor.zul";
-        Invoice editEntity = invoiceServiceImpl.copy(selectedOutgoingInvoice);
+        Invoice editEntity = invoiceDataModel.copy(selectedOutgoingInvoice);
         Map<String, Object> arg = new HashMap<>();
         arg.put("origDocument", selectedOutgoingInvoice);
         arg.put("formDocument", editEntity);
@@ -303,14 +318,13 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         editorWindow.addEventListener("onClose", e -> {
             if (e.getData() != null) {
                 Invoice modifiedEntity = (Invoice) e.getData();
-                List<Invoice> outgoingInvoices = formDocument.getOutgoingInvoices();
-                int index = outgoingInvoices.indexOf(selectedOutgoingInvoice);
+                Set<Invoice> outgoingInvoices = formDocument.getOutgoingInvoices();
                 outgoingInvoices.remove(selectedOutgoingInvoice);
-                outgoingInvoices.add(index, modifiedEntity);
+                outgoingInvoices.add(modifiedEntity);
                 selectedOutgoingInvoice = modifiedEntity;
                 BindUtils.postNotifyChange(this, "selectedOutgoingInvoice");
                 BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices");
-                validate(projectServiceImpl.copy(formDocument));
+                validate(getEntityToValidate());
             }
         });
         editorWindow.doModal();
@@ -326,13 +340,12 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         selectedOutgoingInvoice = null;
         BindUtils.postNotifyChange(this, "selectedOutgoingInvoice");
         BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices");
-        validate(projectServiceImpl.copy(formDocument));
     }
 
     @Command
     public void onAddTreasury() {
         String page = "~./treasury-editor.zul";
-        Treasury editEntity = treasuryServiceImpl.createNew();
+        Treasury editEntity = treasuryDataModel.createNew(formDocument);
         Window editorWindow = (Window) Executions.createComponents(page, null,
                 Collections.singletonMap("formDocument", editEntity));
         editorWindow.addEventListener("onClose", e -> {
@@ -341,7 +354,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
                 selectedTreasury = editEntity;
                 BindUtils.postNotifyChange(this, "selectedTreasury");
                 BindUtils.postNotifyChange(this.formDocument, "treasuries");
-                validate(projectServiceImpl.copy(formDocument));
+                validate(getEntityToValidate());
             }
         });
         editorWindow.doModal();
@@ -351,20 +364,19 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     @Command
     public void onEditTreasury() {
         String page = "~./treasury-editor.zul";
-        Treasury editEntity = treasuryServiceImpl.copy(selectedTreasury);
+        Treasury editEntity = treasuryDataModel.copy(selectedTreasury);
         Map<String, Object> arg = ImmutableMap.of("origDocument", selectedTreasury, "formDocument", editEntity);
         Window editorWindow = (Window) Executions.createComponents(page, null, arg);
         editorWindow.addEventListener("onClose", e -> {
             if (e.getData() != null) {
                 Treasury modifiedEntity = (Treasury) e.getData();
-                List<Treasury> treasuries = formDocument.getTreasuries();
-                int index = treasuries.indexOf(selectedTreasury);
+                Set<Treasury> treasuries = formDocument.getTreasuries();
                 treasuries.remove(selectedTreasury);
-                treasuries.add(index, modifiedEntity);
+                treasuries.add(modifiedEntity);
                 selectedTreasury = modifiedEntity;
                 BindUtils.postNotifyChange(this, "selectedTreasury");
                 BindUtils.postNotifyChange(this.formDocument, "treasuries");
-                validate(projectServiceImpl.copy(formDocument));
+                validate(getEntityToValidate());
             }
         });
         editorWindow.doModal();
@@ -380,7 +392,6 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         selectedTreasury = null;
         BindUtils.postNotifyChange(this, "selectedTreasury");
         BindUtils.postNotifyChange(this.formDocument, "treasuries");
-        validate(projectServiceImpl.copy(formDocument));
     }
 
     private void updateFormInvalid(boolean invalid) {
@@ -416,11 +427,20 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     @Command
     @NotifyChange("formAssociates")
     public void onAfterRenderAssociates() {
+    }
+
+    @NotifyChange("formAssociates")
+    private void initAssociates() {
+        associatesDataModel.listAll();
         formAssociates = new HashMap<>();
         origAssociates = new HashMap<>();
+        if (Objects.isNull(formDocument.getId())) {
+            return;
+        }
+        List<ProjectAssociate> projectAssociates = projectAssociatesDataModel.search(formDocument.getId());
         for (int i = 0; i < associatesDataModel.getSize(); i++) {
             Associate associate = associatesDataModel.getElementAt(i);
-            boolean exists = projectAssociateServiceImpl.getAll().stream()
+            boolean exists = projectAssociates.stream()
                     .anyMatch(
                             pa -> pa.getProject().getId().equals(formDocument.getId()) &&
                                     pa.getAssociate().getId().equals(associate.getId())
@@ -428,9 +448,10 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
             if (exists) {
                 log.info("{} is on project {}", associate.getName(), formDocument.getName());
             }
-            formAssociates.put(associate, exists);
-            origAssociates.put(associate, exists);
+            formAssociates.put(associate.getId(), exists);
+            origAssociates.put(associate.getId(), exists);
         }
+        BindUtils.postNotifyChange(this, "formAssociates");
     }
 
     private boolean isAssociatesChanged() {
@@ -441,7 +462,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     @Command
     public void onAssociateChecked() {
         log.info("Associate checked");
-        validate(projectServiceImpl.copy(formDocument));
+        validate(origDocument);
     }
 
 }
index 9e9f041594a6154dbd48a71bfa0d01256cc3c548..21559db8e84c227b4ca2b29c0032ad831dfe2af3 100644 (file)
@@ -43,7 +43,7 @@ public class EventBus {
         getQueue().publish(new Event(Constants.SET_SERVICE_RECORDS_LIST_DATA, null, data));
     }
 
-    public void setProjectEditorData(Object data) {
+    public void setProjectEditorData(Long data) {
         getQueue().publish(new Event(Constants.SET_PROJECT_EDITOR_DATA, null, data));
     }
 
index 108075912afb271fec2d0b3e7fd7b9fccc79fc3e..e9ad059a67a7873987c0ab08f66bd135ea52efb1 100644 (file)
@@ -77,7 +77,7 @@ public class IndexViewModel implements EventListener {
             String id = path.split("/")[2];
             selectPage(PROJECT_EDITOR);
 //            eventBus.setProjectEditorData(Collections.singletonMap("id", id));
-            eventBus.setProjectEditorData(id);
+            eventBus.setProjectEditorData(Long.parseLong(id));
         } else {
             if (NAVIGATION.containsKey(path)) {
                 setPage(NAVIGATION.get(path));
@@ -102,7 +102,7 @@ public class IndexViewModel implements EventListener {
         }
         if (Constants.SHOW_PROJECT_EDITOR.equals(event.getName())) {
             selectPage(PROJECT_EDITOR);
-            eventBus.setProjectEditorData(event.getData());
+            eventBus.setProjectEditorData((Long) event.getData());
         }
         if (Constants.SHOW_PROJECTS_LIST.equals(event.getName())) {
             selectPage(PROJECTS_LIST);
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/LoginViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/LoginViewModel.java
new file mode 100644 (file)
index 0000000..b2075f9
--- /dev/null
@@ -0,0 +1,19 @@
+package hu.user.lis.ui.view;
+
+import lombok.Getter;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.boot.info.BuildProperties;
+import org.zkoss.zk.ui.select.annotation.VariableResolver;
+import org.zkoss.zk.ui.select.annotation.WireVariable;
+
+@Log4j2
+@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
+@Getter
+public class LoginViewModel {
+    @WireVariable
+    BuildProperties buildProperties;
+
+    public LoginViewModel() {
+
+    }
+}
index 2459dd60fd41c76b16e20f8aad0f00cdc7b6760d..bd4dd889629d353763b66edf64ed6128f8c48d41 100644 (file)
@@ -77,8 +77,6 @@ public class ProjectsViewModel extends AsyncBaseModel implements EventListener {
 
     @Command
     public void onAdd() {
-        Project newEntity = projectsDataModel.createNew();
-//        eventBus.showProjectEditor(ImmutableMap.of("formDocument", newEntity));
         eventBus.showProjectEditor(null);
     }
 
@@ -87,9 +85,8 @@ public class ProjectsViewModel extends AsyncBaseModel implements EventListener {
         if (Objects.isNull(selectedProject)) {
             return;
         }
-//        Project editEntity = projectsDataModel.getProjectService().copy(selectedProject);
-//        eventBus.showProjectEditor(ImmutableMap.of("origDocument", selectedProject, "formDocument", editEntity));
-        eventBus.showProjectEditor(selectedProject.getId());
+        Project editEntity = projectsDataModel.copy(selectedProject);
+        eventBus.showProjectEditor(editEntity.getId());
     }
 
     public boolean isFilterShowInActive() {
index 0b7e9273b7ece8308feb781748157a8bb7a558da..68fa6abb3775feacad9be65e6ad6592e53ba31c4 100644 (file)
@@ -15,10 +15,7 @@ import org.zkoss.bind.BindContext;
 import org.zkoss.bind.BindUtils;
 import org.zkoss.bind.annotation.*;
 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.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.zk.ui.util.Clients;
@@ -172,6 +169,12 @@ public class ServiceRecordsViewModel implements EventListener {
         serviceRecordsDataModel.listAll();
     }
 
+    @Command
+    public void onSort(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) {
+        SortEvent evt = (SortEvent) ctx.getTriggerEvent();
+        //evt.stopPropagation();
+    }
+
     @Override
     public void onEvent(Event evt) throws Exception {
         if (Constants.SET_SERVICE_RECORDS_LIST_DATA.equals(evt.getName())) {
index 4bba82db24ecf36e4b8b9218841c03701103bb89..28d7ddd7286ad8cbc575a26aef9cd41eaad6bb5f 100644 (file)
@@ -4,10 +4,8 @@ import hu.user.lis.db.ProjectStatus;
 import hu.user.lis.ui.data.ProjectStatusDataModel;
 import lombok.Getter;
 import lombok.extern.log4j.Log4j2;
-import org.zkoss.bind.BindContext;
+import org.zkoss.bind.annotation.BindingParam;
 import org.zkoss.bind.annotation.Command;
-import org.zkoss.bind.annotation.ContextParam;
-import org.zkoss.bind.annotation.ContextType;
 import org.zkoss.bind.annotation.Init;
 import org.zkoss.zk.ui.select.annotation.VariableResolver;
 import org.zkoss.zk.ui.select.annotation.WireVariable;
@@ -60,14 +58,11 @@ public class SettingsViewModel extends AsyncBaseModel {
     }
 
     @Command
-    public void onActiveChecked(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) {
-//        CheckEvent evt = (CheckEvent) ctx.getTriggerEvent();
-//        ProjectStatus entity = (ProjectStatus) evt.getData();
-//        projectStatusDataModel.save(entity);
+    public void onActiveChecked(@BindingParam("entity") ProjectStatus entity) {
+        projectStatusDataModel.save(entity);
     }
 
     public void setSelectedProjectStatus(ProjectStatus selectedProjectStatus) {
-        log.info("Sekected {}", selectedProjectStatus.getName());
         this.selectedProjectStatus = selectedProjectStatus;
     }
 }
index 861c2fa8eba31e5400327817d4ccf3f296567e56..04e41f19a5a976f22da182027c02e94982bee782 100644 (file)
@@ -5,6 +5,31 @@
         <session-timeout>300</session-timeout>
         <timeout-uri>/timeout</timeout-uri>
     </session-config>
+    <client-config>
+        <error-reload>
+            <device-type>ajax</device-type>
+            <error-code>403</error-code>
+            <reload-uri>/login</reload-uri>
+        </error-reload>
+        <error-reload>
+            <device-type>ajax</device-type>
+            <error-code>410</error-code>
+            <reload-uri>/timeout</reload-uri>
+            <connection-type>server-push</connection-type>
+        </error-reload>
+        <!--        <click-filter-delay>0</click-filter-delay>-->
+        <!--        <debug-js>false</debug-js>-->
+        <!--        <disable-behind-modal>false</disable-behind-modal>-->
+        <!--        <error-reload>-->
+        <!--            <device-type>ajax</device-type>-->
+        <!--            <error-code>301</error-code>-->
+        <!--            <reload-uri></reload-uri>-->
+        <!--        </error-reload>-->
+        <!--        <keep-across-visits>true</keep-across-visits>-->
+        <!--        <processing-prompt-delay>900</processing-prompt-delay>-->
+        <!--        <tooltip-delay>800</tooltip-delay>-->
+        <!--        <resend-delay>9000</resend-delay>-->
+    </client-config>
     <!--    <error-page>-->
     <!--        <exception-type>java.lang.Throwable</exception-type>-->
     <!--        <location>/timeout</location>-->
index 9482f5b2e72fcdcc8d97b700aa86ebe6803ca034..560d21597c10fabcb200de565fc63aeff7123879 100644 (file)
@@ -3,9 +3,9 @@
 <?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <zk>
     <style>
-        <!--        .z-caption-content {-->
-        <!--        width: 100%;-->
-        <!--        }-->
+        .header > .z-caption-content {
+        width: 100%;
+        }
         .z-window-header {
         font-size: 18px;
         font-weight: bolder;
@@ -25,7 +25,7 @@
         }
     </script>
     <window vflex="true" viewModel="@id('vm') @init('hu.user.lis.ui.view.IndexViewModel')">
-        <caption>
+        <caption sclass="header">
             <div style="display: block">
                 <div style="display: inline; float: left">
                     <hlayout valign="middle">
index 2173d92080d222d898ac134f08d178c5650738df..e6a13ee2e24773d16d64ddac3905d8365fa90137 100644 (file)
         display:table;
         margin:auto;
         }
+        .z-row:hover>.z-row-inner,
+        .z-row:hover>.z-cell {
+        background-color: white;
+        }
+        .z-grid-odd > .z-row-inner, .z-grid-odd > .z-cell {
+        background: none repeat scroll 0 0 white;
+        }
     </n:style>
     <n:form action="/login" method="POST">
-        <grid style="margin-top: 200px">
-            <columns>
-                <column width="100px"/>
-                <column width="280px"/>
-            </columns>
-            <rows>
-                <row spans="2" align="center">
+
+        <window viewModel="@id('vm') @init('hu.user.lis.ui.view.LoginViewModel')"
+                style="margin-top: 200px" border="normal">
+            <caption sclass="header">
+                <div style="display: block">
                     <hlayout valign="middle">
-                        <!--                        <image width="24px" height="24px" src="~./static/images/logo.png"/>-->
-                        <label value="SLY-CRM bejelentkezés"/>
-                    </hlayout>
-                </row>
-                <row>
-                    <label value="User"/>
-                    <textbox name="username" value="user"/>
-                </row>
-                <row>
-                    <label value="Password"/>
-                    <textbox type="password" name="password" value="password"/>
-                </row>
-                <row spans="2" align="right">
-                    <hlayout>
-                        <button type="reset" label="Mégsem"/>
-                        <button type="submit" label="Belépés"/>
+                        <image width="24px" height="24px" src="~./static/images/logo.png"/>
+                        <label value="SLY-CRM"/>
+                        <separator orient="vertical"/>
+                        <label style="font-size: 0.8em" value="@load(vm.buildProperties.version)"/>
                     </hlayout>
-                </row>
-            </rows>
-        </grid>
+                </div>
+            </caption>
+            <grid>
+                <columns>
+                    <column width="100px"/>
+                    <column width="300px"/>
+                </columns>
+                <rows>
+                    <row>
+                        <label value="User"/>
+                        <textbox name="username" value="user1" hflex="true"/>
+                    </row>
+                    <row>
+                        <label value="Password"/>
+                        <textbox type="password" name="password" value="password" hflex="true"/>
+                    </row>
+                    <row spans="2" align="right">
+                        <hlayout>
+                            <button type="submit" label="Belépés"/>
+                        </hlayout>
+                    </row>
+                </rows>
+            </grid>
+
+        </window>
     </n:form>
 </zk>
\ No newline at end of file
index 20ce3d9135d64c9670945eef3181ce89e11ce867..95a7efdf4f1b056078e3c207599b582d63cde0f0 100644 (file)
@@ -59,7 +59,7 @@
                                                         <!--                                                                <comboitem label="${each.name}"/>-->
                                                         <!--                                                            </template>-->
                                                         <!--                                                        </combobox>-->
-                                                        <selectbox model="@load(vm.projectStatusServiceImpl.getAll())"
+                                                        <selectbox model="@load(vm.projectStatusDataModel)"
                                                                    width="100%"
                                                                    selectedIndex="@bind(vm.formDocument.projectStatus) @converter(vm.projectStatusConverter) @validator(vm)"
                                                                    forward="onOK=submit.onClick, onCancel=cancel.onClick">
index ae0ddfe4cdb9d4f6465af51b149c848df73e2301..de30d7ae7886476582c49d28326044d5a1d5b9a0 100644 (file)
                          autopaging="true" pagingPosition="top" onSelect="@command('onListSelection')"
                          onDoubleClick="@command('onEdit')">
                     <listhead sizable="true">
-                        <listheader label="Azonosító" align="left"/>
-                        <listheader label="Ügyfél" align="left"/>
-                        <listheader label="Státusz" align="left"/>
-                        <listheader label="Megnevezés" align="left"/>
-                        <listheader label="Kapcsolattartó" align="left"/>
-                        <listheader label="Aktív" align="left"/>
+                        <listheader label="Azonosító" sort="auto(humanId)" align="left"/>
+                        <listheader label="Ügyfél" sort="auto(partner.name)" align="left"/>
+                        <listheader label="Státusz" sort="auto(projectStatus.name)" align="left"/>
+                        <listheader label="Megnevezés" sort="auto(name)" align="left"/>
+                        <listheader label="Kapcsolattartó" sort="auto(contactName)" align="left"/>
+                        <listheader label="Aktív" sort="auto(active)" align="left"/>
                     </listhead>
                     <template name="model">
                         <listitem>
index 44a0dcf1736863b17a5cb4c1edc68c2c2f01d0c0..35c8c1ee8ac0e742b0c2b94d5ea84cbb6a778d19 100644 (file)
                          autopaging="true" mold="paging" pagingPosition="top" onSelect="@command('onListSelection')"
                          onDoubleClick="@command('onEdit')">
                     <listhead sizable="true">
-                        <listheader label="Projekt azonosító" sort="auto(project.humanId)" align="left"/>
+                        <!--
+                        https://www.zkoss.org/wiki/ZK_Component_Reference/Data/Listbox
+                        -->
+                        <listheader label="Projekt azonosító" sort="auto(project.humanId)" align="left"
+                                    sortDirection="ascending"/>
                         <listheader label="Projekt név" sort="auto(project.name)" align="left"/>
                         <listheader label="Partner név" sort="auto(project.partner.name)" align="left"/>
                         <listheader label="Munkatárs" sort="auto(associate.name)" align="left"/>
index ba035a3a9b76d4b7fb7ba1f650f0ec464f8dc81f..7877d77d998496361f3527264c7450a44676cb0b 100644 (file)
@@ -31,7 +31,8 @@
                                 <textbox inplace="true" instant="true" width="100%" value="@bind(each.name)"/>
                             </listcell>
                             <listcell>
-                                <checkbox checked="@bind(each.active)" onCheck="@command('onActiveChecked')"/>
+                                <checkbox checked="@bind(each.active)"
+                                          onCheck="@command('onActiveChecked', entity=each)"/>
                             </listcell>
                         </listitem>
                     </template>
index 069949a6efb25a13f902240cd693b0d0aa1c6801..f3e78a8cd89ecfacaaf6ceb53db282593c543f40 100644 (file)
@@ -1,5 +1,4 @@
-.z-loading {
-       left: 45% !important; 
+.z-loading { left: 45% !important;
 /*
        top: 50% !important; 
        align: center; 
@@ -28,10 +27,11 @@ textarea {
     resize: none;
 }
 
+/*
 .z-listitem-selected>.z-listcell>.z-listcell-content {
     font-weight: bold;
 }
-
+*/
 .container .form-label {
        font-family: "Calibri";
        line-height: 1.5em;