Transition to JPA finished
authorelgekko <vasary@elgekko.net>
Mon, 17 Jul 2023 09:13:06 +0000 (11:13 +0200)
committerelgekko <vasary@elgekko.net>
Mon, 17 Jul 2023 09:13:06 +0000 (11:13 +0200)
75 files changed:
KB.md
TODO.txt
lis-app/pom.xml
lis-app/src/main/resources/application-dev.yaml
lis-app/src/main/resources/application.yaml
lis-app/src/test/java/hu/user/lis/ReflectionsIT.java [new file with mode: 0644]
lis-app/src/test/java/hu/user/lis/RepositoryIT.java
lis-db/migrations/scripts/004_create_default_user.sql [new file with mode: 0644]
lis-db/pom.xml
lis-db/src/main/java/hu/user/lis/db/Associate.java
lis-db/src/main/java/hu/user/lis/db/EDocument.java
lis-db/src/main/java/hu/user/lis/db/IncomingInvoice.java [new file with mode: 0644]
lis-db/src/main/java/hu/user/lis/db/Invoice.java
lis-db/src/main/java/hu/user/lis/db/OutgoingInvoice.java [new file with mode: 0644]
lis-db/src/main/java/hu/user/lis/db/Partner.java
lis-db/src/main/java/hu/user/lis/db/Project.java
lis-db/src/main/java/hu/user/lis/db/ProjectAssociate.java
lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java
lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java
lis-db/src/main/java/hu/user/lis/db/Treasury.java
lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepositorySearchImpl.java
lis-db/src/main/java/hu/user/lis/db/repository/ProjectAssociateRepository.java
lis-services/pom.xml
lis-services/src/main/java/hu/user/lis/services/api/ProjectApi.java
lis-services/src/main/java/hu/user/lis/services/data/AssociateEntityDataService.java [new file with mode: 0644]
lis-services/src/main/java/hu/user/lis/services/data/DataService.java
lis-services/src/main/java/hu/user/lis/services/data/DataServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/EntityDataService.java [new file with mode: 0644]
lis-services/src/main/java/hu/user/lis/services/data/ProjectAssociateServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/ReflectEntity.java [new file with mode: 0644]
lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/TreasuryServiceImpl.java
lis-ui/src/main/java/hu/user/lis/ui/Constants.java
lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java
lis-ui/src/main/java/hu/user/lis/ui/converter/DateToStringConverter.java
lis-ui/src/main/java/hu/user/lis/ui/data/AssociatesDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/CachedDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/PartnersDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectAssociatesDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectsDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/data/TreasuryDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/AssociateEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/EditCompleted.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/editor/Editors.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/editor/EntityEditorModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/PartnerEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/AssociatesViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/EntityViewModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/view/FilterActiveViewModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/view/IndexViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/PartnersViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java
lis-ui/src/main/resources/web/associate-editor.zul
lis-ui/src/main/resources/web/associates.zul
lis-ui/src/main/resources/web/incoming-invoice-editor.zul
lis-ui/src/main/resources/web/login.zul
lis-ui/src/main/resources/web/outgoing-invoice-editor.zul
lis-ui/src/main/resources/web/partner-editor.zul
lis-ui/src/main/resources/web/partners.zul
lis-ui/src/main/resources/web/project-editor.zul
lis-ui/src/main/resources/web/projects.zul
lis-ui/src/main/resources/web/service-record-editor.zul
lis-ui/src/main/resources/web/settings.zul
lis-ui/src/main/resources/web/treasury-editor.zul
runConfigurations/lis-db2.run.xml [new file with mode: 0644]

diff --git a/KB.md b/KB.md
index 51658e8fffe64c32cb42faa55e8b78c1661a6ba7..45f3d9bab89e9472f12b819e273d87f283aee085 100644 (file)
--- 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
 
index 5e7706ecc2c6cf811a1c7817a67dedc17816fe1e..2f9642210661bbd73ae0bd2a3b31462fbdbbdc1e 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
     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
index e64e7d23ac9663280d9c0b77c18e1bb2dbf30cad..21101b8ce9d305d73448fccd3c44fde9084b3f59 100644 (file)
             <artifactId>lis-services</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>3.24.2</version>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
index ecc9b0fecb59f0f82104eb3242f2f692c8f5a70e..ed967ffd40319f81f98455bbfbc543b573da90b2 100644 (file)
@@ -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
index 507a9d2586a38e4450d5dad9c7446fdca441bcb8..3f2d8e42464d0269190e5976d4bfb41242a1769a 100644 (file)
@@ -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 (file)
index 0000000..fbdfb3a
--- /dev/null
@@ -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<Project> 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<String> l1 = Arrays.asList("a", "b");
+        List<String> 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));
+    }
+}
index af2701c65842cf272de1e9834c888be87439b714..25bed1ad6876e1e3cc9fa68d4201284def66f245 100644 (file)
@@ -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<Project> 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 (file)
index 0000000..77589d4
--- /dev/null
@@ -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';
+
index 15486c6302ce7ef87842983a52128b76600f8578..ea1d6f8dcae3da31de9b2573503932cea6f4905e 100644 (file)
@@ -33,7 +33,7 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-jpa</artifactId>
-            <version>3.0.4</version>
+            <version>2.7.13</version>
         </dependency>
         <dependency>
             <groupId>com.ibm.db2</groupId>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-core</artifactId>
+            <version>5.6.15.Final</version>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
index 6561526b14bc8ee3a30849db64bdb17aec4dfdee..6a679bf135be4314c7e0c53bf2be6451776c68ac 100644 (file)
@@ -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;
index 6bfb7c1d00b8b6ea40446a774d0e832165e6d0c5..e10c0cae016c5c747bd1cf1050c858944ef5c4e1 100644 (file)
@@ -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 (file)
index 0000000..eab1d7d
--- /dev/null
@@ -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;
+    }
+}
index 4ee7af12b71e0d99ec10d33b72e5860c562388b3..38d0bf15149e0cb26d61f945c519b7e21df74ee1 100644 (file)
@@ -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 (file)
index 0000000..0f55a1e
--- /dev/null
@@ -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 {
+}
index 1e1020c902d55c1bf0ad84ba51559685eb2fa7a1..4e3e5dc5c6cfa9b5f98ace72b11cb0ed8c2d9d9f 100644 (file)
@@ -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;
index ff1d8dacc86db7e4283c592d6584bf2aecb9a970..3492c53fec1d8782c79026dff49423a98f7fe848 100644 (file)
@@ -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<Invoice> incomingInvoices;
-    @OneToMany(mappedBy = "project", fetch = FetchType.EAGER)
+    Set<IncomingInvoice> 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<Invoice> outgoingInvoices;
-    @OneToMany(mappedBy = "project", fetch = FetchType.EAGER)
+    Set<OutgoingInvoice> outgoingInvoices;
+
+    @OneToMany(targetEntity = Treasury.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
+    @JoinColumn(name = "projectId", referencedColumnName = "id")
+    @Fetch(FetchMode.JOIN)
     @JsonIncludeProperties({"id"})
     Set<Treasury> treasuries;
+
+    String name;
+
+    String humanId;
+
+    String contactName;
+
+    boolean active;
 }
index 277d7f07114f049ab272cf689ac16480b8abaa31..8cf69ce39e3684f0fd3ccbb3558fb18d6324b124 100644 (file)
@@ -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;
 }
index 39e8918ecfb64ebd71ee9a06c62f779676f1479d..759cc6a19df63f5ee06605d6d0761fdde58cf1c7 100644 (file)
@@ -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;
index 7a4785a60253be428fb2061904178876731f80f7..b0c1c114a1e3c3a8c18955e0a7a750de3a014dc2 100644 (file)
@@ -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;
index 60114e6699007787b62d730ba8960c7972ec5dd1..acf1836d84c4994729bed66dfb96831221481fba 100644 (file)
@@ -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;
+
 }
index 67e57f01846b1cb04428a6da8b590fbe66e52a8f..03eef0f77e229f42ab1b95d97bb7a36d0ec8951a 100644 (file)
@@ -26,7 +26,7 @@ public class PartnerRepositorySearchImpl implements PartnerRepositorySearch {
         if (StringUtils.isNotBlank(partialSearch)) {
             List<Predicate> orPredicates = new ArrayList<>();
             orPredicates.add(cb.like(cb.lower(root.get("name")), "%" + partialSearch.toLowerCase() + "%"));
-            orPredicates.add(cb.like(cb.lower(root.get("vat_nr")), "%" + partialSearch.toLowerCase() + "%"));
+            orPredicates.add(cb.like(cb.lower(root.get("vatNr")), "%" + partialSearch.toLowerCase() + "%"));
             orPredicates.add(cb.like(cb.lower(root.get("address")), "%" + partialSearch.toLowerCase() + "%"));
             predicates.add(cb.or(orPredicates.toArray(new Predicate[]{})));
         }
index eace4a2644a28f2697fc83af190622eb100a0dc9..2a990153d2af67021b41c33e6dac5e959c1b3351 100644 (file)
@@ -10,4 +10,5 @@ public interface ProjectAssociateRepository extends JpaRepository<ProjectAssocia
 
     Long countByProjectId(Long projectId);
 
+    void deleteByProjectId(Long projectId);
 }
index d7a39580f65ae2efb6a80018a23e4838d0e013f1..f83f053f33c249ef700b57650530d0ba9a9ce28c 100644 (file)
@@ -33,5 +33,9 @@
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.skyscreamer</groupId>
+            <artifactId>jsonassert</artifactId>
+        </dependency>
     </dependencies>
 </project>
index 2baadf56252e185ce445ea721193b1109cfc03a4..2ba6d76bff5f48de6b0b2e63eb99f37f9d234625 100644 (file)
@@ -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<Project, ProjectRepository, ProjectService
     @Override
     protected void afterSave(List<Project> entities) {
         entities.forEach(p -> {
-            Set<Invoice> incomingInvoices = p.getIncomingInvoices();
+            Set<IncomingInvoice> incomingInvoices = p.getIncomingInvoices();
             if (Objects.nonNull(incomingInvoices)) {
                 incomingInvoices.forEach(i -> {
-                    i.setProject(p);
+//                    i.setProject(p);
                     invoiceRepository.save(i);
                 });
             }
 
-            Set<Invoice> outgoingInvoices = p.getOutgoingInvoices();
+            Set<OutgoingInvoice> outgoingInvoices = p.getOutgoingInvoices();
             if (Objects.nonNull(outgoingInvoices)) {
                 outgoingInvoices.forEach(i -> {
-                    i.setProject(p);
+//                    i.setProject(p);
                     invoiceRepository.save(i);
                 });
             }
 
             Set<Treasury> 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 (file)
index 0000000..24789b3
--- /dev/null
@@ -0,0 +1,6 @@
+package hu.user.lis.services.data;
+
+import hu.user.lis.db.Associate;
+
+public class AssociateEntityDataService extends EntityDataService<Associate> {
+}
index 2812f6065a2ed434f68617eca545ee1633ec7fcc..c842c5c0dc945bdc63679cfadb3731d0d83e7c09 100644 (file)
@@ -4,10 +4,4 @@ import java.util.List;
 
 public interface DataService<T> {
     List<T> getAll();
-
-    T copy(T sourceEntity);
-
-    T copy(T sourceEntity, String property, Object value);
-
-    String toString(T sourceEntity);
 }
index e3a21b5eca7fcd65ea56f5167965955aea74659e..43cbe5bc687e774ca372770723fb52280d6438bc 100644 (file)
@@ -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<T> implements DataService<T> {
     @Override
     public abstract List<T> 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 (file)
index 0000000..9220531
--- /dev/null
@@ -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<T extends Serializable> {
+    @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;
+    }
+
+}
index 2f9f61321fc4f21d287f430d5827fd3ca1c88f73..2746568e49b2cb93b3ec2a2c1b284fe7010fc778 100644 (file)
@@ -32,7 +32,7 @@ public class ProjectAssociateServiceImpl extends DataServiceImpl<ProjectAssociat
 
     @Override
     public ProjectAssociate createNew(Project project, Associate associate) {
-        return ProjectAssociate.builder().project(project).associate(associate).build();
+        return ProjectAssociate.builder().projectId(project.getId()).associateId(associate.getId()).build();
     }
 
     @Override
@@ -47,11 +47,11 @@ public class ProjectAssociateServiceImpl extends DataServiceImpl<ProjectAssociat
 
     @Override
     public void update(Project project, Map<Associate, Boolean> associates) {
-        List<ProjectAssociate> deleteEntities = entities.stream().filter(pa -> pa.getProject().getId().equals(project.getId())).collect(Collectors.toList());
+        List<ProjectAssociate> 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<ProjectAssociat
             int associatesCount = RandomUtils.nextInt(1, 5);
             for (int i = 0; i < associatesCount; i++) {
                 Associate associate = associateService.getRandom();
-                ProjectAssociate entity = ProjectAssociate.builder().project(project).associate(associate).build();
+                ProjectAssociate entity = ProjectAssociate.builder().projectId(project.getId()).associateId(associate.getId()).build();
                 result.add(entity);
             }
         }
index e099ccc0e8723c6752518234a9850bd87391c089..a8b78a4478d2aa13c466a18d5cf03a3c6dccdc94 100644 (file)
@@ -104,8 +104,8 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> 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<Project> 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<Project> 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<Project> 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<Project> 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<Project> 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 (file)
index 0000000..099a13e
--- /dev/null
@@ -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<String, Method> getGetters(Class clazz) {
+        Map<String, Method> 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<String, Method> getters1 = getGetters(ob1.getClass());
+        Map<String, Method> 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
index 753dca48bae9811aac80d2fa17825cdeac5787a1..fa2f33b9c1a870a36918e84e50985917dbdc60dc 100644 (file)
@@ -90,15 +90,15 @@ public class ServiceRecordServiceImpl extends DataServiceImpl<ServiceRecord> imp
         projectService.getAll().forEach(p -> {
             int serviceRecordCount = RandomUtils.nextInt(3, 10);
 
-            List<ProjectAssociate> projectAssociates = projectAssociateService.getAll().stream().filter(e -> e.getProject().getId().equals(p.getId())).collect(Collectors.toList());
+            List<ProjectAssociate> 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<ServiceRecord> 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)
index 7b8d1dacce268f06e173ff47fe337b7c863861c0..f952ba79c7554c40d6f44be0d9b172a8c0a0a4c0 100644 (file)
@@ -1,6 +1,5 @@
 package hu.user.lis.services.data;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import hu.user.lis.db.Currency;
 import hu.user.lis.db.Treasury;
 import lombok.extern.log4j.Log4j2;
@@ -18,12 +17,13 @@ import java.util.concurrent.TimeUnit;
 @Log4j2
 public class TreasuryServiceImpl extends DataServiceImpl<Treasury> implements TreasuryService {
     int GENERATE_COUNT = 500;
+
     @Autowired
     DataGeneratorService dataGeneratorService;
-    @Autowired
-    ObjectMapper mapper;
+
     private List<Treasury> entities;
 
+
     @Override
     public List<Treasury> getAll() {
         if (entities == null) {
index adf357ba1725520a1da9e1f8560a680c1472c219..f669779988b21f3451d304f3d994d300ac835b57 100644 (file)
@@ -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";
+
 }
index 8fb3891426e07cb0a742fcb922152d7e8ebeaabc..ac9de864b13b2dacf73b1906d8d462cd462569c5 100644 (file)
@@ -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()
index 0957f288b988d95cd687db41a91e4d253b81f852..69af5bf24ca2ac44539850816d63ebec7508a3d7 100644 (file)
@@ -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<String, Date, Listcell> {
     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
index 11c283da7600a264399a5089486f2f45493851e3..26da552c69f417b14b26c93428d5939e39ef7084 100644 (file)
@@ -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<Associate> {
     @Autowired
     AssociateRepository associateRepository;
+
     @Autowired
     AssociateService associateService;
+
+    @Autowired
+    EntityDataService<Associate> associateDataService;
     private String partialName;
+
     private boolean listAll;
+
     private boolean filterShowInActive;
+
     private boolean filterShowActive;
 
     @Override
@@ -78,12 +86,8 @@ public class AssociatesDataModel extends CachedSpringDataModel<Associate> {
         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) {
index 2e151140bedbe7eaabf1586b223a09f8beb8174a..09cc5afa371a2b3e97cd017f0cfc83e1bd31437e 100644 (file)
@@ -25,9 +25,7 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
     private FieldComparator sortComparator;
 
     public CachedDataModel() {
-        //reinit();
-        log.info("Initialized");
-        setMultiple(true);
+        setMultiple(false);
     }
 
     public void reset() {
index e674fd5916bc83ec4f0dd6277c1e54fe66637b2e..3e5d23b108b3d4e948ca14f85fc526d94e81de99 100644 (file)
@@ -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<IncomeMargin> {
     public void recalculate(Project project) {
         clear();
         Map<Currency, Double> balances = new HashMap<>();
-        Set<Invoice> outgoingInvoices = project.getOutgoingInvoices();
+        Set<OutgoingInvoice> outgoingInvoices = project.getOutgoingInvoices();
         if (Objects.nonNull(outgoingInvoices)) {
             for (Invoice invoice : outgoingInvoices) {
                 addBalance(balances, invoice.getCurrency(), invoice.getNetAmount());
             }
         }
 
-        Set<Invoice> incomingInvoices = project.getIncomingInvoices();
+        Set<IncomingInvoice> incomingInvoices = project.getIncomingInvoices();
         if (Objects.nonNull(incomingInvoices)) {
             for (Invoice invoice : incomingInvoices) {
                 substractBalance(balances, invoice.getCurrency(), invoice.getNetAmount());
index 53cbd050fef1dcbaea63177470057f888cd3bb40..3ea164d663ec3efce40fa105fea1b6d34c7cd281 100644 (file)
@@ -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<IncomingInvoice> incomingInvoiceDataService;
+    @Autowired
+    EntityDataService<OutgoingInvoice> 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);
+    }
 }
index c5f62c3ce1e06988b40b9fdcfd8c5936cbb43307..a819a645666783fdc77df2db293432b4d9dbd5bc 100644 (file)
@@ -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<Partner> {
     @Autowired
     PartnerService partnerService;
 
+    @Autowired
+    EntityDataService<Partner> partnerDataService;
+
     private String partialSearch;
 
     private boolean listAll;
@@ -75,12 +79,8 @@ public class PartnersDataModel extends CachedSpringDataModel<Partner> {
         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) {
index afb8a1cd288c7e6c0da15e013568b015169fec11..17fbf0ecbcbaf7d7b1255d57df5ec82199669745 100644 (file)
@@ -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<Long, Boolean> formAssociates) {
+        projectAssociateRepository.deleteByProjectId(project.getId());
+        List<ProjectAssociate> 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);
+        }
+    }
 }
index 058b7141ebab1b35586313273f62c03a8dbad5ef..f674fe16a9219fc3e9eaa0f2f8a3b32043b678b1 100644 (file)
@@ -43,10 +43,4 @@ public class ProjectSelectorDataModel extends CachedSpringDataModel<Project> {
         this.partialSearch = partialSearch;
         super.reset();
     }
-
-    public void getLimited() {
-        log.info("Searching projects using limit {}", SEARCH_LIMIT);
-        this.partialSearch = null;
-        super.reset();
-    }
 }
index 4869f7869696258fbcfacaf5a6ee6334f2865344..3bc9694d98addd83fd7febbd4d87e906367f38f5 100644 (file)
@@ -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<Project> {
     @Autowired
     ProjectStatusDataModel projectStatusDataModel;
 
+    @Autowired
+    EntityDataService<Project> projectDataService;
+
     private String partialName;
 
     private boolean listAll;
@@ -76,11 +79,7 @@ public class ProjectsDataModel extends CachedSpringDataModel<Project> {
     }
 
     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<Project> {
                 .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<Project> {
     public Project getById(Long id) {
         return projectRepository.findById(id).orElseThrow(EntityNotFoundException::new);
     }
+
+    public Project clone(Project entity) {
+        return projectDataService.clone(entity);
+    }
 }
index b232010a0e77832532cc8bf7feece1531aabcdcf..309b87ab82ffaaebe8571f91a166d2878f384709 100644 (file)
@@ -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<Treasury> 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);
     }
+
 }
index fd29d54aeca0f54923cc00fb28c70fe9c4343c02..1eec92a1f83fa8f1a3938c48ddfda6edcccd55e4 100644 (file)
@@ -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<Associate> {
 
     @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 (file)
index 0000000..2f4cd35
--- /dev/null
@@ -0,0 +1,7 @@
+package hu.user.lis.ui.editor;
+
+public interface EditCompleted<E> {
+
+    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 (file)
index 0000000..87a28a9
--- /dev/null
@@ -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 <E> void doEdit(String page, E entity, EditCompleted<E> editCompleted) {
+        doEdit(page, entity, null, editCompleted);
+    }
+
+    public static <E> void doEdit(String page, E entity, E original, EditCompleted<E> editCompleted) {
+        Map<String, E> 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 (file)
index 0000000..ca9927d
--- /dev/null
@@ -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<T extends Serializable> extends AbstractValidator {
+
+    @Getter
+    T formDocument;
+
+    T origDocument;
+
+    @Getter
+    boolean saveEnabled;
+
+    @WireVariable
+    EntityDataService<T> 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);
+    }
+
+}
index 12ffefe196b9cfcfed062416248865fc6b9db5bb..1f897d20fb3fd8acd4304b1c76e13e18cbe5c68d 100644 (file)
@@ -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<Invoice> {
+
     @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);
     }
 }
index 1a7dcbb5e2c4a5ee8d186aab8fbe0a29349ee0b5..959344419c5fddec94879d3d54e567fc9a2b9be1 100644 (file)
@@ -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<Partner> {
     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");
-    }
 }
index d231e4d782e2a2f783e99f800d87824a36d01980..0128c81952468a85917f2a96851176f67d0e847e 100644 (file)
@@ -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<Project> 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<Long, Boolean> origAssociates;
 
     private Map<Long, Boolean> 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<String, Object> 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<Invoice> 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<IncomingInvoice> 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<String, Object> 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<Invoice> 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<OutgoingInvoice> 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<String, Object> arg = ImmutableMap.of("origDocument", selectedTreasury, "formDocument", editEntity);
-        Window editorWindow = (Window) Executions.createComponents(page, null, arg);
-        editorWindow.addEventListener("onClose", e -> {
-            if (e.getData() != null) {
-                Treasury modifiedEntity = (Treasury) e.getData();
-                Set<Treasury> 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<Treasury> 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);
     }
 
 }
index 5fd2e3de398dd7289706f8c92975a26fb505cc23..3a266f5013bdd84b3139e02c7fae244eb235b202 100644 (file)
@@ -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<ServiceRecord> {
+
     @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);
     }
 }
index b4f818bdf273accf334777c90d5441160cb088d5..456aa033ee573774aa13b9ebc9c61b60c360e7e1 100644 (file)
@@ -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<Treasury> {
 
     @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);
     }
 }
index 7ea7ee7ca05c204d4e1c852ae28b5b92eebc9978..21f6ba088d1bcab10af26680624a7ff03bdfbd1e 100644 (file)
@@ -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<Associate> {
     @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<Associate> 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<Associate> 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<String, Object> 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 (file)
index 0000000..dff27a7
--- /dev/null
@@ -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<T extends Serializable> {
+
+    @Getter
+    T selectedEntity;
+    @WireVariable
+    EntityDataService<T> entityDataService;
+
+    abstract CachedSpringDataModel<T> 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<T> 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 (file)
index 0000000..aaf959f
--- /dev/null
@@ -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<T extends Serializable> extends EntityViewModel<T> {
+    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();
+    }
+
+}
index e9ad059a67a7873987c0ab08f66bd135ea52efb1..75b4daeb9fb341fba4d30cf352576433f56b4cca 100644 (file)
@@ -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<String, String> 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;
index cff9f541f4c3a8ca6903b7ddaf508861eef4aa0a..eaf1ee342582d8f0e761d7b956977b03c67161de 100644 (file)
@@ -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<Partner> {
     @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<Partner> 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<Partner> 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> 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<String, Object> 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();
     }
 }
index bd4dd889629d353763b66edf64ed6128f8c48d41..10ec1ea43b9cde1d8b55275419cc79410f0bfd12 100644 (file)
@@ -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<Project> 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<Project> 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<Project> 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<String, Project> args = (Map<String, Project>) 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;
         }
     }
 
index 68fa6abb3775feacad9be65e6ad6592e53ba31c4..4c1a0d4c89f5f8c0a8d4d86dcace589c0869659f 100644 (file)
@@ -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<ServiceRecord> 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<ServiceRecord> 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<ServiceRecord> 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";
index 28d7ddd7286ad8cbc575a26aef9cd41eaad6bb5f..b7e57e7d115bea9e7dbf015b052de45875064fd5 100644 (file)
@@ -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);
     }
 
index c28b92fe0d3113ff32f03f06258af3bb3b104216..789140602daca7ec343f850689c24a48470a1c8f 100644 (file)
@@ -29,7 +29,7 @@
                                 </hlayout>
                                 <label value="Havi önköltség"/>
                                 <doublebox value="@bind(vm.formDocument.monthlyCost) @validator(vm)"
-                                           format="locale:hu-HU" instant="true"
+                                           format="#,###.##" locale="hu" instant="true"
                                            forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                 <label value="Aktív"/>
                                 <checkbox mold="switch" checked="@bind(vm.formDocument.active) @validator(vm)"/>
             <south border="none" flex="true" style="text-align: right; padding: 10px">
                 <hlayout>
                     <button id="cancel" label="Bezár"
-                            onClick="@command('onCloseWindow', target=associatePopup, select=false)"/>
+                            onClick="@command('onCloseWindow', target=associatePopup, save=false)"/>
                     <button id="submit" label="Mentés"
-                            onClick="@command('onCloseWindow', target=associatePopup, select=true)"
-                            disabled="@bind(vm.formInvalid)"/>
+                            onClick="@command('onCloseWindow', target=associatePopup, save=true)"
+                            disabled="@bind(not vm.saveEnabled)"/>
                 </hlayout>
             </south>
         </borderlayout>
index 66e46a86326312fdfc81642ff00acf9ae241b612..fde58d3a2171bec56a62b72a458a9f59bf6626bd 100644 (file)
@@ -26,8 +26,7 @@
             <center border="none" flex="true">
                 <listbox vflex="true" model="@load(vm.associatesDataModel)"
                          autopaging="true" mold="paging" pagingPosition="top" multiple="false"
-                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')"
-                         onAfterRender="@command('onAfterRenderList')">
+                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')">
                     <listhead sizable="true">
                         <listheader label="Név" sort="auto(name)" align="left"/>
                         <listheader label="Login" sort="auto(login)" align="left"/>
index fe8e52ed63bf91a9f6fa24a885caa9d025079a02..e825016275e9dc9b32316082d4d8fde955f71b2d 100644 (file)
                                     <vlayout>
                                         <label value="Nettó összeg"/>
                                         <doublebox value="@bind(vm.formDocument.netAmount) @validator(vm)"
-                                                   format="locale:hu-HU" instant="true"
+                                                   format="#,###.##" locale="hu" instant="true"
                                                    onChange="@command('onNetAmountChange')"
                                                    forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                     <vlayout>
                                         <label value="Bruttó összeg"/>
                                         <doublebox value="@bind(vm.formDocument.grossAmount) @validator(vm)"
-                                                   format="locale:hu-HU" instant="true"
+                                                   format="#,###.##" locale="hu" instant="true"
                                                    forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                     <vlayout>
                                         <label value="ÁFA"/>
                                         <doublebox value="@bind(vm.formDocument.vatAmount) @validator(vm)"
-                                                   format="locale:hu-HU" instant="true"
+                                                   format="#,###.##" locale="hu" instant="true"
                                                    forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                 </hlayout>
             <south border="none" flex="true" style="text-align: right; padding: 10px;">
                 <hlayout>
                     <button id="cancel" label="Bezár"
-                            onClick="@command('onCloseWindow', target=invoicePopup, select=false)"/>
+                            onClick="@command('onCloseWindow', target=invoicePopup, save=false)"/>
                     <button id="submit" label="Mentés"
-                            onClick="@command('onCloseWindow', target=invoicePopup, select=true)"
-                            disabled="@bind(vm.formInvalid)"/>
+                            onClick="@command('onCloseWindow', target=invoicePopup, save=true)"
+                            disabled="@bind(not vm.saveEnabled)"/>
                 </hlayout>
             </south>
         </borderlayout>
index e6a13ee2e24773d16d64ddac3905d8365fa90137..8f4a36ce2166a3c31fdc2a1fb44a7575a334165a 100644 (file)
@@ -45,7 +45,7 @@
                 <rows>
                     <row>
                         <label value="User"/>
-                        <textbox name="username" value="user1" hflex="true"/>
+                        <textbox name="username" value="user" hflex="true"/>
                     </row>
                     <row>
                         <label value="Password"/>
index d5e4c9ad61aa07a7d69c6a3586a29f88597d3d84..e2ead4919eda6f5b28de5819fc602705319577f5 100644 (file)
                                     <vlayout>
                                         <label value="Nettó összeg"/>
                                         <doublebox value="@bind(vm.formDocument.netAmount) @validator(vm)"
-                                                   format="locale:hu-HU" instant="true"
+                                                   format="#,###.##" locale="hu" instant="true"
                                                    onChange="@command('onNetAmountChange')"
                                                    forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                     <vlayout>
                                         <label value="Bruttó összeg"/>
                                         <doublebox value="@bind(vm.formDocument.grossAmount) @validator(vm)"
-                                                   format="locale:hu-HU" instant="true"
+                                                   format="#,###.##" locale="hu" instant="true"
                                                    forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                     <vlayout>
                                         <label value="ÁFA"/>
                                         <doublebox value="@bind(vm.formDocument.vatAmount) @validator(vm)"
-                                                   format="locale:hu-HU" instant="true"
+                                                   format="#,###.##" locale="hu" instant="true"
                                                    forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                 </hlayout>
             <south border="none" flex="true" style="text-align: right; padding: 10px;">
                 <hlayout>
                     <button id="cancel" label="Bezár"
-                            onClick="@command('onCloseWindow', target=invoicePopup, select=false)"/>
+                            onClick="@command('onCloseWindow', target=invoicePopup, save=false)"/>
                     <button id="submit" label="Mentés"
-                            onClick="@command('onCloseWindow', target=invoicePopup, select=true)"
-                            disabled="@bind(vm.formInvalid)"/>
+                            onClick="@command('onCloseWindow', target=invoicePopup, save=true)"
+                            disabled="@bind(not vm.saveEnabled)"/>
                 </hlayout>
             </south>
         </borderlayout>
index e89729d2d3eb2bc8a38918e69c34fc8c38f82cbe..91ec89516140c535a29e8835b3e428d1c2a558eb 100644 (file)
             <south border="none" flex="true" style="text-align: right; padding: 10px">
                 <hlayout>
                     <button id="cancel" label="Bezár"
-                            onClick="@command('onCloseWindow', target=partnerPopup, select=false)"/>
+                            onClick="@command('onCloseWindow', target=partnerPopup, save=false)"/>
                     <button id="submit" label="Mentés"
-                            onClick="@command('onCloseWindow', target=partnerPopup, select=true)"
-                            disabled="@bind(vm.formInvalid)"/>
+                            onClick="@command('onCloseWindow', target=partnerPopup, save=true)"
+                            disabled="@bind(not vm.saveEnabled)"/>
                 </hlayout>
             </south>
         </borderlayout>
index a2cda008b9a2c996d124ec7278cb66c14c67a37d..7c2bb352458ba5589b03db01816c31337aa379c4 100644 (file)
@@ -7,7 +7,7 @@
                 <toolbar>
                     <toolbarbutton label="Hozzáadás" iconSclass="z-icon-plus" onClick="@command('onAdd')"/>
                     <toolbarbutton label="Szerkesztés" iconSclass="z-icon-edit" onClick="@command('onEdit')"
-                                   disabled="@load(empty vm.selectedPartner)"/>
+                                   disabled="@load(empty vm.selectedEntity)"/>
                     <separator orient="vertical"/>
                     <toolbarbutton mode="toggle" iconSclass="z-icon-check" label="Aktív"
                                    checked="@bind(vm.filterShowActive)"/>
@@ -20,8 +20,7 @@
             <center border="none" flex="true">
                 <listbox id="partnersList" vflex="true" model="@load(vm.partnersDataModel)"
                          autopaging="true" mold="paging" pagingPosition="top" multiple="false"
-                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')"
-                         onAfterRender="@command('onAfterRenderPartners')">
+                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')">
                     <listhead sizable="true">
                         <listheader label="Név" sort="auto(name)" align="left"/>
                         <listheader label="Adószám" sort="auto(vatNr)" align="left"/>
index 95a7efdf4f1b056078e3c207599b582d63cde0f0..153ca3dba60d5669f71996f222b31217f60f687a 100644 (file)
                                                 <row>
                                                     <vlayout>
                                                         <label value="Státusz"/>
-                                                        <!--                                                        <combobox model="@load(vm.projectStatusDataModel)"-->
-                                                        <!--                                                                  width="100%" readonly="true"-->
-                                                        <!--                                                                  selectedItem="@bind(vm.formDocument.projectStatus) @validator(vm)"-->
-                                                        <!--                                                                  forward="onOK=submit.onClick, onCancel=cancel.onClick">-->
-                                                        <!--                                                            <template name="model">-->
-                                                        <!--                                                                <comboitem label="${each.name}"/>-->
-                                                        <!--                                                            </template>-->
-                                                        <!--                                                        </combobox>-->
                                                         <selectbox model="@load(vm.projectStatusDataModel)"
                                                                    width="100%"
                                                                    selectedIndex="@bind(vm.formDocument.projectStatus) @converter(vm.projectStatusConverter) @validator(vm)"
                                          onDoubleClick="@command('onEditOutgoing')"
                                          forward="onOK=submit.onClick, onCancel=cancel.onClick">
                                     <listhead sizable="true">
-                                        <listheader label="Vevő" align="left"/>
-                                        <listheader label="Sorszám" align="left"/>
-                                        <listheader label="Megnevezés" align="left"/>
-                                        <listheader label="Nettó összeg" align="right" style="text-align: center"/>
-                                        <listheader label="Pénznem" align="left"/>
-                                        <listheader label="Teljesítés" align="left"/>
-                                        <listheader label="Fizetési határidő" align="left"/>
+                                        <listheader label="Vevő" sort="auto(partner.name)" align="left"/>
+                                        <listheader label="Sorszám" sort="auto(humanId)" align="left"/>
+                                        <listheader label="Megnevezés" sort="auto(title)" align="left"/>
+                                        <listheader label="Nettó összeg" sort="auto(netAmount)" align="right"
+                                                    style="text-align: center"/>
+                                        <listheader label="Pénznem" sort="auto(currency)" align="left"/>
+                                        <listheader label="Teljesítés" sort="auto(completionDate)" align="left"/>
+                                        <listheader label="Fizetési határidő" sort="auto(paymentDeadline)"
+                                                    align="left"/>
                                     </listhead>
                                     <template name="model">
                                         <listitem>
                                          onDoubleClick="@command('onEditIncoming')"
                                          forward="onOK=submit.onClick, onCancel=cancel.onClick">
                                     <listhead sizable="true">
-                                        <listheader label="Szállító" align="left"/>
-                                        <listheader label="Sorszám" align="left"/>
-                                        <listheader label="Megnevezés" align="left"/>
-                                        <listheader label="Nettó összeg" align="right" style="text-align: center"/>
-                                        <listheader label="Pénznem" align="left"/>
-                                        <listheader label="Teljesítés" align="left"/>
-                                        <listheader label="Fizetési határidő" align="left"/>
+                                        <listheader label="Szállító" sort="auto(partner.name)" align="left"/>
+                                        <listheader label="Sorszám" sort="auto(humanId)" align="left"/>
+                                        <listheader label="Megnevezés" sort="auto(title)" align="left"/>
+                                        <listheader label="Nettó összeg" sort="auto(netAmount)" align="right"
+                                                    style="text-align: center"/>
+                                        <listheader label="Pénznem" sort="auto(currency)" align="left"/>
+                                        <listheader label="Teljesítés" sort="auto(completionDate)" align="left"/>
+                                        <listheader label="Fizetési határidő" sort="auto(paymentDeadline)"
+                                                    align="left"/>
                                     </listhead>
                                     <template name="model">
                                         <listitem>
                                     </auxhead>
 
                                     <listhead sizable="true">
-                                        <listheader label="Összeg" align="right" style="text-align: center"/>
-                                        <listheader label="Pénznem" align="left"/>
-                                        <listheader label="Összeg" align="right" style="text-align: center"/>
-                                        <listheader label="Pénznem" align="left"/>
-                                        <listheader label="Üzletkötés dátuma"
+                                        <listheader label="Összeg" sort="auto(sellAmount)" align="right"
+                                                    style="text-align: center"/>
+                                        <listheader label="Pénznem" sort="auto(sellCurrency)" align="left"/>
+                                        <listheader label="Összeg" sort="auto(buyAmount)" align="right"
+                                                    style="text-align: center"/>
+                                        <listheader label="Pénznem" sort="auto(buyCurrency)" align="left"/>
+                                        <listheader label="Üzletkötés dátuma" sort="auto(transactionDate)"
                                                     align="left"/>
-                                        <listheader label="Értéknap" align="left"/>
+                                        <listheader label="Értéknap" sort="auto(valueDate)" align="left"/>
                                     </listhead>
                                     <template name="model">
                                         <listitem>
                             <listbox model="@load(vm.serviceRecordsDataModel)"
                                      forward="onOK=submit.onClick, onCancel=cancel.onClick">
                                 <listhead sizable="true">
-                                    <listheader label="Munkatárs" align="left"/>
-                                    <listheader label="Óraszám" align="right" style="text-align: center"/>
-                                    <listheader label="Ráfordítás" align="right" style="text-align: center"/>
+                                    <listheader label="Munkatárs" sort="auto(associate.name)" align="left"/>
+                                    <listheader label="Óraszám" sort="auto(workHours)" align="right"
+                                                style="text-align: center"/>
+                                    <listheader label="Ráfordítás" sort="auto(cost)" align="right"
+                                                style="text-align: center"/>
                                 </listhead>
                                 <template name="model">
                                     <listitem>
                         <!--                                    </north>-->
                         <panelchildren>
                             <listbox model="@load(vm.associatesDataModel)"
-                                     multiple="false"
-                                     onAfterRender="@command('onAfterRenderAssociates')">
+                                     multiple="false">
                                 <listhead sizable="true">
                                     <listheader hflex="min" label="Tag" align="left"/>
-                                    <listheader label="Név" align="left"/>
-                                    <listheader label="Login" align="left"/>
+                                    <listheader label="Név" sort="auto(name)" align="left"/>
+                                    <listheader label="Login" sort="auto(login)" align="left"/>
                                 </listhead>
                                 <template name="model">
                                     <listitem>
             <south border="none" flex="true" style="text-align: right; padding: 10px;">
                 <hlayout>
                     <button id="cancel" label="Mégsem"
-                            onClick="@command('onEndEdit', target=projectEditor, select=false)"/>
+                            onClick="@command('onEndEdit', target=projectEditor, save=false)"/>
                     <button id="submit" label="Mentés"
-                            onClick="@command('onEndEdit', target=projectEditor, select=true)"
-                            disabled="@bind(vm.formInvalid)"/>
+                            onClick="@command('onEndEdit', target=projectEditor, save=true)"
+                            disabled="@bind(not vm.saveEnabled)"/>
                 </hlayout>
             </south>
         </borderlayout>
index de30d7ae7886476582c49d28326044d5a1d5b9a0..c13ed10dee7255f7a3297aa5436bd93e12436036 100644 (file)
@@ -6,7 +6,7 @@
                 <toolbar>
                     <toolbarbutton label="Hozzáadás" iconSclass="z-icon-plus" onClick="@command('onAdd')"/>
                     <toolbarbutton label="Szerkesztés" iconSclass="z-icon-edit" onClick="@command('onEdit')"
-                                   disabled="@load(empty vm.selectedProject)"/>
+                                   disabled="@load(empty vm.selectedEntity)"/>
                     <separator orient="vertical"/>
                     <toolbarbutton mode="toggle" iconSclass="z-icon-check" label="Aktív"
                                    checked="@bind(vm.filterShowActive)"/>
@@ -18,8 +18,8 @@
             </north>
             <center border="none" flex="true">
                 <listbox id="partnersList" vflex="true" model="@load(vm.projectsDataModel)"
-                         autopaging="true" pagingPosition="top" onSelect="@command('onListSelection')"
-                         onDoubleClick="@command('onEdit')">
+                         autopaging="true" pagingPosition="top" multiple="false"
+                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')">
                     <listhead sizable="true">
                         <listheader label="Azonosító" sort="auto(humanId)" align="left"/>
                         <listheader label="Ügyfél" sort="auto(partner.name)" align="left"/>
index 7cc8c8e7aab32aeba34328984eae4e4003c12dac..20f41bebc962b0bc68eb22119fddad81516da986 100644 (file)
             <south border="none" flex="true" style="text-align: right; padding: 10px">
                 <hlayout>
                     <button id="cancel" label="Bezár"
-                            onClick="@command('onCloseWindow', target=serviceRecordPopup, select=false)"/>
+                            onClick="@command('onCloseWindow', target=serviceRecordPopup, save=false)"/>
                     <button id="submit" label="Mentés"
-                            onClick="@command('onCloseWindow', target=serviceRecordPopup, select=true)"
-                            disabled="@bind(vm.formInvalid)"/>
+                            onClick="@command('onCloseWindow', target=serviceRecordPopup, save=true)"
+                            disabled="@bind(not vm.saveEnabled)"/>
                 </hlayout>
             </south>
         </borderlayout>
index 7877d77d998496361f3527264c7450a44676cb0b..2563234abe6bdd6af0e873e098b66b8c28115d71 100644 (file)
                                 <label value="@load(each.order)"/>
                             </listcell>
                             <listcell>
-                                <textbox inplace="true" instant="true" width="100%" value="@bind(each.name)"/>
+                                <textbox inplace="true" width="100%" value="@bind(each.name)"
+                                         onChange="@command('onProjectStatusChanged', entity=each)"/>
                             </listcell>
                             <listcell>
                                 <checkbox checked="@bind(each.active)"
-                                          onCheck="@command('onActiveChecked', entity=each)"/>
+                                          onCheck="@command('onProjectStatusChanged', entity=each)"/>
                             </listcell>
                         </listitem>
                     </template>
index f78ebf840865c5675e3eda98ef788c784291428a..f71473eaa189999f48c79258ef2ee4f9fe8331b2 100644 (file)
@@ -30,7 +30,7 @@
                                         <vlayout>
                                             <label value="Összeg"/>
                                             <doublebox value="@bind(vm.formDocument.sellAmount) @validator(vm)"
-                                                       format="locale:hu-HU" instant="true"
+                                                       format="#,###.##" locale="hu" instant="true"
                                                        forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                         </vlayout>
                                     </hlayout>
@@ -47,7 +47,7 @@
                                         <vlayout>
                                             <label value="Összeg"/>
                                             <doublebox value="@bind(vm.formDocument.buyAmount) @validator(vm)"
-                                                       format="locale:hu-HU" instant="true"
+                                                       format="#,###.##" locale="hu" instant="true"
                                                        forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                         </vlayout>
                                     </hlayout>
             <south border="none" flex="true" style="text-align: right; padding: 10px;">
                 <hlayout>
                     <button id="cancel" label="Bezár"
-                            onClick="@command('onCloseWindow', target=invoicePopup, select=false)"/>
+                            onClick="@command('onCloseWindow', target=invoicePopup, save=false)"/>
                     <button id="submit" label="Mentés"
-                            onClick="@command('onCloseWindow', target=invoicePopup, select=true)"
-                            disabled="@bind(vm.formInvalid)"/>
+                            onClick="@command('onCloseWindow', target=invoicePopup, save=true)"
+                            disabled="@bind(not vm.saveEnabled)"/>
                 </hlayout>
             </south>
         </borderlayout>
diff --git a/runConfigurations/lis-db2.run.xml b/runConfigurations/lis-db2.run.xml
new file mode 100644 (file)
index 0000000..527568a
--- /dev/null
@@ -0,0 +1,63 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="lis-db2" type="docker-deploy" factoryName="docker-image" server-name="Docker">
+    <deployment type="docker-image">
+      <settings>
+        <option name="imageTag" value="ibmcom/db2:latest" />
+        <option name="attachToContainerNeeded" value="true" />
+        <option name="command" value="" />
+        <option name="containerName" value="lis-db2" />
+        <option name="envVars">
+          <list>
+            <DockerEnvVarImpl>
+              <option name="name" value="DB2INST1_PASSWORD" />
+              <option name="value" value="password" />
+            </DockerEnvVarImpl>
+            <DockerEnvVarImpl>
+              <option name="name" value="DB2INSTANCE" />
+              <option name="value" value="db2admin" />
+            </DockerEnvVarImpl>
+            <DockerEnvVarImpl>
+              <option name="name" value="LICENSE" />
+              <option name="value" value="accept" />
+            </DockerEnvVarImpl>
+            <DockerEnvVarImpl>
+              <option name="name" value="DBNAME" />
+              <option name="value" value="lis" />
+            </DockerEnvVarImpl>
+            <DockerEnvVarImpl>
+              <option name="name" value="TO_CREATE_SAMPLEDB" />
+              <option name="value" value="true" />
+            </DockerEnvVarImpl>
+            <DockerEnvVarImpl>
+              <option name="name" value="PERSISTENT_HOME" />
+              <option name="value" value="true" />
+            </DockerEnvVarImpl>
+          </list>
+        </option>
+        <option name="portBindings">
+          <list>
+            <DockerPortBindingImpl>
+              <option name="containerPort" value="50000" />
+              <option name="hostPort" value="50000" />
+            </DockerPortBindingImpl>
+            <DockerPortBindingImpl>
+              <option name="containerPort" value="27017" />
+              <option name="hostPort" value="27017" />
+            </DockerPortBindingImpl>
+          </list>
+        </option>
+        <option name="commandLineOptions" value="-itd --privileged=true" />
+        <option name="showCommandPreview" value="true" />
+        <option name="volumeBindings">
+          <list>
+            <DockerVolumeBindingImpl>
+              <option name="containerPath" value="/database" />
+              <option name="hostPath" value="/Docker" />
+            </DockerVolumeBindingImpl>
+          </list>
+        </option>
+      </settings>
+    </deployment>
+    <method v="2" />
+  </configuration>
+</component>
\ No newline at end of file