From: elgekko Date: Mon, 17 Jul 2023 09:13:06 +0000 (+0200) Subject: Transition to JPA finished X-Git-Url: http://git.useribm.hu/?a=commitdiff_plain;h=b90fb4ec06a43a31395505209b27bfc4ee82f56f;p=sly-crm.git Transition to JPA finished --- diff --git a/KB.md b/KB.md index 51658e8..45f3d9b 100644 --- a/KB.md +++ b/KB.md @@ -9,6 +9,8 @@ https://www.thymeleaf.org/doc/articles/springmail.html ##### Spring properties https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html +https://www.baeldung.com/spring-cloud-config-without-git +https://docs.spring.io/spring-cloud-config/docs/current/reference/html/ ##### Spring mongo diff --git a/TODO.txt b/TODO.txt index 5e7706e..2f96422 100644 --- a/TODO.txt +++ b/TODO.txt @@ -56,6 +56,14 @@ Kimenő - Bejövő - Treasury eladás + Treasury vétel * auth/ldap ldap:fds.in.useribm.hu:389,ldaps:fds.useribm.hu:636 +*Lista rendezés a projek szerkesztőn belül +-Projekt résztvevő társítás nem eredményez projekt validálást, mentés gomb inaktív marad +-Projekt számla társítás vagy módosítás nem eredményez projekt validálást, mentés gomb inaktív marad +-Modositott treasury mentésre kerül a projekt mentés gomb aktív lesz, de ha mégseme gombot nyomok akkor is megőrződnek a változtatások +-Fájl feltöltes nem műkodik sehol + + + autorizacio nav szamla erkeztetes camunda: egy felasznalohoz jon be, projekthez lehessen csatolni, projektszanot ellenorizze diff --git a/lis-app/pom.xml b/lis-app/pom.xml index e64e7d2..21101b8 100644 --- a/lis-app/pom.xml +++ b/lis-app/pom.xml @@ -116,6 +116,11 @@ lis-services 0.0.1-SNAPSHOT + + org.assertj + assertj-core + 3.24.2 + junit junit diff --git a/lis-app/src/main/resources/application-dev.yaml b/lis-app/src/main/resources/application-dev.yaml index ecc9b0f..ed967ff 100644 --- a/lis-app/src/main/resources/application-dev.yaml +++ b/lis-app/src/main/resources/application-dev.yaml @@ -16,18 +16,16 @@ spring: output: ansi: enabled: always - # data: - # mongodb: - # host: localhost - # port: 27017 - # database: lis datasource: - # driver-class-name: com.mysql.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource url: jdbc:db2://localhost:50000/lis username: db2admin password: password -# hikari: -# pool-name: testmc -# maximum-pool-size: 50 -# minimum-idle: 10 +logging: + level: + org.hibernate.engine.jdbc.spi.SqlExceptionHelper: ERROR + org.springframework.security: DEBUG + org.springframework.security.web: INFO +# pattern: +# console: "%d %-5level %logger : %msg%n" +# file: "%d %-5level [%thread] %logger : %msg%n" \ No newline at end of file diff --git a/lis-app/src/main/resources/application.yaml b/lis-app/src/main/resources/application.yaml index 507a9d2..3f2d8e4 100644 --- a/lis-app/src/main/resources/application.yaml +++ b/lis-app/src/main/resources/application.yaml @@ -9,7 +9,7 @@ spring: jpa: hibernate: use-new-id-generator-mappings: false - show-sql: false + show-sql: true properties: hibernate: format_sql: true diff --git a/lis-app/src/test/java/hu/user/lis/ReflectionsIT.java b/lis-app/src/test/java/hu/user/lis/ReflectionsIT.java new file mode 100644 index 0000000..fbdfb3a --- /dev/null +++ b/lis-app/src/test/java/hu/user/lis/ReflectionsIT.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) $today.year-$today.month-24. + * By elGekko + */ + +package hu.user.lis; + +import com.google.common.collect.Sets; +import hu.user.lis.db.Associate; +import hu.user.lis.db.Project; +import hu.user.lis.db.Treasury; +import hu.user.lis.services.data.EntityDataService; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.SerializationUtils; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + +@Log4j2 +@RunWith(SpringRunner.class) +@ComponentScan("hu.user.lis") +@SpringBootTest +public class ReflectionsIT { + @Autowired + EntityDataService entityDataService; + + @Test + public void testPlainMember() { + Associate associate = Associate.builder() + .id(1L) + .name("Test") + .active(true) + .build(); + Associate clone = SerializationUtils.clone(associate); + clone.setName("Test1"); + + Assertions.assertNotEquals(associate.getName(), clone.getName()); + } + + @Test + public void testList() { + List l1 = Arrays.asList("a", "b"); + List l2 = Arrays.asList("b", "a"); + assertThat(l1).hasSameElementsAs(l2); + } + + @Test + public void testPlainEquality() { + Associate associate = Associate.builder() + .id(1L) + .name("Test") + .active(true) + .build(); + Associate clone = SerializationUtils.clone(associate); + + Assertions.assertNotEquals(associate, clone); + } + + @Test + public void testOneToManyMemberChanged() { + Treasury treasury = Treasury.builder() + .id(1L) + .humanId("Test") + .build(); + Project project = Project.builder() + .id(1L) + .treasuries(Sets.newHashSet(treasury)) + .build(); + Project clone = SerializationUtils.clone(project); + Treasury cloneTreasury = (Treasury) clone.getTreasuries().toArray()[0]; + cloneTreasury.setId(2L); + assertFalse(entityDataService.areEquals(project, clone)); + } + + @Test + public void testOneToManyMemberOrderEquals() { + Treasury treasury1 = Treasury.builder() + .id(1L) + .humanId("Test1") + .build(); + Treasury treasury2 = Treasury.builder() + .id(2L) + .humanId("Test2") + .build(); + Project project = Project.builder() + .id(1L) + .treasuries(Sets.newHashSet(treasury1, treasury2)) + .build(); + Project clone = SerializationUtils.clone(project); + Treasury treasury3 = Treasury.builder() + .id(1L) + .humanId("Test1") + .build(); + Treasury treasury4 = Treasury.builder() + .id(2L) + .humanId("Test2") + .build(); + clone.setTreasuries(Sets.newHashSet(treasury4, treasury3)); + assertTrue(entityDataService.areEquals(project, clone)); + } +} diff --git a/lis-app/src/test/java/hu/user/lis/RepositoryIT.java b/lis-app/src/test/java/hu/user/lis/RepositoryIT.java index af2701c..25bed1a 100644 --- a/lis-app/src/test/java/hu/user/lis/RepositoryIT.java +++ b/lis-app/src/test/java/hu/user/lis/RepositoryIT.java @@ -5,28 +5,47 @@ package hu.user.lis; -import hu.user.lis.db.ServiceRecord; +import hu.user.lis.db.*; +import hu.user.lis.db.repository.ProjectRepository; import hu.user.lis.db.repository.ServiceRecordRepository; +import hu.user.lis.db.repository.TreasuryRepository; +import hu.user.lis.services.data.ProjectService; +import hu.user.lis.services.data.TreasuryService; import lombok.extern.log4j.Log4j2; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; +import javax.persistence.EntityNotFoundException; import java.util.List; +import static org.junit.Assert.assertEquals; + @Log4j2 @RunWith(SpringRunner.class) @ComponentScan("hu.user.lis") @SpringBootTest -//@TestPropertySource("classpath:application.yaml") +@ActiveProfiles("dev") +//@Profile("dev") +@TestPropertySource("classpath:application-dev.yaml") //@AutoConfigureMockMvc public class RepositoryIT { @Autowired - private ServiceRecordRepository serviceRecordRepository; + ServiceRecordRepository serviceRecordRepository; + @Autowired + ProjectRepository projectRepository; + @Autowired + ProjectService projectService; + @Autowired + TreasuryService treasuryService; + @Autowired + private TreasuryRepository treasuryRepository; @Test public void testRepositoryCapabilities() { @@ -40,4 +59,47 @@ public class RepositoryIT { log.info("Found {} items", filteredItems2.size()); } + @Test + public void listProjects() { + List allItems = projectRepository.findAll(); + log.info("Found {} items", allItems.size()); + } + + @Test + public void createProjectWithTreasury() { + Project project = projectService.createNew(); + project.setProjectStatus(null); + + Treasury treasury = treasuryService.createNew(); + project.getTreasuries().add(treasury); + projectRepository.save(project); + + Project persistedProject = projectRepository.findById(project.getId()).orElseThrow(EntityNotFoundException::new); + assertEquals(1, persistedProject.getTreasuries().size()); + + projectRepository.deleteAll(); + } + + @Test + public void createProjectWithIncomingInvoice() { + Project project = projectService.createNew(); + project.setProjectStatus(null); + + IncomingInvoice invoice = IncomingInvoice.builder() + .income(true) + .planned(true) + .currency(Currency.HUF) + .netAmount(1) + .grossAmount(1) + .vatAmount(0.5) + .build(); + project.getIncomingInvoices().add(invoice); + projectRepository.save(project); + + Project persistedProject = projectRepository.findById(project.getId()).orElseThrow(EntityNotFoundException::new); + assertEquals(1, persistedProject.getIncomingInvoices().size()); + assertEquals(0, persistedProject.getOutgoingInvoices().size()); + + projectRepository.deleteAll(); + } } diff --git a/lis-db/migrations/scripts/004_create_default_user.sql b/lis-db/migrations/scripts/004_create_default_user.sql new file mode 100644 index 0000000..77589d4 --- /dev/null +++ b/lis-db/migrations/scripts/004_create_default_user.sql @@ -0,0 +1,10 @@ +-- // create default user +-- Migration SQL that makes the change goes here. + +INSERT INTO ASSOCIATE (login, password, monthly_cost, active) VALUES ('user', 'password', 1, 1); + +-- //@UNDO +-- SQL to undo the change goes here. + +DELETE FROM ASSOCIATE WHERE login = 'user'; + diff --git a/lis-db/pom.xml b/lis-db/pom.xml index 15486c6..ea1d6f8 100644 --- a/lis-db/pom.xml +++ b/lis-db/pom.xml @@ -33,7 +33,7 @@ org.springframework.boot spring-boot-starter-data-jpa - 3.0.4 + 2.7.13 com.ibm.db2 @@ -44,5 +44,10 @@ com.fasterxml.jackson.core jackson-annotations + + org.hibernate + hibernate-core + 5.6.15.Final + \ No newline at end of file diff --git a/lis-db/src/main/java/hu/user/lis/db/Associate.java b/lis-db/src/main/java/hu/user/lis/db/Associate.java index 6561526..6a679bf 100644 --- a/lis-db/src/main/java/hu/user/lis/db/Associate.java +++ b/lis-db/src/main/java/hu/user/lis/db/Associate.java @@ -6,14 +6,15 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import java.io.Serializable; @Getter @Setter @Entity @Builder -@AllArgsConstructor @NoArgsConstructor -public class Associate { +@AllArgsConstructor +public class Associate implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; diff --git a/lis-db/src/main/java/hu/user/lis/db/EDocument.java b/lis-db/src/main/java/hu/user/lis/db/EDocument.java index 6bfb7c1..e10c0ca 100644 --- a/lis-db/src/main/java/hu/user/lis/db/EDocument.java +++ b/lis-db/src/main/java/hu/user/lis/db/EDocument.java @@ -6,15 +6,16 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import java.io.Serializable; import java.util.Date; @Getter @Setter @Entity @Builder -@AllArgsConstructor @NoArgsConstructor -public class EDocument { +@AllArgsConstructor +public class EDocument implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; diff --git a/lis-db/src/main/java/hu/user/lis/db/IncomingInvoice.java b/lis-db/src/main/java/hu/user/lis/db/IncomingInvoice.java new file mode 100644 index 0000000..eab1d7d --- /dev/null +++ b/lis-db/src/main/java/hu/user/lis/db/IncomingInvoice.java @@ -0,0 +1,15 @@ +package hu.user.lis.db; + +import lombok.experimental.SuperBuilder; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity +@SuperBuilder +@DiscriminatorValue("1") +public class IncomingInvoice extends Invoice { + public IncomingInvoice() { + income = true; + } +} 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 4ee7af1..38d0bf1 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 @@ -1,31 +1,29 @@ package hu.user.lis.db; import com.fasterxml.jackson.annotation.JsonIncludeProperties; -import lombok.*; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; import javax.persistence.*; +import java.io.Serializable; import java.util.Date; @Getter @Setter @Entity -@Builder -@AllArgsConstructor +@SuperBuilder @NoArgsConstructor -public class Invoice { +@DiscriminatorColumn(name = "income", discriminatorType = DiscriminatorType.INTEGER) +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +public class Invoice implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String humanId; String title; - @OneToOne - @JoinColumn(name = "partner_id") - @JsonIncludeProperties({"id"}) - Partner partner; - @ManyToOne - @JoinColumn(name = "project_id") - @JsonIncludeProperties({"id"}) - Project project; + @Column(nullable = false, insertable = false, updatable = false) boolean income; Currency currency; double netAmount; @@ -36,4 +34,12 @@ public class Invoice { Date paymentDeadline; boolean planned; byte[] file; + @OneToOne + @JoinColumn(name = "partner_id") + @JsonIncludeProperties({"id"}) + Partner partner; +// @ManyToOne(fetch = FetchType.LAZY) +// @JoinColumn(name = "project_id") +// @JsonIncludeProperties({"id"}) +// Project project; } diff --git a/lis-db/src/main/java/hu/user/lis/db/OutgoingInvoice.java b/lis-db/src/main/java/hu/user/lis/db/OutgoingInvoice.java new file mode 100644 index 0000000..0f55a1e --- /dev/null +++ b/lis-db/src/main/java/hu/user/lis/db/OutgoingInvoice.java @@ -0,0 +1,14 @@ +package hu.user.lis.db; + +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity +@SuperBuilder +@NoArgsConstructor +@DiscriminatorValue("0") +public class OutgoingInvoice extends Invoice { +} diff --git a/lis-db/src/main/java/hu/user/lis/db/Partner.java b/lis-db/src/main/java/hu/user/lis/db/Partner.java index 1e1020c..4e3e5dc 100644 --- a/lis-db/src/main/java/hu/user/lis/db/Partner.java +++ b/lis-db/src/main/java/hu/user/lis/db/Partner.java @@ -6,14 +6,15 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import java.io.Serializable; @Getter @Setter @Entity @Builder -@AllArgsConstructor @NoArgsConstructor -public class Partner { +@AllArgsConstructor +public class Partner implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; 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 ff1d8da..3492c53 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,38 +2,59 @@ package hu.user.lis.db; import com.fasterxml.jackson.annotation.JsonIncludeProperties; import lombok.*; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.Where; import javax.persistence.*; +import java.io.Serializable; import java.util.Set; @Getter @Setter @Entity @Builder -@AllArgsConstructor @NoArgsConstructor -public class Project { +@AllArgsConstructor +public class Project implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; + @ManyToOne @JoinColumn(name = "project_status_id") ProjectStatus projectStatus; - String name; - String humanId; - String contactName; + @ManyToOne - @JoinColumn(name = "partner_id") + @Fetch(FetchMode.JOIN) @JsonIncludeProperties({"id"}) Partner partner; - boolean active; - @OneToMany(mappedBy = "project", fetch = FetchType.EAGER) + + @OneToMany(targetEntity = IncomingInvoice.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + @JoinColumn(name = "projectId", referencedColumnName = "id") + @Where(clause = "income=1") + @Fetch(FetchMode.JOIN) @JsonIncludeProperties({"id"}) - Set incomingInvoices; - @OneToMany(mappedBy = "project", fetch = FetchType.EAGER) + Set incomingInvoices; + + @OneToMany(targetEntity = OutgoingInvoice.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + @JoinColumn(name = "projectId", referencedColumnName = "id") + @Where(clause = "income=0") + @Fetch(FetchMode.JOIN) @JsonIncludeProperties({"id"}) - Set outgoingInvoices; - @OneToMany(mappedBy = "project", fetch = FetchType.EAGER) + Set outgoingInvoices; + + @OneToMany(targetEntity = Treasury.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + @JoinColumn(name = "projectId", referencedColumnName = "id") + @Fetch(FetchMode.JOIN) @JsonIncludeProperties({"id"}) Set treasuries; + + String name; + + String humanId; + + String contactName; + + boolean active; } diff --git a/lis-db/src/main/java/hu/user/lis/db/ProjectAssociate.java b/lis-db/src/main/java/hu/user/lis/db/ProjectAssociate.java index 277d7f0..8cf69ce 100644 --- a/lis-db/src/main/java/hu/user/lis/db/ProjectAssociate.java +++ b/lis-db/src/main/java/hu/user/lis/db/ProjectAssociate.java @@ -2,22 +2,22 @@ package hu.user.lis.db; import lombok.*; -import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; @Getter @Setter @Entity @Builder -@AllArgsConstructor @NoArgsConstructor -public class ProjectAssociate { +@AllArgsConstructor +public class ProjectAssociate implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; - @ManyToOne - @JoinColumn(name = "project_id") - Project project; - @ManyToOne - @JoinColumn(name = "associate_id") - Associate associate; + Long projectId; + Long associateId; } diff --git a/lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java b/lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java index 39e8918..759cc6a 100644 --- a/lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java +++ b/lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java @@ -2,17 +2,19 @@ package hu.user.lis.db; import lombok.*; -import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; @Getter @Setter -@Builder @Entity -//@Document -@AllArgsConstructor +@Builder @NoArgsConstructor -@Table(name = "project_status") -public class ProjectStatus { +@AllArgsConstructor +public class ProjectStatus implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; diff --git a/lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java b/lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java index 7a4785a..b0c1c11 100644 --- a/lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java +++ b/lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java @@ -4,15 +4,16 @@ import com.fasterxml.jackson.annotation.JsonIncludeProperties; import lombok.*; import javax.persistence.*; +import java.io.Serializable; import java.util.Date; @Getter @Setter @Entity @Builder -@AllArgsConstructor @NoArgsConstructor -public class ServiceRecord { +@AllArgsConstructor +public class ServiceRecord implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; diff --git a/lis-db/src/main/java/hu/user/lis/db/Treasury.java b/lis-db/src/main/java/hu/user/lis/db/Treasury.java index 60114e6..acf1836 100644 --- a/lis-db/src/main/java/hu/user/lis/db/Treasury.java +++ b/lis-db/src/main/java/hu/user/lis/db/Treasury.java @@ -1,31 +1,45 @@ package hu.user.lis.db; -import com.fasterxml.jackson.annotation.JsonIncludeProperties; import lombok.*; -import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; import java.util.Date; @Getter @Setter -@Builder @Entity -@AllArgsConstructor +@Builder @NoArgsConstructor -public class Treasury { +@AllArgsConstructor +public class Treasury implements Serializable { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; - @ManyToOne - @JoinColumn(name = "project_id") - @JsonIncludeProperties({"id"}) - Project project; + String humanId; + double buyAmount; + Currency buyCurrency; + double sellAmount; + Currency sellCurrency; + Date transactionDate; + Date valueDate; + byte[] file; + +// @ManyToOne(fetch = FetchType.LAZY) +// @JoinColumn(name = "project_id") +// @JsonIncludeProperties({"id"}) +// Project project; + } diff --git a/lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepositorySearchImpl.java b/lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepositorySearchImpl.java index 67e57f0..03eef0f 100644 --- a/lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepositorySearchImpl.java +++ b/lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepositorySearchImpl.java @@ -26,7 +26,7 @@ public class PartnerRepositorySearchImpl implements PartnerRepositorySearch { if (StringUtils.isNotBlank(partialSearch)) { List 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("vatNr")), "%" + partialSearch.toLowerCase() + "%")); orPredicates.add(cb.like(cb.lower(root.get("address")), "%" + partialSearch.toLowerCase() + "%")); predicates.add(cb.or(orPredicates.toArray(new Predicate[]{}))); } diff --git a/lis-db/src/main/java/hu/user/lis/db/repository/ProjectAssociateRepository.java b/lis-db/src/main/java/hu/user/lis/db/repository/ProjectAssociateRepository.java index eace4a2..2a99015 100644 --- a/lis-db/src/main/java/hu/user/lis/db/repository/ProjectAssociateRepository.java +++ b/lis-db/src/main/java/hu/user/lis/db/repository/ProjectAssociateRepository.java @@ -10,4 +10,5 @@ public interface ProjectAssociateRepository extends JpaRepositorycom.fasterxml.jackson.core jackson-databind + + org.skyscreamer + jsonassert + diff --git a/lis-services/src/main/java/hu/user/lis/services/api/ProjectApi.java b/lis-services/src/main/java/hu/user/lis/services/api/ProjectApi.java index 2baadf5..2ba6d76 100644 --- a/lis-services/src/main/java/hu/user/lis/services/api/ProjectApi.java +++ b/lis-services/src/main/java/hu/user/lis/services/api/ProjectApi.java @@ -1,6 +1,7 @@ package hu.user.lis.services.api; -import hu.user.lis.db.Invoice; +import hu.user.lis.db.IncomingInvoice; +import hu.user.lis.db.OutgoingInvoice; import hu.user.lis.db.Project; import hu.user.lis.db.Treasury; import hu.user.lis.db.repository.InvoiceRepository; @@ -42,25 +43,25 @@ public class ProjectApi extends DbApi entities) { entities.forEach(p -> { - Set incomingInvoices = p.getIncomingInvoices(); + Set incomingInvoices = p.getIncomingInvoices(); if (Objects.nonNull(incomingInvoices)) { incomingInvoices.forEach(i -> { - i.setProject(p); +// i.setProject(p); invoiceRepository.save(i); }); } - Set outgoingInvoices = p.getOutgoingInvoices(); + Set outgoingInvoices = p.getOutgoingInvoices(); if (Objects.nonNull(outgoingInvoices)) { outgoingInvoices.forEach(i -> { - i.setProject(p); +// i.setProject(p); invoiceRepository.save(i); }); } Set treasuries = p.getTreasuries(); treasuries.forEach(t -> { - t.setProject(p); +// t.setProject(p); treasuryRepository.save(t); }); }); diff --git a/lis-services/src/main/java/hu/user/lis/services/data/AssociateEntityDataService.java b/lis-services/src/main/java/hu/user/lis/services/data/AssociateEntityDataService.java new file mode 100644 index 0000000..24789b3 --- /dev/null +++ b/lis-services/src/main/java/hu/user/lis/services/data/AssociateEntityDataService.java @@ -0,0 +1,6 @@ +package hu.user.lis.services.data; + +import hu.user.lis.db.Associate; + +public class AssociateEntityDataService extends EntityDataService { +} diff --git a/lis-services/src/main/java/hu/user/lis/services/data/DataService.java b/lis-services/src/main/java/hu/user/lis/services/data/DataService.java index 2812f60..c842c5c 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/DataService.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/DataService.java @@ -4,10 +4,4 @@ import java.util.List; public interface DataService { List getAll(); - - T copy(T sourceEntity); - - T copy(T sourceEntity, String property, Object value); - - String toString(T sourceEntity); } diff --git a/lis-services/src/main/java/hu/user/lis/services/data/DataServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/DataServiceImpl.java index e3a21b5..43cbe5b 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/DataServiceImpl.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/DataServiceImpl.java @@ -1,11 +1,9 @@ package hu.user.lis.services.data; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import java.lang.reflect.Field; import java.util.List; @Log4j2 @@ -16,41 +14,41 @@ public abstract class DataServiceImpl implements DataService { @Override public abstract List getAll(); - @Override - public T copy(T sourceEntity) { - T result = null; - try { - String json = toString(sourceEntity); - result = (T) mapper.readValue(json, sourceEntity.getClass()); - } catch (JsonProcessingException e) { - log.catching(e); - } - return result; - } - - @Override - public T copy(T sourceEntity, String property, Object value) { - T result = copy(sourceEntity); - Field field = null; - try { - field = result.getClass().getDeclaredField(property); - field.setAccessible(true); - field.set(result, value); - } catch (Exception e) { - log.catching(e); - } - return result; - } - - @Override - public String toString(T sourceEntity) { - String result = null; - try { - result = mapper.writeValueAsString(sourceEntity); - } catch (JsonProcessingException e) { - log.catching(e); - } - return result; - } +// @Override +// public T copy(T sourceEntity) { +// T result = null; +// try { +// String json = toString(sourceEntity); +// result = (T) mapper.readValue(json, sourceEntity.getClass()); +// } catch (JsonProcessingException e) { +// log.catching(e); +// } +// return result; +// } +// +// @Override +// public T copy(T sourceEntity, String property, Object value) { +// T result = copy(sourceEntity); +// Field field = null; +// try { +// field = result.getClass().getDeclaredField(property); +// field.setAccessible(true); +// field.set(result, value); +// } catch (Exception e) { +// log.catching(e); +// } +// return result; +// } +// +// @Override +// public String toString(T sourceEntity) { +// String result = null; +// try { +// result = mapper.writeValueAsString(sourceEntity); +// } catch (JsonProcessingException e) { +// log.catching(e); +// } +// return result; +// } } diff --git a/lis-services/src/main/java/hu/user/lis/services/data/EntityDataService.java b/lis-services/src/main/java/hu/user/lis/services/data/EntityDataService.java new file mode 100644 index 0000000..9220531 --- /dev/null +++ b/lis-services/src/main/java/hu/user/lis/services/data/EntityDataService.java @@ -0,0 +1,95 @@ +package hu.user.lis.services.data; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.SerializationUtils; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.util.Objects; + +@Log4j2 +@Service +public class EntityDataService { + @Autowired + ObjectMapper objectMapper; + + public T clone(T sourceEntity) { + return SerializationUtils.clone(sourceEntity); + } + + + private boolean setFieldValue(T entity, Class clazz, String property, Object value) { + boolean result = false; + try { + Field field = clazz.getDeclaredField(property); + field.setAccessible(true); + field.set(entity, value); + result = true; + } catch (Exception e) { + //log.error(e.getMessage()); + } + return result; + } + + public T clone(T sourceEntity, String property, Object value) { + T result = clone(sourceEntity); + if (setFieldValue(result, result.getClass(), property, value)) { + return result; + } + if (setFieldValue(result, result.getClass().getSuperclass(), property, value)) { + return result; + } + return null; + } + + + public String toJSON(T entity) { + String result = null; + try { + result = objectMapper.writeValueAsString(entity); + } catch (JsonProcessingException e) { + log.catching(e); + } + return result; + } + + public boolean areEquals(T entity1, T entity2) { + boolean result = true; + String json1 = toJSON(entity1); + String json2 = toJSON(entity2); + + try { + JSONAssert.assertEquals(json1, json2, JSONCompareMode.LENIENT); + } catch (Throwable e) { + result = false; + log.error(e); + } + + return result; + } + + public boolean areDifferent(T entity1, T entity2) { + boolean result = false; + if (Objects.isNull(entity1) && Objects.nonNull(entity2)) { + result = true; + } else { + String json1 = toJSON(entity1); + String json2 = toJSON(entity2); + + try { + JSONAssert.assertEquals(json1, json2, JSONCompareMode.LENIENT); + } catch (Throwable e) { + result = true; + log.error(e); + } + } + return result; + } + +} diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ProjectAssociateServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/ProjectAssociateServiceImpl.java index 2f9f613..2746568 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/ProjectAssociateServiceImpl.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/ProjectAssociateServiceImpl.java @@ -32,7 +32,7 @@ public class ProjectAssociateServiceImpl extends DataServiceImpl associates) { - List deleteEntities = entities.stream().filter(pa -> pa.getProject().getId().equals(project.getId())).collect(Collectors.toList()); + List deleteEntities = entities.stream().filter(pa -> pa.getProjectId().equals(project.getId())).collect(Collectors.toList()); entities.removeAll(deleteEntities); associates.forEach((associate, isAssociate) -> { if (isAssociate) { - ProjectAssociate projectAssociate = ProjectAssociate.builder().project(project).associate(associate).build(); + ProjectAssociate projectAssociate = ProjectAssociate.builder().projectId(project.getId()).associateId(associate.getId()).build(); entities.add(projectAssociate); } }); @@ -64,7 +64,7 @@ public class ProjectAssociateServiceImpl extends DataServiceImpl implements Proj .name(name) .contactName(contactName) .partner(partner) - .incomingInvoices(invoiceService.getRandom(true)) - .outgoingInvoices(invoiceService.getRandom(false)) +// .incomingInvoices(invoiceService.getRandom(true)) +// .outgoingInvoices(invoiceService.getRandom(false)) .treasuries(new HashSet<>()) .build(); result.add(entity); @@ -129,8 +129,8 @@ public class ProjectServiceImpl extends DataServiceImpl implements Proj .name(name) .contactName(contactName) .partner(partner) - .incomingInvoices(invoiceService.getByHumanIds(new String[]{"VSz-2023/00070-"})) // VSz-2023/00070- - .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"USER-2023-7"})) // USER-2023-7 +// .incomingInvoices(invoiceService.getByHumanIds(new String[]{"VSz-2023/00070-"})) // VSz-2023/00070- +// .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"USER-2023-7"})) // USER-2023-7 .treasuries(new HashSet<>()) .build(); result.add(entity); @@ -146,8 +146,8 @@ public class ProjectServiceImpl extends DataServiceImpl implements Proj .name(name) .contactName(contactName) .partner(partner) - .incomingInvoices(invoiceService.getByHumanIds(new String[]{"582-SPI1003006-3021", "582-SPI003118", "582-SPI003680", "582-SPI003681", "582-SPI004090", "9090010764", "VSz-2021/00091"})) // 582-SPI1003006-3021, 582-SPI003118, 582-SPI003680, 582-SPI003681, 582-SPI004090, 9090010764, VSz-2021/00091 - .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"2021/0001", "2021/0069"})) // 2021/0001, 2021/0069 +// .incomingInvoices(invoiceService.getByHumanIds(new String[]{"582-SPI1003006-3021", "582-SPI003118", "582-SPI003680", "582-SPI003681", "582-SPI004090", "9090010764", "VSz-2021/00091"})) // 582-SPI1003006-3021, 582-SPI003118, 582-SPI003680, 582-SPI003681, 582-SPI004090, 9090010764, VSz-2021/00091 +// .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"2021/0001", "2021/0069"})) // 2021/0001, 2021/0069 .treasuries(treasuryService.getByHumanIds(new String[]{"014", "015"})) .build(); result.add(entity); @@ -163,8 +163,8 @@ public class ProjectServiceImpl extends DataServiceImpl implements Proj .name(name) .contactName(contactName) .partner(partner) - .incomingInvoices(invoiceService.getByHumanIds(new String[]{"EURSZLA0177/2022", "19044", "9171058452", "9171058628", "2022-SOV/000495", "2022-SOV/000496", "E-SYMPR-2022-105"})) // EURSZLA0177/2022, 19044, 9171058452, 9171058628, V-SZ3-2022/00001, 2022-SOV/000495, 2022-SOV/000496, E-SYMPR-2022-105 - .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-12", "E-USER-2023-13"})) // E-USER-2023-12, E-USER-2023-13 +// .incomingInvoices(invoiceService.getByHumanIds(new String[]{"EURSZLA0177/2022", "19044", "9171058452", "9171058628", "2022-SOV/000495", "2022-SOV/000496", "E-SYMPR-2022-105"})) // EURSZLA0177/2022, 19044, 9171058452, 9171058628, V-SZ3-2022/00001, 2022-SOV/000495, 2022-SOV/000496, E-SYMPR-2022-105 +// .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-12", "E-USER-2023-13"})) // E-USER-2023-12, E-USER-2023-13 .treasuries(treasuryService.getByHumanIds(new String[]{"001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011"})) .build(); result.add(entity); @@ -180,8 +180,8 @@ public class ProjectServiceImpl extends DataServiceImpl implements Proj .name(name) .contactName(contactName) .partner(partner) - .incomingInvoices(invoiceService.getByHumanIds(new String[]{"17356/23"})) // 17356/23 - .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-53"})) // E-USER-2023-53 +// .incomingInvoices(invoiceService.getByHumanIds(new String[]{"17356/23"})) // 17356/23 +// .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-53"})) // E-USER-2023-53 .treasuries(new HashSet<>()) .build(); result.add(entity); @@ -197,8 +197,8 @@ public class ProjectServiceImpl extends DataServiceImpl implements Proj .name(name) .contactName(contactName) .partner(partner) - .incomingInvoices(invoiceService.getByHumanIds(new String[]{"2023-SOV/000123"})) // 2023-SOV/000123 - .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-95"})) // E-USER-2023-95 +// .incomingInvoices(invoiceService.getByHumanIds(new String[]{"2023-SOV/000123"})) // 2023-SOV/000123 +// .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-95"})) // E-USER-2023-95 .treasuries(treasuryService.getByHumanIds(new String[]{"012", "013"})) .build(); result.add(entity); diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ReflectEntity.java b/lis-services/src/main/java/hu/user/lis/services/data/ReflectEntity.java new file mode 100644 index 0000000..099a13e --- /dev/null +++ b/lis-services/src/main/java/hu/user/lis/services/data/ReflectEntity.java @@ -0,0 +1,66 @@ +package hu.user.lis.services.data; + +import org.springframework.stereotype.Service; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@Service +public class ReflectEntity { + + public boolean areEquals(Object ob1, Object ob2) { + if (Objects.isNull(ob1) && Objects.isNull(ob2)) { + return true; + } + + if (Objects.isNull(ob1) || Objects.isNull(ob2)) { + return false; + } + + if (!(ob1.getClass().isAssignableFrom(ob2.getClass()) || ob2.getClass().isAssignableFrom(ob1.getClass()))) { + return false; + } + return process(ob1, ob2); + } + + public Map getGetters(Class clazz) { + Map getters = new HashMap<>(); + // get getters + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + if ("CLASS".equals(method.getName())) { + continue; + } + if (isGetter(method)) { + getters.put(method.getName(), method); + } + } + return getters; + } + + private boolean process(Object ob1, Object ob2) { + + Map getters1 = getGetters(ob1.getClass()); + Map getters2 = getGetters(ob2.getClass()); + + if (getters1.size() < getters2.size()) { + } + + return false; + } + + public boolean isGetter(Method method) { + if (!method.getName().startsWith("get") || !method.getName().startsWith("is")) { + return false; + } + if (method.getParameterTypes().length != 0) { + return false; + } + if (void.class.equals(method.getReturnType())) { + return false; + } + return true; + } +} \ No newline at end of file diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java index 753dca4..fa2f33b 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java @@ -90,15 +90,15 @@ public class ServiceRecordServiceImpl extends DataServiceImpl imp projectService.getAll().forEach(p -> { int serviceRecordCount = RandomUtils.nextInt(3, 10); - List projectAssociates = projectAssociateService.getAll().stream().filter(e -> e.getProject().getId().equals(p.getId())).collect(Collectors.toList()); + List projectAssociates = projectAssociateService.getAll().stream().filter(e -> e.getProjectId().equals(p.getId())).collect(Collectors.toList()); projectAssociates.forEach(pa -> { for (int i = 0; i < serviceRecordCount; i++) { Date workDay = dataGeneratorService.faker().date().past(i * 10 + 1, TimeUnit.DAYS); String description = dataGeneratorService.faker().lorem().sentence(10); int workHours = RandomUtils.nextInt(1, 9); ServiceRecord entity = ServiceRecord.builder() - .associate(pa.getAssociate()) - .project(pa.getProject()) +// .associate(pa.getAssociate()) +// .project(pa.getProject()) .workDay(workDay) .workHours(workHours) .description(description) @@ -107,8 +107,8 @@ public class ServiceRecordServiceImpl extends DataServiceImpl imp result.add(entity); entity = ServiceRecord.builder() - .associate(pa.getAssociate()) - .project(pa.getProject()) +// .associate(pa.getAssociate()) +// .project(pa.getProject()) .workDay(workDay) .workHours(workHours) .description(description) diff --git a/lis-services/src/main/java/hu/user/lis/services/data/TreasuryServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/TreasuryServiceImpl.java index 7b8d1da..f952ba7 100644 --- a/lis-services/src/main/java/hu/user/lis/services/data/TreasuryServiceImpl.java +++ b/lis-services/src/main/java/hu/user/lis/services/data/TreasuryServiceImpl.java @@ -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.Treasury; import lombok.extern.log4j.Log4j2; @@ -18,12 +17,13 @@ import java.util.concurrent.TimeUnit; @Log4j2 public class TreasuryServiceImpl extends DataServiceImpl implements TreasuryService { int GENERATE_COUNT = 500; + @Autowired DataGeneratorService dataGeneratorService; - @Autowired - ObjectMapper mapper; + private List entities; + @Override public List getAll() { if (entities == null) { diff --git a/lis-ui/src/main/java/hu/user/lis/ui/Constants.java b/lis-ui/src/main/java/hu/user/lis/ui/Constants.java index adf357b..f669779 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/Constants.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/Constants.java @@ -9,4 +9,12 @@ public class Constants { public static final String SET_PROJECTS_LIST_DATA = "SET_PROJECTS_LIST_DATA"; public static final String PROJECT_EDITOR_QUEUE = "PROJECT_EDITOR_QUEUE"; + public static final String NAV_PARTNERS = "/partners"; + public static final String NAV_PROJECTS = "/projects"; + public static final String NAV_PROJECT = "/project"; + public static final String NAV_ASSOCIATES = "/associates"; + public static final String NAV_PROJECT_ASSOCIATES = "/project-associates"; + public static final String NAV_SERVICE_RECORDS = "/service-records"; + public static final String NAV_SETTINGS = "/settings"; + } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java b/lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java index 8fb3891..ac9de86 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java @@ -34,9 +34,11 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); String[] navigation = NAVIGATION.keySet().toArray(new String[]{}); + http.headers().frameOptions().sameOrigin(); http.authorizeRequests() .antMatchers(ZUL_FILES).denyAll() // block direct access to zul files .antMatchers(HttpMethod.GET, ZK_RESOURCES).permitAll() // allow zk resources + .antMatchers(HttpMethod.POST, "/zkau/upload/**").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", "/api/**").permitAll() diff --git a/lis-ui/src/main/java/hu/user/lis/ui/converter/DateToStringConverter.java b/lis-ui/src/main/java/hu/user/lis/ui/converter/DateToStringConverter.java index 0957f28..69af5bf 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/converter/DateToStringConverter.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/converter/DateToStringConverter.java @@ -1,18 +1,20 @@ package hu.user.lis.ui.converter; +import org.apache.commons.lang3.StringUtils; import org.zkoss.bind.BindContext; import org.zkoss.bind.Converter; import org.zkoss.zul.Listcell; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Objects; public class DateToStringConverter implements Converter { private SimpleDateFormat df = new SimpleDateFormat("yyyy. MM. dd."); @Override public String coerceToUi(Date date, Listcell listCell, BindContext bindContext) { - return df.format(date); + return Objects.isNull(date) ? StringUtils.EMPTY : df.format(date); } @Override diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/AssociatesDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/AssociatesDataModel.java index 11c283d..26da552 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/AssociatesDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/AssociatesDataModel.java @@ -3,6 +3,7 @@ package hu.user.lis.ui.data; import hu.user.lis.db.Associate; import hu.user.lis.db.repository.AssociateRepository; import hu.user.lis.services.data.AssociateService; +import hu.user.lis.services.data.EntityDataService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -19,11 +20,18 @@ import java.util.List; public class AssociatesDataModel extends CachedSpringDataModel { @Autowired AssociateRepository associateRepository; + @Autowired AssociateService associateService; + + @Autowired + EntityDataService associateDataService; private String partialName; + private boolean listAll; + private boolean filterShowInActive; + private boolean filterShowActive; @Override @@ -78,12 +86,8 @@ public class AssociatesDataModel extends CachedSpringDataModel { return associateService.createNew(); } - public void addNew(Associate entity) { - associateRepository.save(entity); - } - - public Associate copy(Associate selectedEntity) { - return associateService.copy(selectedEntity); + public Associate clone(Associate selectedEntity) { + return associateDataService.clone(selectedEntity); } public Associate save(Associate entity) { diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/CachedDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/CachedDataModel.java index 2e15114..09cc5af 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/CachedDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/CachedDataModel.java @@ -25,9 +25,7 @@ public abstract class CachedDataModel extends ListModelList { private FieldComparator sortComparator; public CachedDataModel() { - //reinit(); - log.info("Initialized"); - setMultiple(true); + setMultiple(false); } public void reset() { diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java index e674fd5..3e5d23b 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java @@ -1,9 +1,7 @@ package hu.user.lis.ui.data; import hu.user.lis.db.Currency; -import hu.user.lis.db.Invoice; -import hu.user.lis.db.Project; -import hu.user.lis.db.Treasury; +import hu.user.lis.db.*; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; @@ -20,14 +18,14 @@ public class IncomeMarginsDataModel extends ArrayList { public void recalculate(Project project) { clear(); Map balances = new HashMap<>(); - Set outgoingInvoices = project.getOutgoingInvoices(); + Set outgoingInvoices = project.getOutgoingInvoices(); if (Objects.nonNull(outgoingInvoices)) { for (Invoice invoice : outgoingInvoices) { addBalance(balances, invoice.getCurrency(), invoice.getNetAmount()); } } - Set incomingInvoices = project.getIncomingInvoices(); + Set incomingInvoices = project.getIncomingInvoices(); if (Objects.nonNull(incomingInvoices)) { for (Invoice invoice : incomingInvoices) { substractBalance(balances, invoice.getCurrency(), invoice.getNetAmount()); 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 index 53cbd05..3ea164d 100644 --- 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 @@ -1,31 +1,58 @@ package hu.user.lis.ui.data; +import hu.user.lis.db.IncomingInvoice; import hu.user.lis.db.Invoice; -import hu.user.lis.db.Project; +import hu.user.lis.db.OutgoingInvoice; import hu.user.lis.db.repository.InvoiceRepository; +import hu.user.lis.services.data.EntityDataService; 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); + @Autowired + EntityDataService incomingInvoiceDataService; + @Autowired + EntityDataService outgoingInvoiceDataService; + + public IncomingInvoice clone(IncomingInvoice entity) { + return incomingInvoiceDataService.clone(entity); + } + + public OutgoingInvoice clone(OutgoingInvoice entity) { + return outgoingInvoiceDataService.clone(entity); } - public Invoice createNew(Project formDocument) { - Invoice result = invoiceService.createNew(); - result.setProject(formDocument); + public IncomingInvoice createNewIncomingInvoice() { + IncomingInvoice result = IncomingInvoice.builder() + .income(true) + .planned(true) + .build(); return result; } + + public OutgoingInvoice createNewOutgoingInvoice() { + OutgoingInvoice result = OutgoingInvoice.builder() + .planned(true) + .build(); + return result; + } + + public void save(Invoice modifiedEntity) { + invoiceRepository.save(modifiedEntity); + } + + public void delete(Invoice selectedIncomingInvoice) { + invoiceRepository.delete(selectedIncomingInvoice); + } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/PartnersDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/PartnersDataModel.java index c5f62c3..a819a64 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/PartnersDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/PartnersDataModel.java @@ -2,6 +2,7 @@ package hu.user.lis.ui.data; import hu.user.lis.db.Partner; import hu.user.lis.db.repository.PartnerRepository; +import hu.user.lis.services.data.EntityDataService; import hu.user.lis.services.data.PartnerService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; @@ -23,6 +24,9 @@ public class PartnersDataModel extends CachedSpringDataModel { @Autowired PartnerService partnerService; + @Autowired + EntityDataService partnerDataService; + private String partialSearch; private boolean listAll; @@ -75,12 +79,8 @@ public class PartnersDataModel extends CachedSpringDataModel { return partnerService.createNew(); } - public void addNew(Partner entity) { - partnerRepository.save(entity); - } - - public Partner copy(Partner selectedEntity) { - return partnerService.copy(selectedEntity); + public Partner clone(Partner selectedEntity) { + return partnerDataService.clone(selectedEntity); } public Partner save(Partner selectedEntity) { diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectAssociatesDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectAssociatesDataModel.java index afb8a1c..17fbf0e 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectAssociatesDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectAssociatesDataModel.java @@ -1,12 +1,17 @@ package hu.user.lis.ui.data; +import hu.user.lis.db.Associate; +import hu.user.lis.db.Project; import hu.user.lis.db.ProjectAssociate; import hu.user.lis.db.repository.ProjectAssociateRepository; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; @Component @@ -25,4 +30,23 @@ public class ProjectAssociatesDataModel { return result; } + + @Transactional + public void updateAssociates(Project project, Map formAssociates) { + projectAssociateRepository.deleteByProjectId(project.getId()); + List associates = new ArrayList<>(); + formAssociates.forEach((k, v) -> { + if (v) { + Associate associate = Associate.builder().build(); + associate.setId(k); + associates.add(ProjectAssociate.builder() + .projectId(project.getId()) + .associateId(associate.getId()) + .build()); + } + }); + if (!associates.isEmpty()) { + projectAssociateRepository.saveAll(associates); + } + } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java index 058b714..f674fe1 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java @@ -43,10 +43,4 @@ public class ProjectSelectorDataModel extends CachedSpringDataModel { this.partialSearch = partialSearch; super.reset(); } - - public void getLimited() { - log.info("Searching projects using limit {}", SEARCH_LIMIT); - this.partialSearch = null; - super.reset(); - } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectsDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectsDataModel.java index 4869f78..3bc9694 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectsDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectsDataModel.java @@ -3,6 +3,7 @@ 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.EntityDataService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -12,7 +13,6 @@ 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; @@ -29,6 +29,9 @@ public class ProjectsDataModel extends CachedSpringDataModel { @Autowired ProjectStatusDataModel projectStatusDataModel; + @Autowired + EntityDataService projectDataService; + private String partialName; private boolean listAll; @@ -76,11 +79,7 @@ public class ProjectsDataModel extends CachedSpringDataModel { } public Project 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)); + String humanId = generateHumanId(); ProjectStatus projectStatus = projectStatusDataModel.getDefault(); return Project.builder() .projectStatus(projectStatus) @@ -92,31 +91,16 @@ public class ProjectsDataModel extends CachedSpringDataModel { .build(); } - public void addNew(Project entity) { - projectRepository.save(entity); - } - - 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); + private String generateHumanId() { + String yearSearch = String.format("%s-%%", Year.now().getValue()); + Project lastInYear = projectRepository.findFirstByHumanIdLikeOrderByHumanIdDesc(yearSearch); + int sortOrder = 0; + if (Objects.nonNull(lastInYear)) { + sortOrder = Integer.parseInt(lastInYear.getHumanId().split("-")[1]); } + DecimalFormat decFormat = new DecimalFormat("0000"); + String humanId = String.format("%s-%s", Year.now().getValue(), decFormat.format(++sortOrder)); + return humanId; } public Project save(Project selectedEntity) { @@ -126,4 +110,8 @@ public class ProjectsDataModel extends CachedSpringDataModel { public Project getById(Long id) { return projectRepository.findById(id).orElseThrow(EntityNotFoundException::new); } + + public Project clone(Project entity) { + return projectDataService.clone(entity); + } } 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 index b232010..309b87a 100644 --- 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 @@ -1,32 +1,28 @@ 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.EntityDataService; 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; + EntityDataService treasuryDataService; @Autowired - TreasuryRepository treasuryRepository; + TreasuryService treasuryService; - public Treasury copy(Treasury entity) { - return treasuryRepository.findById(entity.getId()).orElseThrow(EntityExistsException::new); + public Treasury createNew() { + return treasuryService.createNew(); } - public Treasury createNew(Project formDocument) { - Treasury result = treasuryService.createNew(); - result.setProject(formDocument); - return result; + public Treasury clone(Treasury entity) { + return treasuryDataService.clone(entity); } + } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/AssociateEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/AssociateEditorModel.java index fd29d54..1eec92a 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/editor/AssociateEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/AssociateEditorModel.java @@ -1,86 +1,27 @@ package hu.user.lis.ui.editor; import hu.user.lis.db.Associate; -import hu.user.lis.services.data.AssociateService; import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; -import org.zkoss.bind.BindUtils; -import org.zkoss.bind.ValidationContext; -import org.zkoss.bind.annotation.BindingParam; -import org.zkoss.bind.annotation.Command; import org.zkoss.bind.annotation.Init; -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.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 AssociateEditorModel extends AbstractValidator { - @WireVariable - AssociateService associateServiceImpl; - private Associate formDocument; - private Associate origDocument; - private boolean formInvalid = true; +public class AssociateEditorModel extends EntityEditorModel { @Init public void init() { - log.info("Initialized"); - origDocument = (Associate) Executions.getCurrent().getArg().get("origDocument"); - formDocument = (Associate) Executions.getCurrent().getArg().get("formDocument"); - } - - @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); + super.init(); } @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); - updateFormInvalid(false); - try { - Associate newData = associateServiceImpl.copy(formDocument, property, value); - if (!Objects.isNull(origDocument) && associateServiceImpl.toString(origDocument).equals(associateServiceImpl.toString(newData))) { - log.info("Document not changed"); - updateFormInvalid(true); - return; - } - if (StringUtils.isBlank(newData.getName()) || - StringUtils.isBlank(newData.getLogin()) || - (!newData.isRemotelyAuthenticated() && StringUtils.isBlank(newData.getPassword())) || - newData.getMonthlyCost() < 1 - ) { - 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"); + protected boolean canSave(Associate entity) { + return StringUtils.isNotBlank(entity.getName()) && + StringUtils.isNotBlank(entity.getLogin()) && + (entity.isRemotelyAuthenticated() || StringUtils.isNotBlank(entity.getPassword())) && + entity.getMonthlyCost() > 0; } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/EditCompleted.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/EditCompleted.java new file mode 100644 index 0000000..2f4cd35 --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/EditCompleted.java @@ -0,0 +1,7 @@ +package hu.user.lis.ui.editor; + +public interface EditCompleted { + + void done(E entity); + +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/Editors.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/Editors.java new file mode 100644 index 0000000..87a28a9 --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/Editors.java @@ -0,0 +1,43 @@ +package hu.user.lis.ui.editor; + +import com.google.common.collect.ImmutableMap; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zul.Window; + +import java.util.Map; +import java.util.Objects; + +public class Editors { + public static String INCOMING_INVOICE = "~./incoming-invoice-editor.zul"; + public static String OUTGOING_INVOICE = "~./outgoing-invoice-editor.zul"; + + public static String TREASURY = "~./treasury-editor.zul"; + public static String ASSOCIATE = "~./associate-editor.zul"; + public static String PARTNER = "~./partner-editor.zul"; + + public static void doEdit(String page, E entity, EditCompleted editCompleted) { + doEdit(page, entity, null, editCompleted); + } + + public static void doEdit(String page, E entity, E original, EditCompleted editCompleted) { + Map arg; + if (Objects.isNull(entity)) { + //header double click + return; + } + + if (Objects.isNull(original)) { + arg = ImmutableMap.of("formDocument", entity); + } else { + arg = ImmutableMap.of("formDocument", entity, "origDocument", original); + } + Window editorWindow = (Window) Executions.createComponents(page, null, arg); + editorWindow.addEventListener("onClose", e -> { + if (e.getData() != null) { + editCompleted.done((E) e.getData()); + } + }); + editorWindow.doModal(); + editorWindow.setFocus(true); + } +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/EntityEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/EntityEditorModel.java new file mode 100644 index 0000000..ca9927d --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/EntityEditorModel.java @@ -0,0 +1,92 @@ +package hu.user.lis.ui.editor; + +import hu.user.lis.services.data.EntityDataService; +import lombok.Getter; +import lombok.extern.log4j.Log4j2; +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.select.Selectors; +import org.zkoss.zk.ui.select.annotation.VariableResolver; +import org.zkoss.zk.ui.select.annotation.WireVariable; +import org.zkoss.zkplus.spring.DelegatingVariableResolver; +import org.zkoss.zul.Window; + +import java.io.Serializable; + + +@Log4j2 +@VariableResolver(DelegatingVariableResolver.class) +public abstract class EntityEditorModel extends AbstractValidator { + + @Getter + T formDocument; + + T origDocument; + + @Getter + boolean saveEnabled; + + @WireVariable + EntityDataService entityDataService; + + + @Command + public void onCloseWindow(@BindingParam("target") Window target, @BindingParam("save") boolean save) { + if (save) { + if (saveEnabled) { + Events.postEvent(new Event("onClose", target, formDocument)); + } + } else { + Events.postEvent(new Event("onClose", target, null)); + } + } + + private void setSaveEnabled(boolean saveEnabled) { + this.saveEnabled = saveEnabled; + log.info("Document save enabled {}", saveEnabled); + BindUtils.postNotifyChange(this, "saveEnabled"); + } + + @AfterCompose + public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) { + Selectors.wireComponents(view, this, false); + Selectors.wireEventListeners(view, this); + } + + @Init + public void init() { + origDocument = (T) Executions.getCurrent().getArg().get("origDocument"); + formDocument = (T) Executions.getCurrent().getArg().get("formDocument"); + } + + @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); + try { + validate(entityDataService.clone(formDocument, property, value)); + } catch (Exception e) { + log.catching(e); + } + } + + protected abstract boolean canSave(T entity); + + protected boolean areDifferent(T entity) { + return entityDataService.areDifferent(origDocument, entity); + } + + protected void validate(T entity) { + boolean enable = areDifferent(entity) && canSave(entity); + setSaveEnabled(enable); + } + +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java index 12ffefe..1f897d2 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java @@ -2,7 +2,6 @@ package hu.user.lis.ui.editor; 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; @@ -10,39 +9,30 @@ 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.*; -import org.zkoss.zk.ui.select.annotation.VariableResolver; +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.event.InputEvent; +import org.zkoss.zk.ui.event.OpenEvent; +import org.zkoss.zk.ui.event.UploadEvent; import org.zkoss.zk.ui.select.annotation.WireVariable; -import org.zkoss.zkplus.spring.DelegatingVariableResolver; import org.zkoss.zul.Messagebox; -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; +public class InvoiceEditorModel extends EntityEditorModel { + @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(); + super.init(); + //partnerSelectorDataModel.clearSelection(); } @Command @@ -51,18 +41,10 @@ public class InvoiceEditorModel extends AbstractValidator { formDocument.setGrossAmount(formDocument.getNetAmount() * 1.27); formDocument.setVatAmount(formDocument.getGrossAmount() - formDocument.getNetAmount()); BindUtils.postNotifyChange(this.formDocument, "grossAmount", "vatAmount"); + validate(formDocument); } } - @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(); @@ -78,68 +60,17 @@ public class InvoiceEditorModel extends AbstractValidator { } @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); - try { - Invoice newData = invoiceServiceImpl.copy(formDocument, property, value); - validate(newData); - } catch (Exception e) { - log.catching(e); - } - - } - - private void validate(Invoice newData) { - updateFormInvalid(false); - if (!Objects.isNull(origDocument) && invoiceServiceImpl.toString(origDocument).equals(invoiceServiceImpl.toString(newData))) { - log.info("Document not changed"); - updateFormInvalid(true); - return; - } - - boolean invalid = false; - if (newData.isPlanned()) { - if (newData.getNetAmount() <= 0 || - StringUtils.isBlank(newData.getTitle()) || - Objects.isNull(newData.getPartner()) - ) { - invalid = true; - } - - if (!Currency.HUF.equals(newData.getCurrency())) { - if (newData.getGrossAmount() <= 0 || newData.getVatAmount() <= 0) { - invalid = true; - } - } - } else { - 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()) - ) { - invalid = true; - } - } - - if (invalid) { - log.info("Document is not valid"); - updateFormInvalid(true); - } - } - - private void updateFormInvalid(boolean invalid) { - setFormInvalid(invalid); - BindUtils.postNotifyChange(this, "formInvalid"); + protected boolean canSave(Invoice entity) { + return entity.getNetAmount() > 0 && + entity.getGrossAmount() > 0 && + entity.getVatAmount() > 0 && + StringUtils.isNotBlank(entity.getTitle()) && + Objects.nonNull(entity.getPartner()) && + Objects.nonNull(entity.getCompletionDate()) && + Objects.nonNull(entity.getCreateDate()) && + Objects.nonNull(entity.getPaymentDeadline()) && + entity.getCreateDate().before(entity.getCompletionDate()) && + entity.getCompletionDate().before(entity.getPaymentDeadline()); } @Command @@ -151,13 +82,13 @@ public class InvoiceEditorModel extends AbstractValidator { } formDocument.setFile(evt.getMedia().getByteData()); BindUtils.postNotifyChange(this.formDocument, "file"); - validate(invoiceServiceImpl.copy(formDocument)); + validate(formDocument); } @Command public void onRemoveFile() { formDocument.setFile(null); BindUtils.postNotifyChange(this.formDocument, "file"); - validate(invoiceServiceImpl.copy(formDocument)); + validate(formDocument); } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/PartnerEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/PartnerEditorModel.java index 1a7dcbb..9593444 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/editor/PartnerEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/PartnerEditorModel.java @@ -1,83 +1,30 @@ package hu.user.lis.ui.editor; import hu.user.lis.db.Partner; -import hu.user.lis.services.data.PartnerService; import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; -import org.zkoss.bind.BindUtils; -import org.zkoss.bind.ValidationContext; -import org.zkoss.bind.annotation.BindingParam; -import org.zkoss.bind.annotation.Command; import org.zkoss.bind.annotation.Init; -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.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 PartnerEditorModel extends AbstractValidator { +public class PartnerEditorModel extends EntityEditorModel { private static final String VAT_NR_PATTERN = "/^[0-9]{8}-[1-5]{1}-[02]|[22]|[03]|[23]|[04]|[24]|[05]|[25]|[06]|[26]|[07]|[27]|[08]|[28]|[09]|[29]|[10]|[30]|[11]|[31]|[12]|[32]|[13]|[33]|[14]|[34]|[15]|[35]|[16]|[36]|[17]|[37]|[18]|[38]|[19]|[39]|[20]|[40]|[41]|[42]|[43]|[44]|[51]$/s"; - @WireVariable - PartnerService partnerServiceImpl; - private Partner formDocument; - private Partner origDocument; - private boolean formInvalid = true; @Init public void init() { - log.info("Initialized"); - origDocument = (Partner) Executions.getCurrent().getArg().get("origDocument"); - formDocument = (Partner) Executions.getCurrent().getArg().get("formDocument"); - } - - @Command - public void onCloseWindow(@BindingParam("target") Window target, @BindingParam("select") boolean select) { - if (select && !formInvalid) { - Event closeEvent = new Event("onClose", target, select ? formDocument : null); - Events.postEvent(closeEvent); - } + super.init(); } @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); - 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()) || - newData.getVatNr().length() != 13 || - !isVatNumber(newData.getVatNr()) - ) { - log.info("Document is not valid"); - updateFormInvalid(true); - } - - - } catch (Exception e) { - log.catching(e); - } + protected boolean canSave(Partner entity) { + return StringUtils.isNotBlank(entity.getName()) && + StringUtils.isNotBlank(entity.getAddress()) && + StringUtils.isNotBlank(entity.getVatNr()) && + entity.getVatNr().length() == 13 && + isVatNumber(entity.getVatNr()); } private boolean isVatNumber(String vatNr) { @@ -88,9 +35,4 @@ public class PartnerEditorModel extends AbstractValidator { // log.info("Vat number regex match {}", result); // return result; } - - private void updateFormInvalid(boolean invalid) { - setFormInvalid(invalid); - BindUtils.postNotifyChange(this, "formInvalid"); - } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java index d231e4d..0128c81 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java @@ -3,32 +3,23 @@ package hu.user.lis.ui.editor; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.collect.ImmutableMap; 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.*; import hu.user.lis.ui.event.EventBus; -import hu.user.lis.ui.session.SessionSettings; 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.EventListener; import org.zkoss.zk.ui.event.InputEvent; import org.zkoss.zk.ui.event.OpenEvent; -import org.zkoss.zk.ui.select.annotation.VariableResolver; import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zk.ui.util.Clients; -import org.zkoss.zkplus.spring.DelegatingVariableResolver; import org.zkoss.zul.Center; import org.zkoss.zul.Panel; import org.zkoss.zul.Window; @@ -38,19 +29,12 @@ import java.util.*; @Log4j2 @Getter @Setter -@VariableResolver(DelegatingVariableResolver.class) -public class ProjectEditorModel extends AbstractValidator implements EventListener { +public class ProjectEditorModel extends EntityEditorModel implements EventListener { @WireVariable AssociatesDataModel associatesDataModel; @WireVariable - ServiceRecordService serviceRecordServiceImpl; - - @WireVariable - SessionSettings sessionSettings; - - @WireVariable - private ProjectsDataModel projectsDataModel; + ProjectsDataModel projectsDataModel; @WireVariable private PartnerSelectorDataModel partnerSelectorDataModel; @@ -61,9 +45,6 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen @WireVariable private TreasuryDataModel treasuryDataModel; - @WireVariable - private ProjectService projectServiceImpl; - @WireVariable private ServiceRecordsDataModel serviceRecordsDataModel; @@ -82,19 +63,13 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen @WireVariable private EventBus eventBus; - private Project formDocument; - - private Project origDocument; - private Map origAssociates; private Map formAssociates; - private boolean formInvalid = true; - - private Invoice selectedIncomingInvoice; + private IncomingInvoice selectedIncomingInvoice; - private Invoice selectedOutgoingInvoice; + private OutgoingInvoice selectedOutgoingInvoice; private Treasury selectedTreasury; @@ -104,7 +79,6 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen public void init() { projectStatusDataModel.listAll(); eventBus.register(this); - log.info("Initialized"); } @Override @@ -117,14 +91,15 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen 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); + origDocument = projectsDataModel.clone(formDocument); } - serviceRecordsDataModel.search(formDocument, true); initAssociates(); + serviceRecordsDataModel.search(formDocument, true); incomeMarginsDataModel.recalculate(formDocument); BindUtils.postNotifyChange(this, "formDocument"); } @@ -145,11 +120,14 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen } @Command - public void onEndEdit(@BindingParam("target") Window target, @BindingParam("select") boolean select) { - if (select && !formInvalid) { + public void onEndEdit(@BindingParam("target") Window target, @BindingParam("save") boolean save) { + if (save && saveEnabled) { projectsDataModel.save(formDocument); - eventBus.showProjectsList(ImmutableMap.of("formDocument", formDocument)); + if (isAssociatesChanged()) { + projectAssociatesDataModel.updateAssociates(formDocument, formAssociates); + } } + eventBus.showProjectsList(ImmutableMap.of("formDocument", formDocument)); } @Command @@ -166,238 +144,140 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen partnerSelectorDataModel.search(null); } - @Command - public void onPopupPartners() { - String page = "~./suppliers.zul"; - Window editorWindow = (Window) Executions.createComponents(page, null, null); - editorWindow.addEventListener("onClose", e -> { - log.info("Suppliers popup result {}", e.getData()); - if (e.getData() != null) { - partnerSelectorDataModel.clearSelection(); - //setSelectedSupplierId(((Supplier) e.getData()).getId()); - BindUtils.postNotifyChange(this, "selectedSupplierId"); - } - }); - editorWindow.doModal(); - editorWindow.setFocus(true); - } +// @Command +// public void onPopupPartners() { +// String page = "~./suppliers.zul"; +// Window editorWindow = (Window) Executions.createComponents(page, null, null); +// editorWindow.addEventListener("onClose", e -> { +// log.info("Suppliers popup result {}", e.getData()); +// if (e.getData() != null) { +// partnerSelectorDataModel.clearSelection(); +// //setSelectedSupplierId(((Supplier) e.getData()).getId()); +// BindUtils.postNotifyChange(this, "selectedSupplierId"); +// } +// }); +// editorWindow.doModal(); +// editorWindow.setFocus(true); +// } @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); - try { - - 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.nonNull(origDocument)) { - boolean invalid = projectServiceImpl.toString(origDocument).equals(projectServiceImpl.toString(newData)) - && !isAssociatesChanged(); - updateFormInvalid(invalid); - return; - } - - if (StringUtils.isBlank(newData.getName()) || - StringUtils.isBlank(newData.getContactName()) || - Objects.isNull(newData.getPartner()) - ) { - log.info("Document is not valid"); - updateFormInvalid(true); - } + protected boolean canSave(Project entity) { + return (StringUtils.isNotBlank(entity.getName()) && + StringUtils.isNotBlank(entity.getContactName()) && + Objects.nonNull(entity.getPartner())) || isAssociatesChanged(); } @Command public void onAddIncoming() { - String page = "~./incoming-invoice-editor.zul"; - Invoice editEntity = invoiceDataModel.createNew(formDocument); - 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"); - validate(getEntityToValidate()); - } + IncomingInvoice entity = invoiceDataModel.createNewIncomingInvoice(); + Editors.doEdit(Editors.INCOMING_INVOICE, entity, modifiedEntity -> { + formDocument.getIncomingInvoices().add(modifiedEntity); + selectedIncomingInvoice = modifiedEntity; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onEditIncoming() throws JsonProcessingException { - String page = "~./incoming-invoice-editor.zul"; - Invoice editEntity = invoiceDataModel.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(); - Set incomingInvoices = formDocument.getIncomingInvoices(); - incomingInvoices.remove(selectedIncomingInvoice); - incomingInvoices.add(modifiedEntity); - selectedIncomingInvoice = modifiedEntity; - BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); - BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); - validate(getEntityToValidate()); - } + IncomingInvoice entity = invoiceDataModel.clone(selectedIncomingInvoice); + Editors.doEdit(Editors.INCOMING_INVOICE, entity, selectedIncomingInvoice, modifiedEntity -> { + Set incomingInvoices = formDocument.getIncomingInvoices(); + incomingInvoices.remove(selectedIncomingInvoice); + incomingInvoices.add(modifiedEntity); + selectedIncomingInvoice = modifiedEntity; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onRemoveIncoming() { - if (selectedIncomingInvoice == null) { - return; + if (Objects.nonNull(selectedIncomingInvoice)) { + formDocument.getIncomingInvoices().remove(selectedIncomingInvoice); + selectedIncomingInvoice = null; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); } - formDocument.getIncomingInvoices().remove(selectedIncomingInvoice); - selectedIncomingInvoice = null; - BindUtils.postNotifyChange(this, "selectedIncomingInvoice"); - BindUtils.postNotifyChange(this.formDocument, "incomingInvoices"); } @Command public void onAddOutgoing() { - String page = "~./outgoing-invoice-editor.zul"; - Invoice editEntity = invoiceDataModel.createNew(formDocument); - 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"); - validate(getEntityToValidate()); - } + OutgoingInvoice entity = invoiceDataModel.createNewOutgoingInvoice(); + Editors.doEdit(Editors.OUTGOING_INVOICE, entity, modifiedEntity -> { + formDocument.getOutgoingInvoices().add(modifiedEntity); + selectedOutgoingInvoice = modifiedEntity; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onEditOutgoing() throws JsonProcessingException { - String page = "~./outgoing-invoice-editor.zul"; - Invoice editEntity = invoiceDataModel.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(); - Set outgoingInvoices = formDocument.getOutgoingInvoices(); - outgoingInvoices.remove(selectedOutgoingInvoice); - outgoingInvoices.add(modifiedEntity); - selectedOutgoingInvoice = modifiedEntity; - BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); - BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); - validate(getEntityToValidate()); - } + OutgoingInvoice entity = invoiceDataModel.clone(selectedOutgoingInvoice); + Editors.doEdit(Editors.OUTGOING_INVOICE, entity, selectedOutgoingInvoice, modifiedEntity -> { + Set outgoingInvoices = formDocument.getOutgoingInvoices(); + outgoingInvoices.remove(selectedOutgoingInvoice); + outgoingInvoices.add(modifiedEntity); + selectedOutgoingInvoice = modifiedEntity; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onRemoveOutgoing() { - if (selectedOutgoingInvoice == null) { - return; + if (Objects.nonNull(selectedOutgoingInvoice)) { + formDocument.getOutgoingInvoices().remove(selectedOutgoingInvoice); + selectedOutgoingInvoice = null; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); + BindUtils.postNotifyChange(this.formDocument, "outgoingInvoice"); } - formDocument.getOutgoingInvoices().remove(selectedOutgoingInvoice); - selectedOutgoingInvoice = null; - BindUtils.postNotifyChange(this, "selectedOutgoingInvoice"); - BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices"); } @Command public void onAddTreasury() { - String page = "~./treasury-editor.zul"; - Treasury editEntity = treasuryDataModel.createNew(formDocument); - Window editorWindow = (Window) Executions.createComponents(page, null, - Collections.singletonMap("formDocument", editEntity)); - editorWindow.addEventListener("onClose", e -> { - if (e.getData() != null) { - formDocument.getTreasuries().add(editEntity); - selectedTreasury = editEntity; - BindUtils.postNotifyChange(this, "selectedTreasury"); - BindUtils.postNotifyChange(this.formDocument, "treasuries"); - validate(getEntityToValidate()); - } + Treasury entity = treasuryDataModel.createNew(); + Editors.doEdit(Editors.TREASURY, entity, modifiedEntity -> { + formDocument.getTreasuries().add(modifiedEntity); + selectedTreasury = modifiedEntity; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedTreasury"); + BindUtils.postNotifyChange(this.formDocument, "treasuries"); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onEditTreasury() { - String page = "~./treasury-editor.zul"; - Treasury editEntity = treasuryDataModel.copy(selectedTreasury); - Map 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(); - Set treasuries = formDocument.getTreasuries(); - treasuries.remove(selectedTreasury); - treasuries.add(modifiedEntity); - selectedTreasury = modifiedEntity; - BindUtils.postNotifyChange(this, "selectedTreasury"); - BindUtils.postNotifyChange(this.formDocument, "treasuries"); - validate(getEntityToValidate()); - } + Treasury entity = treasuryDataModel.clone(selectedTreasury); + Editors.doEdit(Editors.TREASURY, entity, selectedTreasury, modifiedEntity -> { + Set treasuries = formDocument.getTreasuries(); + treasuries.remove(selectedTreasury); + treasuries.add(modifiedEntity); + selectedTreasury = modifiedEntity; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedTreasury"); + BindUtils.postNotifyChange(this.formDocument, "treasuries"); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onRemoveTreasury() { - if (selectedOutgoingInvoice == null) { - return; + if (Objects.nonNull(selectedTreasury)) { + formDocument.getTreasuries().remove(selectedTreasury); + selectedTreasury = null; + validate(formDocument); + BindUtils.postNotifyChange(this, "selectedTreasury"); + BindUtils.postNotifyChange(this.formDocument, "treasuries"); } - formDocument.getTreasuries().remove(selectedTreasury); - selectedTreasury = null; - BindUtils.postNotifyChange(this, "selectedTreasury"); - BindUtils.postNotifyChange(this.formDocument, "treasuries"); } - private void updateFormInvalid(boolean invalid) { - setFormInvalid(invalid); - BindUtils.postNotifyChange(this, "formInvalid"); - } @Destroy public void onDestroy() { @@ -424,11 +304,6 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen eventBus.showServiceRecordsList(ImmutableMap.of("filterAssociate", associate, "filterProject", formDocument)); } - @Command - @NotifyChange("formAssociates") - public void onAfterRenderAssociates() { - } - @NotifyChange("formAssociates") private void initAssociates() { associatesDataModel.listAll(); @@ -442,8 +317,8 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen Associate associate = associatesDataModel.getElementAt(i); boolean exists = projectAssociates.stream() .anyMatch( - pa -> pa.getProject().getId().equals(formDocument.getId()) && - pa.getAssociate().getId().equals(associate.getId()) + pa -> pa.getProjectId().equals(formDocument.getId()) && + pa.getAssociateId().equals(associate.getId()) ); if (exists) { log.info("{} is on project {}", associate.getName(), formDocument.getName()); @@ -459,10 +334,14 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen .anyMatch(e -> !e.getValue().equals(origAssociates.get(e.getKey()))); } + protected boolean areDifferent(Project entity) { + return super.areDifferent(entity) || isAssociatesChanged(); + } + @Command public void onAssociateChecked() { log.info("Associate checked"); - validate(origDocument); + validate(formDocument); } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java index 5fd2e3d..3a266f5 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java @@ -1,7 +1,6 @@ package hu.user.lis.ui.editor; import hu.user.lis.db.ServiceRecord; -import hu.user.lis.services.data.ServiceRecordService; import hu.user.lis.ui.data.AssociateSelectorDataModel; import hu.user.lis.ui.data.ProjectSelectorDataModel; import lombok.Getter; @@ -10,34 +9,29 @@ 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.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.Executions; -import org.zkoss.zk.ui.event.*; -import org.zkoss.zk.ui.select.annotation.VariableResolver; +import org.zkoss.zk.ui.event.InputEvent; +import org.zkoss.zk.ui.event.OpenEvent; +import org.zkoss.zk.ui.event.UploadEvent; import org.zkoss.zk.ui.select.annotation.WireVariable; -import org.zkoss.zkplus.spring.DelegatingVariableResolver; import org.zkoss.zul.Messagebox; -import org.zkoss.zul.Window; import java.util.Objects; @Log4j2 @Getter @Setter -@VariableResolver(DelegatingVariableResolver.class) -public class ServiceRecordEditorModel extends AbstractValidator { - @WireVariable - ServiceRecordService serviceRecordServiceImpl; +public class ServiceRecordEditorModel extends EntityEditorModel { + @WireVariable private AssociateSelectorDataModel associateSelectorDataModel; + @WireVariable private ProjectSelectorDataModel projectSelectorDataModel; - private ServiceRecord formDocument; - private ServiceRecord origDocument; - private boolean formInvalid = true; @Init public void init() { @@ -57,13 +51,13 @@ public class ServiceRecordEditorModel extends AbstractValidator { public void onProjectBandOpen(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { OpenEvent event = (OpenEvent) ctx.getTriggerEvent(); log.info("onProjectBandOpen: {}", event.isOpen()); - projectSelectorDataModel.getLimited(); + projectSelectorDataModel.search(null); } @Command - public void onAssociatetBandChanging(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { + public void onAssociateBandChanging(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { InputEvent event = (InputEvent) ctx.getTriggerEvent(); - log.info("onAssociatetBandChanging: {}", event.getValue()); + log.info("onAssociateBandChanging: {}", event.getValue()); associateSelectorDataModel.search(event.getValue()); } @@ -74,51 +68,15 @@ public class ServiceRecordEditorModel extends AbstractValidator { associateSelectorDataModel.search(null); } - @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); - } - @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); - try { - ServiceRecord newData = serviceRecordServiceImpl.copy(formDocument, property, value); - validate(newData); - } catch (Exception e) { - log.catching(e); - } + protected boolean canSave(ServiceRecord entity) { + return Objects.nonNull(entity.getProject()) && + Objects.nonNull(entity.getAssociate()) && + Objects.nonNull(entity.getWorkDay()) && + StringUtils.isNotBlank(entity.getDescription()) && + entity.getWorkHours() > 0; } - private void validate(ServiceRecord newData) { - updateFormInvalid(false); - if (!Objects.isNull(origDocument) && serviceRecordServiceImpl.toString(origDocument).equals(serviceRecordServiceImpl.toString(newData))) { - log.info("Document not changed"); - updateFormInvalid(true); - return; - } - if (Objects.isNull(newData.getProject()) || - Objects.isNull(newData.getAssociate()) || - Objects.isNull(newData.getWorkDay()) || - StringUtils.isBlank(newData.getDescription()) || - newData.getWorkHours() < 1 - ) { - log.info("Document is not valid"); - updateFormInvalid(true); - } - } - - private void updateFormInvalid(boolean invalid) { - setFormInvalid(invalid); - BindUtils.postNotifyChange(this, "formInvalid"); - } @Command public void onUploadFile(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { @@ -129,13 +87,13 @@ public class ServiceRecordEditorModel extends AbstractValidator { } formDocument.setFile(evt.getMedia().getByteData()); BindUtils.postNotifyChange(this.formDocument, "file"); - validate(serviceRecordServiceImpl.copy(formDocument)); + validate(formDocument); } @Command public void onRemoveFile() { formDocument.setFile(null); BindUtils.postNotifyChange(this.formDocument, "file"); - validate(serviceRecordServiceImpl.copy(formDocument)); + validate(formDocument); } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java index b4f818b..456aa03 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java @@ -1,97 +1,32 @@ package hu.user.lis.ui.editor; import hu.user.lis.db.Treasury; -import hu.user.lis.services.data.TreasuryService; -import lombok.Getter; -import lombok.Setter; import lombok.extern.log4j.Log4j2; 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.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.event.UploadEvent; -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.Messagebox; -import org.zkoss.zul.Window; import java.util.Objects; @Log4j2 -@Getter -@Setter -@VariableResolver(DelegatingVariableResolver.class) -public class TreasuryEditorModel extends AbstractValidator { - private Treasury origDocument; - private Treasury formDocument; - @WireVariable - private TreasuryService treasuryServiceImpl; - private boolean formInvalid = true; +public class TreasuryEditorModel extends EntityEditorModel { @Init public void init() { - log.info("Initialized"); - origDocument = (Treasury) Executions.getCurrent().getArg().get("origDocument"); - formDocument = (Treasury) Executions.getCurrent().getArg().get("formDocument"); - } - - @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); + super.init(); } @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); - try { - Treasury newData = treasuryServiceImpl.copy(formDocument, property, value); - validate(newData); - } catch (Exception e) { - log.catching(e); - } - - } - - private void validate(Treasury newData) { - updateFormInvalid(false); - if (!Objects.isNull(origDocument) && treasuryServiceImpl.toString(origDocument).equals(treasuryServiceImpl.toString(newData))) { - log.info("Document not changed"); - updateFormInvalid(true); - return; - } - - boolean invalid = false; - if (newData.getBuyAmount() <= 0 || - newData.getSellAmount() <= 0 || - Objects.isNull(newData.getValueDate()) || - Objects.isNull(newData.getTransactionDate()) - ) { - invalid = true; - } - - if (invalid) { - log.info("Document is not valid"); - updateFormInvalid(true); - } - } - - private void updateFormInvalid(boolean invalid) { - setFormInvalid(invalid); - BindUtils.postNotifyChange(this, "formInvalid"); + protected boolean canSave(Treasury entity) { + return entity.getBuyAmount() > 0 && + entity.getSellAmount() > 0 && + Objects.nonNull(entity.getValueDate()) && + Objects.nonNull(entity.getTransactionDate()); } @Command @@ -103,13 +38,13 @@ public class TreasuryEditorModel extends AbstractValidator { } formDocument.setFile(evt.getMedia().getByteData()); BindUtils.postNotifyChange(this.formDocument, "file"); - validate(treasuryServiceImpl.copy(formDocument)); + validate(formDocument); } @Command public void onRemoveFile() { formDocument.setFile(null); BindUtils.postNotifyChange(this.formDocument, "file"); - validate(treasuryServiceImpl.copy(formDocument)); + validate(formDocument); } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/AssociatesViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/AssociatesViewModel.java index 7ea7ee7..21f6ba0 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/AssociatesViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/AssociatesViewModel.java @@ -1,47 +1,40 @@ package hu.user.lis.ui.view; import hu.user.lis.db.Associate; +import hu.user.lis.ui.Constants; import hu.user.lis.ui.data.AssociatesDataModel; +import hu.user.lis.ui.data.CachedSpringDataModel; +import hu.user.lis.ui.editor.Editors; import lombok.Getter; import lombok.extern.log4j.Log4j2; -import org.zkoss.bind.annotation.*; -import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.select.Selectors; -import org.zkoss.zk.ui.select.annotation.VariableResolver; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.Init; import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zk.ui.util.Clients; -import org.zkoss.zkplus.spring.DelegatingVariableResolver; -import org.zkoss.zul.Window; - -import java.util.*; @Log4j2 -@VariableResolver(DelegatingVariableResolver.class) -public class AssociatesViewModel { +public class AssociatesViewModel extends FilterActiveViewModel { @WireVariable @Getter AssociatesDataModel associatesDataModel; - @Getter - private Associate selectedEntity; - private boolean filterShowInActive; - private boolean filterShowActive; - private boolean filterShowBoth; - @AfterCompose - public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) { - Selectors.wireComponents(view, this, false); - Selectors.wireEventListeners(view, this); + @Override + CachedSpringDataModel getDataModel() { + return associatesDataModel; + } + + @Override + protected String getNavigation() { + return Constants.NAV_ASSOCIATES; } @Init public void init() { - setFilterShowActive(true); - log.info("Initialized"); + super.init(); Clients.evalJavaScript("pushNav('/associates')"); } - private void refresh() { + protected void refresh() { associatesDataModel.clearSelection(); selectedEntity = null; if (filterShowBoth) { @@ -51,101 +44,23 @@ public class AssociatesViewModel { } } - @Command - @NotifyChange("selectedEntity") - public void onListSelection() { - selectedEntity = null; - Set selections = associatesDataModel.getSelection(); - if (selections.size() == 1) { - selectedEntity = selections.iterator().next(); - log.info("Selected {}", selectedEntity); - } - } - - @Command - public void onAfterRenderList() { - } - @Command public void onAdd() { - String page = "~./associate-editor.zul"; - Associate newEntity = associatesDataModel.createNew(); - Window editorWindow = (Window) Executions.createComponents(page, null, - Collections.singletonMap("formDocument", newEntity)); - editorWindow.addEventListener("onClose", e -> { - if (e.getData() != null) { - log.info("Associate popup result {}", e.getData()); - associatesDataModel.addNew(newEntity); - associatesDataModel.clearSelection(); - refresh(); - associatesDataModel.addToSelection(newEntity); - selectedEntity = newEntity; - } + Associate entity = associatesDataModel.createNew(); + Editors.doEdit(Editors.ASSOCIATE, entity, modifiedEntity -> { + associatesDataModel.save(modifiedEntity); + refresh(); + associatesDataModel.addToSelection(modifiedEntity); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onEdit() { - if (Objects.isNull(selectedEntity)) { - return; - } - String page = "~./associate-editor.zul"; - Associate editEntity = associatesDataModel.copy(selectedEntity); - Map arg = new HashMap<>(); - arg.put("origDocument", selectedEntity); - 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()); - Associate modifiedEntity = (Associate) e.getData(); - associatesDataModel.clearSelection(); - associatesDataModel.save(modifiedEntity); - refresh(); - associatesDataModel.addToSelection(modifiedEntity); - selectedEntity = modifiedEntity; - } + Associate entity = associatesDataModel.clone(selectedEntity); + Editors.doEdit(Editors.ASSOCIATE, entity, selectedEntity, modifiedEntity -> { + associatesDataModel.save(modifiedEntity); + refresh(); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } - - public boolean isFilterShowInActive() { - return filterShowInActive; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowInActive(boolean filterShowInActive) { - this.filterShowBoth = false; - this.filterShowActive = false; - this.filterShowInActive = filterShowInActive; - refresh(); - } - - public boolean isFilterShowActive() { - return filterShowActive; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowActive(boolean filterShowActive) { - this.filterShowBoth = false; - this.filterShowInActive = false; - this.filterShowActive = filterShowActive; - refresh(); - } - - public boolean isFilterShowBoth() { - return this.filterShowBoth; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowBoth(boolean filterShowBoth) { - this.filterShowActive = false; - this.filterShowInActive = false; - this.filterShowBoth = filterShowBoth; - refresh(); - } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/EntityViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/EntityViewModel.java new file mode 100644 index 0000000..dff27a7 --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/EntityViewModel.java @@ -0,0 +1,61 @@ +package hu.user.lis.ui.view; + +import hu.user.lis.services.data.EntityDataService; +import hu.user.lis.ui.data.CachedSpringDataModel; +import lombok.Getter; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.zkoss.bind.annotation.*; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.select.Selectors; +import org.zkoss.zk.ui.select.annotation.VariableResolver; +import org.zkoss.zk.ui.select.annotation.WireVariable; +import org.zkoss.zk.ui.util.Clients; +import org.zkoss.zkplus.spring.DelegatingVariableResolver; + +import java.io.Serializable; +import java.util.Set; + + +@Log4j2 +@VariableResolver(DelegatingVariableResolver.class) +public abstract class EntityViewModel { + + @Getter + T selectedEntity; + @WireVariable + EntityDataService entityDataService; + + abstract CachedSpringDataModel getDataModel(); + + @AfterCompose + public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) { + Selectors.wireComponents(view, this, false); + Selectors.wireEventListeners(view, this); + } + + protected abstract String getNavigation(); + + protected void setNavigation(String nav) { + Clients.evalJavaScript(String.format("pushNav('%s')", nav)); + } + + @Init + public void init() { + if (StringUtils.isNotBlank(getNavigation())) { + setNavigation(getNavigation()); + } + } + + @Command + @NotifyChange("selectedEntity") + public void onListSelection() { + selectedEntity = null; + Set selections = getDataModel().getSelection(); + if (selections.size() == 1) { + selectedEntity = selections.iterator().next(); + log.info("Selected {}", selectedEntity); + } + } + +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/FilterActiveViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/FilterActiveViewModel.java new file mode 100644 index 0000000..aaf959f --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/FilterActiveViewModel.java @@ -0,0 +1,62 @@ +package hu.user.lis.ui.view; + +import lombok.extern.log4j.Log4j2; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; + +import java.io.Serializable; + + +@Log4j2 +public abstract class FilterActiveViewModel extends EntityViewModel { + boolean filterShowInActive; + + boolean filterShowActive; + + boolean filterShowBoth; + + protected abstract void refresh(); + + @Init + public void init() { + super.init(); + setFilterShowActive(true); + } + + public boolean isFilterShowActive() { + return filterShowActive; + } + + @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) + public void setFilterShowActive(boolean filterShowActive) { + this.filterShowBoth = false; + this.filterShowInActive = false; + this.filterShowActive = filterShowActive; + refresh(); + } + + public boolean isFilterShowInActive() { + return filterShowInActive; + } + + @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) + public void setFilterShowInActive(boolean filterShowInActive) { + this.filterShowBoth = false; + this.filterShowActive = false; + this.filterShowInActive = filterShowInActive; + refresh(); + } + + public boolean isFilterShowBoth() { + return this.filterShowBoth; + } + + @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) + public void setFilterShowBoth(boolean filterShowBoth) { + this.filterShowActive = false; + this.filterShowInActive = false; + this.filterShowBoth = filterShowBoth; + refresh(); + } + +} 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 e9ad059..75b4dae 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 @@ -21,6 +21,7 @@ import org.zkoss.zk.ui.select.annotation.WireVariable; import java.util.Map; + @Log4j2 @VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class) @Getter @@ -34,14 +35,13 @@ public class IndexViewModel implements EventListener { private static final String SERVICE_RECORDS_LIST = "~./service-records.zul"; private static final String SETTINGS_LIST = "~./settings.zul"; public static Map NAVIGATION = ImmutableMap.of( - "/partners", PARTNERS_LIST, - "/projects", PROJECTS_LIST, - "/project", PROJECT_EDITOR, - "/associates", ASSOCIATES_LIST, - "/project-associates", PROJECT_ASSOCIATES_LIST, - "/service-records", SERVICE_RECORDS_LIST, - "/settings", SETTINGS_LIST - + Constants.NAV_PARTNERS, PARTNERS_LIST, + Constants.NAV_PROJECTS, PROJECTS_LIST, + Constants.NAV_PROJECT, PROJECT_EDITOR, + Constants.NAV_ASSOCIATES, ASSOCIATES_LIST, + Constants.NAV_PROJECT_ASSOCIATES, PROJECT_ASSOCIATES_LIST, + Constants.NAV_SERVICE_RECORDS, SERVICE_RECORDS_LIST, + Constants.NAV_SETTINGS, SETTINGS_LIST ); @WireVariable BuildProperties buildProperties; 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 cff9f54..eaf1ee3 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 @@ -1,53 +1,40 @@ package hu.user.lis.ui.view; import hu.user.lis.db.Partner; +import hu.user.lis.ui.Constants; +import hu.user.lis.ui.data.CachedSpringDataModel; import hu.user.lis.ui.data.PartnersDataModel; +import hu.user.lis.ui.editor.Editors; import lombok.Getter; import lombok.extern.log4j.Log4j2; -import org.zkoss.bind.annotation.*; -import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.select.Selectors; -import org.zkoss.zk.ui.select.annotation.VariableResolver; -import org.zkoss.zk.ui.select.annotation.Wire; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; import org.zkoss.zk.ui.select.annotation.WireVariable; -import org.zkoss.zk.ui.util.Clients; -import org.zkoss.zkplus.spring.DelegatingVariableResolver; -import org.zkoss.zul.Listbox; -import org.zkoss.zul.Window; - -import java.util.*; @Log4j2 -@VariableResolver(DelegatingVariableResolver.class) -public class PartnersViewModel extends AsyncBaseModel { +public class PartnersViewModel extends FilterActiveViewModel { @WireVariable @Getter PartnersDataModel partnersDataModel; - @Wire - Listbox partnersList; - @Getter - private Partner selectedPartner; - private boolean filterShowInActive; - private boolean filterShowActive; - private boolean filterShowBoth; - @AfterCompose - public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) { - Selectors.wireComponents(view, this, false); - Selectors.wireEventListeners(view, this); + @Override + CachedSpringDataModel getDataModel() { + return partnersDataModel; + } + + @Override + protected String getNavigation() { + return Constants.NAV_PARTNERS; } @Init public void init() { - setFilterShowActive(true); - Clients.evalJavaScript("pushNav('/partners')"); - log.info("Initialized"); + super.init(); } - private void refresh() { + protected void refresh() { partnersDataModel.clearSelection(); - selectedPartner = null; if (filterShowBoth) { partnersDataModel.search(true, true); } else { @@ -60,110 +47,22 @@ public class PartnersViewModel extends AsyncBaseModel { public void search() { } - @Command - @NotifyChange("selectedPartner") - public void onListSelection() { - selectedPartner = null; - Set selections = partnersDataModel.getSelection(); - if (selections.size() == 1) { - selectedPartner = selections.iterator().next(); - log.info("Selected {}", selectedPartner); - } - } - - @Command - public void onAfterRenderPartners() { - } - @Command public void onAdd() { - String page = "~./partner-editor.zul"; - Partner newEntity = partnersDataModel.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.addNew(newEntity); - partnersDataModel.clearSelection(); - refresh(); - partnersDataModel.addToSelection(newEntity); - selectedPartner = newEntity; - -// Optional listItem = partnersList.getItems().stream() -// .filter(li -> ((Partner) li.getValue()).getId().equals(newEntity.getId())) -// .findFirst(); -// if (listItem.isPresent()) { -// Clients.scrollIntoView(listItem.get()); -// } -// registerTask(() -> { -// }); - } + Partner entity = partnersDataModel.createNew(); + Editors.doEdit(Editors.PARTNER, entity, modifiedEntity -> { + partnersDataModel.save(modifiedEntity); + refresh(); + partnersDataModel.addToSelection(modifiedEntity); }); - editorWindow.doModal(); - editorWindow.setFocus(true); } @Command public void onEdit() { - if (Objects.isNull(selectedPartner)) { - return; - } - String page = "~./partner-editor.zul"; - Partner editEntity = partnersDataModel.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(); - partnersDataModel.clearSelection(); - partnersDataModel.save(modifiedEntity); - refresh(); - partnersDataModel.addToSelection(modifiedEntity); - selectedPartner = modifiedEntity; - } + Partner entity = partnersDataModel.clone(selectedEntity); + Editors.doEdit(Editors.PARTNER, entity, selectedEntity, modifiedEntity -> { + partnersDataModel.save(modifiedEntity); + refresh(); }); - editorWindow.doModal(); - editorWindow.setFocus(true); - } - - - public boolean isFilterShowInActive() { - return filterShowInActive; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowInActive(boolean filterShowInActive) { - this.filterShowBoth = false; - this.filterShowActive = false; - this.filterShowInActive = filterShowInActive; - refresh(); - } - - public boolean isFilterShowActive() { - return filterShowActive; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowActive(boolean filterShowActive) { - this.filterShowBoth = false; - this.filterShowInActive = false; - this.filterShowActive = filterShowActive; - refresh(); - } - - public boolean isFilterShowBoth() { - return this.filterShowBoth; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowBoth(boolean filterShowBoth) { - this.filterShowActive = false; - this.filterShowInActive = false; - this.filterShowBoth = filterShowBoth; - refresh(); } } 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 bd4dd88..10ec1ea 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 @@ -2,56 +2,50 @@ package hu.user.lis.ui.view; import hu.user.lis.db.Project; import hu.user.lis.ui.Constants; +import hu.user.lis.ui.data.CachedSpringDataModel; import hu.user.lis.ui.data.ProjectsDataModel; import hu.user.lis.ui.event.EventBus; import lombok.Getter; import lombok.extern.log4j.Log4j2; -import org.zkoss.bind.annotation.*; -import org.zkoss.zk.ui.Component; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.Destroy; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; -import org.zkoss.zk.ui.select.Selectors; -import org.zkoss.zk.ui.select.annotation.VariableResolver; import org.zkoss.zk.ui.select.annotation.WireVariable; -import org.zkoss.zk.ui.util.Clients; -import org.zkoss.zkplus.spring.DelegatingVariableResolver; import java.util.Map; import java.util.Objects; -import java.util.Set; @Log4j2 -@VariableResolver(DelegatingVariableResolver.class) -public class ProjectsViewModel extends AsyncBaseModel implements EventListener { +public class ProjectsViewModel extends FilterActiveViewModel implements EventListener { @WireVariable @Getter ProjectsDataModel projectsDataModel; @WireVariable EventBus eventBus; - @Getter - private Project selectedProject; - private boolean filterShowInActive; - private boolean filterShowActive; - private boolean filterShowBoth; - @AfterCompose - public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) { - Selectors.wireComponents(view, this, false); - Selectors.wireEventListeners(view, this); + @Override + CachedSpringDataModel getDataModel() { + return projectsDataModel; + } + + @Override + protected String getNavigation() { + return Constants.NAV_PROJECTS; } @Init public void init() { - setFilterShowActive(true); + super.init(); eventBus.register(this); - Clients.evalJavaScript("pushNav('/projects')"); - log.info("Initialized"); } - private void refresh() { + protected void refresh() { projectsDataModel.clearSelection(); - selectedProject = null; + selectedEntity = null; if (filterShowBoth) { projectsDataModel.search(true, true); } else { @@ -64,17 +58,6 @@ public class ProjectsViewModel extends AsyncBaseModel implements EventListener { public void search() { } - @Command - @NotifyChange("selectedProject") - public void onListSelection() { - selectedProject = null; - Set selections = projectsDataModel.getSelection(); - if (selections.size() == 1) { - selectedProject = selections.iterator().next(); - log.info("Selected {}", selectedProject); - } - } - @Command public void onAdd() { eventBus.showProjectEditor(null); @@ -82,48 +65,12 @@ public class ProjectsViewModel extends AsyncBaseModel implements EventListener { @Command public void onEdit() { - if (Objects.isNull(selectedProject)) { - return; + if (Objects.nonNull(selectedEntity)) { + Project editEntity = entityDataService.clone(selectedEntity); + eventBus.showProjectEditor(editEntity.getId()); } - Project editEntity = projectsDataModel.copy(selectedProject); - eventBus.showProjectEditor(editEntity.getId()); } - public boolean isFilterShowInActive() { - return filterShowInActive; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowInActive(boolean filterShowInActive) { - this.filterShowBoth = false; - this.filterShowActive = false; - this.filterShowInActive = filterShowInActive; - refresh(); - } - - public boolean isFilterShowActive() { - return filterShowActive; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowActive(boolean filterShowActive) { - this.filterShowBoth = false; - this.filterShowInActive = false; - this.filterShowActive = filterShowActive; - refresh(); - } - - public boolean isFilterShowBoth() { - return this.filterShowBoth; - } - - @NotifyChange({"filterShowActive", "filterShowInActive", "filterShowBoth"}) - public void setFilterShowBoth(boolean filterShowBoth) { - this.filterShowActive = false; - this.filterShowInActive = false; - this.filterShowBoth = filterShowBoth; - refresh(); - } @Override public void onEvent(Event event) { @@ -132,15 +79,9 @@ public class ProjectsViewModel extends AsyncBaseModel implements EventListener { projectsDataModel.clearSelection(); Map args = (Map) event.getData(); Project formDocument = args.get("formDocument"); - if (args.containsKey("origDocument")) { - Project origDocument = args.get("origDocument"); - projectsDataModel.save(formDocument); - } else { - projectsDataModel.addNew(formDocument); - } refresh(); projectsDataModel.addToSelection(formDocument); - selectedProject = formDocument; + selectedEntity = formDocument; } } diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java index 68fa6ab..4c1a0d4 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java @@ -6,6 +6,7 @@ import hu.user.lis.db.Project; import hu.user.lis.db.ServiceRecord; import hu.user.lis.ui.Constants; import hu.user.lis.ui.data.AssociateSelectorDataModel; +import hu.user.lis.ui.data.CachedSpringDataModel; import hu.user.lis.ui.data.ProjectSelectorDataModel; import hu.user.lis.ui.data.ServiceRecordsDataModel; import hu.user.lis.ui.event.EventBus; @@ -18,43 +19,52 @@ import org.zkoss.zk.ui.Executions; 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; import org.zkoss.zkplus.spring.DelegatingVariableResolver; import org.zkoss.zul.Window; import java.util.Collections; import java.util.Map; import java.util.Objects; -import java.util.Set; @Log4j2 @VariableResolver(DelegatingVariableResolver.class) -public class ServiceRecordsViewModel implements EventListener { +public class ServiceRecordsViewModel extends EntityViewModel implements EventListener { @WireVariable @Getter ServiceRecordsDataModel serviceRecordsDataModel; + @WireVariable @Getter private AssociateSelectorDataModel associateSelectorDataModel; + @WireVariable @Getter private ProjectSelectorDataModel projectSelectorDataModel; - @Getter - private ServiceRecord selectedEntity; + @Getter private Project filterProject; + @Getter private Associate filterAssociate; + @WireVariable private EventBus eventBus; + @Override + CachedSpringDataModel getDataModel() { + return serviceRecordsDataModel; + } + + @Override + protected String getNavigation() { + return Constants.NAV_SERVICE_RECORDS; + } + @Init public void init() { - Clients.evalJavaScript("pushNav('/service-records')"); + super.init(); eventBus.register(this); - refresh(); - log.info("Initialized"); } @Command @@ -68,7 +78,7 @@ public class ServiceRecordsViewModel implements EventListener { public void onProjectFilterBandOpen(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) { OpenEvent event = (OpenEvent) ctx.getTriggerEvent(); log.info("onProjectFilterBandOpen: {}", event.isOpen()); - projectSelectorDataModel.getLimited(); + projectSelectorDataModel.search(null); } @Command @@ -96,17 +106,6 @@ public class ServiceRecordsViewModel implements EventListener { public void search() { } - @Command - @NotifyChange("selectedProject") - public void onListSelection() { - selectedEntity = null; - Set selections = serviceRecordsDataModel.getSelection(); - if (selections.size() == 1) { - selectedEntity = selections.iterator().next(); - log.info("Selected {}", selectedEntity); - } - } - @Command public void onAdd() { String page = "~./service-record-editor.zul"; diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java index 28d7ddd..b7e57e7 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java @@ -58,7 +58,7 @@ public class SettingsViewModel extends AsyncBaseModel { } @Command - public void onActiveChecked(@BindingParam("entity") ProjectStatus entity) { + public void onProjectStatusChanged(@BindingParam("entity") ProjectStatus entity) { projectStatusDataModel.save(entity); } diff --git a/lis-ui/src/main/resources/web/associate-editor.zul b/lis-ui/src/main/resources/web/associate-editor.zul index c28b92f..7891406 100644 --- a/lis-ui/src/main/resources/web/associate-editor.zul +++ b/lis-ui/src/main/resources/web/associate-editor.zul @@ -29,7 +29,7 @@