Entity selector unique id usage solved bug, import modified for tests
authorVásáry Dániel <vasary@elgekko.net>
Tue, 16 Jan 2024 08:49:49 +0000 (09:49 +0100)
committerVásáry Dániel <vasary@elgekko.net>
Tue, 16 Jan 2024 08:49:49 +0000 (09:49 +0100)
37 files changed:
lis-app/pom.xml
lis-app/src/test/java/hu/user/lis/service/dataimport/DataImportIT.java [new file with mode: 0644]
lis-db/migrations/scripts/024_modify_short_name_on_partner.sql [new file with mode: 0644]
lis-db/migrations/scripts/025_add_unique_index_to_project_status_name.sql [new file with mode: 0644]
lis-db/migrations/scripts/skratch/024_remove_unique_index_on_partner_vatnr.sql [new file with mode: 0644]
lis-db/src/main/java/hu/user/lis/db/Currency.java
lis-db/src/main/java/hu/user/lis/db/repository/JdbcTemplateRepository.java [new file with mode: 0644]
lis-db/src/main/java/hu/user/lis/db/repository/PartnerRepository.java
lis-db/src/main/java/hu/user/lis/db/repository/ProjectStatusRepository.java
lis-service/pom.xml
lis-service/src/main/java/hu/user/lis/service/dataimport/DataImportService.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/IncomingInvoiceXlsProcessor.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/OutgoingInvoiceXlsProcessor.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/PartnerXlsProcessor.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/ProjectXlsProcessor.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/XlsProcessor.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/InvoiceXlsMapper.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/PartnerXlsMapper.java [new file with mode: 0644]
lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/ProjectXlsMapper.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/auth/CurrentProfile.java
lis-ui/src/main/java/hu/user/lis/ui/view/SpringBindComposer.java [new file with mode: 0644]
lis-ui/src/main/resources/web/associates.zul
lis-ui/src/main/resources/web/editor/import-invoice-approve-editor.zul
lis-ui/src/main/resources/web/editor/import-invoice-assign-editor.zul
lis-ui/src/main/resources/web/editor/project-editor.zul
lis-ui/src/main/resources/web/editor/service-record-editor.zul
lis-ui/src/main/resources/web/editor/treasury-editor.zul
lis-ui/src/main/resources/web/form/invoice-form.zul
lis-ui/src/main/resources/web/import-invoices-approve.zul
lis-ui/src/main/resources/web/import-invoices-assign.zul
lis-ui/src/main/resources/web/import-invoices-suspended.zul
lis-ui/src/main/resources/web/invoices.zul
lis-ui/src/main/resources/web/partners.zul
lis-ui/src/main/resources/web/projects.zul
lis-ui/src/main/resources/web/service-records.zul
lis-ui/src/main/resources/web/settings.zul
lis-ui/src/main/resources/web/widget/entity-selector.zul

index b0d0c6e0784cfbc0c605a908aeb2416b77903442..27b5c974b554949316881c4d1867fe0d4ba75058 100644 (file)
@@ -3,7 +3,7 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <artifactId>lis-app</artifactId>
-    <version>0.1.9-SNAPSHOT</version>
+    <version>0.2.0-SNAPSHOT</version>
     <name>SLY-CRM</name>
     <parent>
         <groupId>hu.user</groupId>
diff --git a/lis-app/src/test/java/hu/user/lis/service/dataimport/DataImportIT.java b/lis-app/src/test/java/hu/user/lis/service/dataimport/DataImportIT.java
new file mode 100644 (file)
index 0000000..c66bd68
--- /dev/null
@@ -0,0 +1,61 @@
+package hu.user.lis.service.dataimport;
+
+import hu.user.lis.db.repository.*;
+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.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.nio.file.Paths;
+
+
+@Log4j2
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@ActiveProfiles("dev")
+@TestPropertySource("classpath:application-dev.yaml")
+//@ActiveProfiles("prod")
+//@TestPropertySource("classpath:application-prod.yaml")
+public class DataImportIT {
+    @Autowired
+    InvoiceImportRepository invoiceImportRepository;
+    @Autowired
+    PaymentRepository paymentRepository;
+    @Autowired
+    ProjectAssociateRepository projectAssociateRepository;
+    @Autowired
+    ServiceRecordRepository serviceRecordRepository;
+    @Autowired
+    TreasuryRepository treasuryRepository;
+    @Autowired
+    InvoiceRepository invoiceRepository;
+    @Autowired
+    ProjectRepository projectRepository;
+    @Autowired
+    EDocumentRepository eDocumentRepository;
+    @Autowired
+    PartnerRepository partnerRepository;
+
+    @Autowired
+    private DataImportService dataImportService;
+
+
+    @Test
+    public void importTest() throws Exception {
+        invoiceImportRepository.deleteAllInBatch();
+        paymentRepository.deleteAllInBatch();
+        projectAssociateRepository.deleteAllInBatch();
+        serviceRecordRepository.deleteAllInBatch();
+        treasuryRepository.deleteAllInBatch();
+        invoiceRepository.deleteAllInBatch();
+        projectRepository.deleteAllInBatch();
+        partnerRepository.deleteAllInBatch();
+
+        dataImportService.importData(Paths.get("c:/work/_spec/slycrm/2024/dataimport.xlsx"));
+    }
+
+}
diff --git a/lis-db/migrations/scripts/024_modify_short_name_on_partner.sql b/lis-db/migrations/scripts/024_modify_short_name_on_partner.sql
new file mode 100644 (file)
index 0000000..e605f7d
--- /dev/null
@@ -0,0 +1,10 @@
+-- // modify short name on partner
+-- Migration SQL that makes the change goes here.
+
+ALTER TABLE partner
+    ALTER COLUMN short_name
+    SET DATA TYPE VARCHAR(100);
+
+-- //@UNDO
+-- SQL to undo the change goes here.
+
diff --git a/lis-db/migrations/scripts/025_add_unique_index_to_project_status_name.sql b/lis-db/migrations/scripts/025_add_unique_index_to_project_status_name.sql
new file mode 100644 (file)
index 0000000..abb9c58
--- /dev/null
@@ -0,0 +1,9 @@
+-- // add unique index to project_status name
+-- Migration SQL that makes the change goes here.
+
+CREATE UNIQUE INDEX UX_PROJECT_STATUS_NAME ON PROJECT_STATUS(name);
+
+-- //@UNDO
+-- SQL to undo the change goes here.
+
+DROP INDEX UX_PROJECT_STATUS_NAME;
diff --git a/lis-db/migrations/scripts/skratch/024_remove_unique_index_on_partner_vatnr.sql b/lis-db/migrations/scripts/skratch/024_remove_unique_index_on_partner_vatnr.sql
new file mode 100644 (file)
index 0000000..f64737b
--- /dev/null
@@ -0,0 +1,7 @@
+-- // remove unique index on partner vatnr
+-- Migration SQL that makes the change goes here.
+DROP INDEX UX_PARTNER_VAT_NR;
+
+-- //@UNDO
+-- SQL to undo the change goes here.
+CREATE UNIQUE INDEX UX_PARTNER_VAT_NR ON PARTNER(vat_nr);
index 4c3d50974e4bbd32737c92a4de2118a67e5abf90..92a51c29473b4f7ad4ad81d2dfa39867ddef9b13 100644 (file)
@@ -5,7 +5,7 @@ import lombok.Getter;
 
 @Getter
 public enum Currency {
-    HUF(0), USD(1), EUR(2);
+    HUF(0), USD(1), EUR(2), GBP(3);
     final int val;
 
     Currency(int val) {
diff --git a/lis-db/src/main/java/hu/user/lis/db/repository/JdbcTemplateRepository.java b/lis-db/src/main/java/hu/user/lis/db/repository/JdbcTemplateRepository.java
new file mode 100644 (file)
index 0000000..737c801
--- /dev/null
@@ -0,0 +1,17 @@
+package hu.user.lis.db.repository;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JdbcTemplateRepository {
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Transactional
+    public void truncateTable(String tableName) {
+        jdbcTemplate.execute(String.format("TRUNCATE TABLE %s IGNORE DELETE TRIGGERS IMMEDIATE", tableName));
+    }
+}
\ No newline at end of file
index daabdb68af015b4dfc13bb5b76c75c8a1a417916..b4a88c6ba8cfd981b66fcb9afd5cb916dd78bdef 100644 (file)
@@ -3,10 +3,13 @@ package hu.user.lis.db.repository;
 import hu.user.lis.db.Partner;
 import org.springframework.data.jpa.repository.JpaRepository;
 
+import java.util.List;
 import java.util.Optional;
 
 public interface PartnerRepository extends JpaRepository<Partner, Long>, PartnerRepositorySearch {
 
     Optional<Partner> findByVatNr(String vatNr);
 
+    List<Partner> findAllByName(String name);
+
 }
index c3087e4d4791a4823e603098b191694f4a8f0463..786f24e8b39b06dc7743c9e628470cab38e8b1a0 100644 (file)
@@ -5,10 +5,13 @@ import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.repository.JpaRepository;
 
 import java.util.List;
+import java.util.Optional;
 
 public interface ProjectStatusRepository extends JpaRepository<ProjectStatus, Long> {
     List<ProjectStatus> findByActiveIsTrue(Sort sort);
 
+    Optional<ProjectStatus> findByName(String name);
+
     long countByActiveIsTrue();
 
     ProjectStatus findByOrder(int order);
index 7f36fada6e1ca3013416c4b98fb28e6ac26aadf4..49e17fd74b298634e2004153aaf73e2172a2c685 100644 (file)
             <artifactId>bcprov-jdk18on</artifactId>
             <version>1.76</version>
         </dependency>
+        <dependency>
+            <groupId>org.dhatim</groupId>
+            <artifactId>fastexcel-reader</artifactId>
+            <version>0.15.7</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-webflux</artifactId>
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/DataImportService.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/DataImportService.java
new file mode 100644 (file)
index 0000000..3e4cccc
--- /dev/null
@@ -0,0 +1,34 @@
+package hu.user.lis.service.dataimport;
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+@Log4j2
+@Service
+public class DataImportService {
+    @Autowired
+    private PartnerXlsProcessor partnerXlsProcessor;
+
+    @Autowired
+    private ProjectXlsProcessor projectXlsProcessor;
+
+    @Autowired
+    private IncomingInvoiceXlsProcessor incomingInvoiceXlsProcessor;
+
+    @Autowired
+    private OutgoingInvoiceXlsProcessor outgoingInvoiceXlsProcessor;
+
+    public void importData(Path inputFile) throws Exception {
+        String fileName = inputFile.getFileName().toString();
+        byte[] xlsData = Files.readAllBytes(inputFile);
+        partnerXlsProcessor.process(fileName, xlsData, 1);
+        projectXlsProcessor.process(fileName, xlsData, 0);
+        incomingInvoiceXlsProcessor.process(fileName, xlsData, 3);
+        outgoingInvoiceXlsProcessor.process(fileName, xlsData, 2);
+    }
+
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/IncomingInvoiceXlsProcessor.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/IncomingInvoiceXlsProcessor.java
new file mode 100644 (file)
index 0000000..af838e0
--- /dev/null
@@ -0,0 +1,65 @@
+package hu.user.lis.service.dataimport;
+
+import hu.user.lis.db.IncomingInvoice;
+import hu.user.lis.db.InvoiceStatus;
+import hu.user.lis.db.Project;
+import hu.user.lis.db.repository.InvoiceRepository;
+import hu.user.lis.db.repository.ProjectRepository;
+import hu.user.lis.service.dataimport.mapper.InvoiceXlsMapper;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Objects;
+
+@Log4j2
+@Component
+public class IncomingInvoiceXlsProcessor extends XlsProcessor<IncomingInvoice> {
+    @Autowired
+    private InvoiceRepository invoiceRepository;
+
+    @Autowired
+    private ProjectRepository projectRepository;
+
+    @Autowired
+    private InvoiceXlsMapper invoiceXlsMapper;
+
+    @Override
+    protected IncomingInvoice mapEntity(Map<String, String> rowData) {
+        IncomingInvoice entity = invoiceXlsMapper.toIncomingInvoiceEntity(rowData);
+        entity.setStatus(InvoiceStatus.ACTIVE);
+        entity.setIncoming(true);
+        return entity;
+    }
+
+    @Override
+    protected boolean isValid(IncomingInvoice entity) {
+        return !StringUtils.isBlank(entity.getHumanId())
+//                && !Objects.isNull(entity.getPartner())
+                && !Objects.isNull(entity.getCurrency())
+                && !Objects.isNull(entity.getCreateDate())
+                && !Objects.isNull(entity.getCompletionDate())
+                && !Objects.isNull(entity.getPaymentDeadline())
+                && entity.getNetAmount() > 0
+                && entity.getGrossAmount() > 0
+                && entity.getVatAmount() > 0;
+    }
+
+    @Override
+    protected void process(IncomingInvoice entity) {
+        invoiceRepository.save(entity);
+        Project project = entity.getProject();
+        if (Objects.nonNull(project)) {
+            if (Objects.isNull(project.getIncomingInvoices())) {
+                project.setIncomingInvoices(new ArrayList<>());
+            }
+            project.getIncomingInvoices().add(entity);
+            projectRepository.save(project);
+        }
+        log.info("Incoming invoice added: {}", entity.getHumanId());
+    }
+
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/OutgoingInvoiceXlsProcessor.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/OutgoingInvoiceXlsProcessor.java
new file mode 100644 (file)
index 0000000..94ad14c
--- /dev/null
@@ -0,0 +1,64 @@
+package hu.user.lis.service.dataimport;
+
+import hu.user.lis.db.InvoiceStatus;
+import hu.user.lis.db.OutgoingInvoice;
+import hu.user.lis.db.Project;
+import hu.user.lis.db.repository.InvoiceRepository;
+import hu.user.lis.db.repository.ProjectRepository;
+import hu.user.lis.service.dataimport.mapper.InvoiceXlsMapper;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Objects;
+
+@Log4j2
+@Component
+public class OutgoingInvoiceXlsProcessor extends XlsProcessor<OutgoingInvoice> {
+    @Autowired
+    private InvoiceRepository invoiceRepository;
+
+    @Autowired
+    private ProjectRepository projectRepository;
+
+    @Autowired
+    private InvoiceXlsMapper invoiceXlsMapper;
+
+    @Override
+    protected OutgoingInvoice mapEntity(Map<String, String> rowData) {
+        OutgoingInvoice entity = invoiceXlsMapper.toOutgoingInvoiceEntity(rowData);
+        entity.setStatus(InvoiceStatus.ACTIVE);
+        return entity;
+    }
+
+    @Override
+    protected boolean isValid(OutgoingInvoice entity) {
+        return !StringUtils.isBlank(entity.getHumanId())
+//                && !Objects.isNull(entity.getPartner())
+                && !Objects.isNull(entity.getCurrency())
+                && !Objects.isNull(entity.getCreateDate())
+                && !Objects.isNull(entity.getCompletionDate())
+                && !Objects.isNull(entity.getPaymentDeadline())
+                && entity.getNetAmount() > 0
+                && entity.getGrossAmount() > 0
+                && entity.getVatAmount() > 0;
+    }
+
+    @Override
+    protected void process(OutgoingInvoice entity) {
+        invoiceRepository.save(entity);
+        Project project = entity.getProject();
+        if (Objects.nonNull(project)) {
+            if (Objects.isNull(project.getOutgoingInvoices())) {
+                project.setOutgoingInvoices(new ArrayList<>());
+            }
+            project.getOutgoingInvoices().add(entity);
+            projectRepository.save(project);
+        }
+        log.info("Outgoing invoice added: {}", entity.getHumanId());
+    }
+
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/PartnerXlsProcessor.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/PartnerXlsProcessor.java
new file mode 100644 (file)
index 0000000..5884eb1
--- /dev/null
@@ -0,0 +1,45 @@
+package hu.user.lis.service.dataimport;
+
+import hu.user.lis.db.Partner;
+import hu.user.lis.db.repository.PartnerRepository;
+import hu.user.lis.service.dataimport.mapper.PartnerXlsMapper;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.Objects;
+
+@Log4j2
+@Component
+public class PartnerXlsProcessor extends XlsProcessor<Partner> {
+    @Autowired
+    private PartnerRepository partnerRepository;
+
+    @Autowired
+    private PartnerXlsMapper partnerXlsMapper;
+
+    @Override
+    protected Partner mapEntity(Map<String, String> rowData) {
+        Partner entity = partnerXlsMapper.toEntity(rowData);
+        if (Objects.isNull(entity.getShortName())) {
+            entity.setShortName(entity.getName());
+        }
+        entity.setActive(true);
+        return entity;
+    }
+
+    @Override
+    protected boolean isValid(Partner entity) {
+        return !StringUtils.isBlank(entity.getName())
+                && !StringUtils.isBlank(entity.getShortName());
+    }
+
+    @Override
+    protected void process(Partner entity) {
+        partnerRepository.save(entity);
+        log.info("Partner added: {}", entity.getName());
+    }
+
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/ProjectXlsProcessor.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/ProjectXlsProcessor.java
new file mode 100644 (file)
index 0000000..8745a3b
--- /dev/null
@@ -0,0 +1,69 @@
+package hu.user.lis.service.dataimport;
+
+import hu.user.lis.db.Project;
+import hu.user.lis.db.ProjectStatus;
+import hu.user.lis.db.repository.ProjectRepository;
+import hu.user.lis.db.repository.ProjectStatusRepository;
+import hu.user.lis.service.dataimport.mapper.ProjectXlsMapper;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Optional;
+
+@Log4j2
+@Component
+public class ProjectXlsProcessor extends XlsProcessor<Project> {
+    public static final String IMPORTED = "IMPORTED";
+    @Autowired
+    private ProjectRepository projectRepository;
+
+    @Autowired
+    private ProjectStatusRepository projectStatusRepository;
+
+    @Autowired
+    private ProjectXlsMapper projectXlsMapper;
+
+    private ProjectStatus defaultProjectStatus;
+
+    @Override
+    public void process(String fileName, byte[] xlsData, int sheetIndex) throws IOException {
+        Optional<ProjectStatus> projectStatus = projectStatusRepository.findByName(IMPORTED);
+        if (projectStatus.isPresent()) {
+            defaultProjectStatus = projectStatus.get();
+        } else {
+            defaultProjectStatus = ProjectStatus.builder().name(IMPORTED).active(true).build();
+            projectStatusRepository.saveAndFlush(defaultProjectStatus);
+        }
+        super.process(fileName, xlsData, sheetIndex);
+    }
+
+    @Override
+    protected Project mapEntity(Map<String, String> rowData) {
+        Project entity = projectXlsMapper.toEntity(rowData);
+        entity.setProjectStatus(defaultProjectStatus);
+        entity.setActive(true);
+
+        if (entity.getHumanId().equals("99000199")) {
+            log.info("");
+        }
+        return entity;
+    }
+
+    @Override
+    protected boolean isValid(Project entity) {
+        return !StringUtils.isBlank(entity.getName())
+                && !StringUtils.isBlank(entity.getHumanId());
+//                && !Objects.isNull(entity.getPartner());
+    }
+
+    @Override
+    protected void process(Project entity) {
+        projectRepository.save(entity);
+        log.info("Project added: {}", entity.getName());
+    }
+
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/XlsProcessor.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/XlsProcessor.java
new file mode 100644 (file)
index 0000000..b718480
--- /dev/null
@@ -0,0 +1,85 @@
+package hu.user.lis.service.dataimport;
+
+import lombok.extern.log4j.Log4j2;
+import org.dhatim.fastexcel.reader.Cell;
+import org.dhatim.fastexcel.reader.ReadableWorkbook;
+import org.dhatim.fastexcel.reader.Row;
+import org.dhatim.fastexcel.reader.Sheet;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Log4j2
+public abstract class XlsProcessor<T> {
+    private List<Cell> headers;
+
+    @Transactional
+    public void process(String fileName, byte[] xlsData, int sheetIndex) throws IOException {
+        try (InputStream is = new ByteArrayInputStream(xlsData);
+             ReadableWorkbook wb = new ReadableWorkbook(is)) {
+            Sheet sheet = wb.getSheet(sheetIndex).orElseThrow(IndexOutOfBoundsException::new);
+            try (Stream<Row> rows = sheet.openStream()) {
+                rows.forEach(row -> {
+                    if (row.getRowNum() == 1) {
+                        headers = getHeaders(row);
+                    } else if (row.getRowNum() == 2) {
+                        //skip
+                    } else {
+                        //log.info("Processing {}", row.getRowNum());
+                        processRow(row);
+                    }
+                });
+            }
+        } catch (IOException e) {
+            log.error("Excel file reading error from {}. System message: {}", fileName, e.getMessage());
+            throw e;
+        }
+    }
+
+    private List<Cell> getHeaders(Row row) {
+        return row.stream().collect(Collectors.toList());
+    }
+
+    private void processRow(Row r) {
+        Map<String, String> rowData = getRowMap(r);
+        T entity = mapEntity(rowData);
+        try {
+            if (isValid(entity)) {
+                process(entity);
+            }
+        } catch (Exception e) {
+            log.error("Processing error for {}", r, e);
+            throw e;
+        }
+    }
+
+    private Map<String, String> getRowMap(Row r) {
+        Map<String, String> rowData = new HashMap<>();
+        r.stream().filter(Objects::nonNull).forEach(c -> {
+            try {
+                if (c.getColumnIndex() < headers.size()) {
+                    String header = headers.get(c.getColumnIndex()).getRawValue();
+                    String data = c.getRawValue();
+                    rowData.put(header, data);
+                }
+            } catch (Exception e) {
+                log.error("Cell error!", e);
+            }
+        });
+        return rowData;
+    }
+
+    protected abstract T mapEntity(Map<String, String> rowData);
+
+    protected abstract boolean isValid(T entity);
+
+    protected abstract void process(T entity);
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/InvoiceXlsMapper.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/InvoiceXlsMapper.java
new file mode 100644 (file)
index 0000000..7d3a44f
--- /dev/null
@@ -0,0 +1,91 @@
+package hu.user.lis.service.dataimport.mapper;
+
+import hu.user.lis.db.IncomingInvoice;
+import hu.user.lis.db.OutgoingInvoice;
+import hu.user.lis.db.Partner;
+import hu.user.lis.db.Project;
+import hu.user.lis.db.repository.PartnerRepository;
+import hu.user.lis.db.repository.ProjectRepository;
+import org.apache.commons.lang3.StringUtils;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Named;
+import org.mapstruct.ReportingPolicy;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.sql.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public abstract class InvoiceXlsMapper {
+    @Autowired
+    private PartnerRepository partnerRepository;
+
+    @Autowired
+    private ProjectRepository projectRepository;
+
+    @Named("mapDate")
+    static Date mapDate(String numberValue) {
+        long longValue = 0;
+        try {
+            longValue = Long.parseLong(numberValue);
+        } catch (Exception ignored) {
+        }
+        long javaDateValue = (longValue - 25569) * 86400 * 1000;
+        return new Date(javaDateValue);
+    }
+
+    @Named("mapPartner")
+    Partner mapPartner(String partnerName) {
+        Partner result = null;
+        List<Partner> partners = partnerRepository.findAllByName(partnerName);
+        if (partners.size() == 1) {
+            result = partners.get(0);
+        }
+        return result;
+    }
+
+    @Named("mapProject")
+    Project mapProject(String humanId) {
+        Project result = null;
+        Optional<Project> project = projectRepository.findByHumanId(humanId);
+        if (project.isPresent()) {
+            result = project.get();
+        }
+        return result;
+    }
+
+    @Named("mapPaid")
+    boolean mapPaid(String paymentDate) {
+        return StringUtils.isNotBlank(paymentDate);
+    }
+
+    @Mapping(source = "Sorszám", target = "humanId")
+    @Mapping(source = "Azonosító", target = "project", qualifiedByName = "mapProject")
+    @Mapping(source = "Partner", target = "partner", qualifiedByName = "mapPartner")
+    @Mapping(source = "Teljesítés dátuma", target = "completionDate", qualifiedByName = "mapDate")
+    @Mapping(source = "Számla kelte", target = "createDate", qualifiedByName = "mapDate")
+    @Mapping(source = "Fizetési határidő", target = "paymentDeadline", qualifiedByName = "mapDate")
+    @Mapping(source = "Nettó összeg", target = "netAmount")
+    @Mapping(source = "Bruttó összeg", target = "grossAmount")
+    @Mapping(source = "ÁFA (HUF)", target = "vatAmount")
+    @Mapping(source = "Devizanem", target = "currency")
+    @Mapping(source = "Kiegyenlítve", target = "paid", qualifiedByName = "mapPaid")
+    public abstract IncomingInvoice toIncomingInvoiceEntity(Map<String, String> xlsRowData);
+
+    @Mapping(source = "Sorszám", target = "humanId")
+    @Mapping(source = "Azonosító", target = "project", qualifiedByName = "mapProject")
+    @Mapping(source = "Partner", target = "partner", qualifiedByName = "mapPartner")
+    @Mapping(source = "Teljesítés dátuma", target = "completionDate", qualifiedByName = "mapDate")
+    @Mapping(source = "Számla kelte", target = "createDate", qualifiedByName = "mapDate")
+    @Mapping(source = "Fizetési határidő", target = "paymentDeadline", qualifiedByName = "mapDate")
+    @Mapping(source = "Nettó összeg", target = "netAmount")
+    @Mapping(source = "Bruttó összeg", target = "grossAmount")
+    @Mapping(source = "ÁFA (HUF)", target = "vatAmount")
+    @Mapping(source = "Devizanem", target = "currency")
+    @Mapping(source = "Kiegyenlítve", target = "paid", qualifiedByName = "mapPaid")
+    public abstract OutgoingInvoice toOutgoingInvoiceEntity(Map<String, String> xlsRowData);
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/PartnerXlsMapper.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/PartnerXlsMapper.java
new file mode 100644 (file)
index 0000000..7fce8d9
--- /dev/null
@@ -0,0 +1,18 @@
+package hu.user.lis.service.dataimport.mapper;
+
+import hu.user.lis.db.Partner;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.ReportingPolicy;
+
+import java.util.Map;
+
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface PartnerXlsMapper {
+    @Mapping(source = "Partner név", target = "name")
+    @Mapping(source = "Rövid név", target = "shortName")
+    @Mapping(source = "Adószám", target = "vatNr")
+    @Mapping(source = "Cím", target = "address")
+    Partner toEntity(Map<String, String> xlsRowData);
+}
diff --git a/lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/ProjectXlsMapper.java b/lis-service/src/main/java/hu/user/lis/service/dataimport/mapper/ProjectXlsMapper.java
new file mode 100644 (file)
index 0000000..4b95430
--- /dev/null
@@ -0,0 +1,42 @@
+package hu.user.lis.service.dataimport.mapper;
+
+import hu.user.lis.db.Partner;
+import hu.user.lis.db.Project;
+import hu.user.lis.db.repository.PartnerRepository;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Named;
+import org.mapstruct.ReportingPolicy;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.List;
+import java.util.Map;
+
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public abstract class ProjectXlsMapper {
+    @Autowired
+    private PartnerRepository partnerRepository;
+
+    @Named("mapPartner")
+    Partner mapPartner(String partnerName) {
+        Partner result = null;
+        List<Partner> partners = partnerRepository.findAllByName(partnerName);
+        if (partners.size() == 1) {
+            result = partners.get(0);
+        }
+        return result;
+    }
+
+    @Mapping(source = "Megnevezés", target = "name")
+    @Mapping(source = "Azonosító", target = "humanId")
+    @Mapping(source = "Kapcsolattartó", target = "contactName")
+    @Mapping(source = "Ügyfél", target = "partner", qualifiedByName = "mapPartner")
+    @Mapping(target = "projectStatus", ignore = true)
+    @Mapping(target = "incomingInvoices", ignore = true)
+    @Mapping(target = "outgoingInvoices", ignore = true)
+    @Mapping(target = "treasuries", ignore = true)
+    public abstract Project toEntity(Map<String, String> xlsRowData);
+
+
+}
index f9ebf1b70eba2e0e73992a2268070c8a6d4c48e0..22b2a77e159b30b8e2416945b6bc6fd5eece78f7 100644 (file)
@@ -15,6 +15,7 @@ import java.util.stream.Collectors;
 
 @Service
 public class CurrentProfile {
+
     @Autowired
     ProfileRepository profileRepository;
     @Getter
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/SpringBindComposer.java b/lis-ui/src/main/java/hu/user/lis/ui/view/SpringBindComposer.java
new file mode 100644 (file)
index 0000000..62ad329
--- /dev/null
@@ -0,0 +1,6 @@
+package hu.user.lis.ui.view;
+
+import org.zkoss.bind.BindComposer;
+
+public class SpringBindComposer extends BindComposer {
+}
index eb0ac5f274e07192ad8a80103099e94dd3ef74a4..95d71a8b023abd918a27ac567cfe0df664b1fcb4 100644 (file)
@@ -28,7 +28,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')">
+                         onSelect="@command('onListSelection')">
                     <listhead sizable="true">
                         <listheader label="Név" sort="auto(name)" align="left"
                                     sortDirection="@load(vm.cols['name'].sortDirection)"/>
@@ -39,7 +39,7 @@
 
                     </listhead>
                     <template name="model">
-                        <listitem>
+                        <listitem onDoubleClick="@command('onEdit')">
                             <listcell label="@load(each.name)"/>
                             <listcell label="@load(each.login)"/>
                             <listcell>
index 3e314d315d1a6da8eb702ed5cddeb02c99fff0e6..b785be5208179480404e920141d4432b0c208344 100644 (file)
@@ -22,7 +22,7 @@
                         <tabpanel>
                             <vlayout hflex="true">
                                 <label value="Projekt"/>
-                                <entity-selector entity="Project" hflex="true"/>
+                                <entity-selector selector_id="approve_project" entity="Project" hflex="true"/>
 
                                 <label value="Leírás"/>
                                 <textbox hflex="true" instant="true"
@@ -30,7 +30,7 @@
                                          forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                 <hlayout>
                                     <label value="Partner"/>
-                                    <entity-selector entity="Partner"/>
+                                    <entity-selector selector_id="approve_partner" entity="Partner"/>
                                     <button label="Szerkesztés" iconSclass="z-icon-edit"
                                             onClick="@command('onEditPartner')"
                                             disabled="@bind(not vm.canEditPartner)"/>
index cb8b99cb5d15352b5afdee74e52177b30fcdadd6..530fb3d5ad1e2b8217164bed68b7a23a1f6e2d6e 100644 (file)
@@ -22,7 +22,7 @@
                         <tabpanel>
                             <vlayout hflex="true">
                                 <label value="Projekt"/>
-                                <entity-selector entity="Project" hflex="true"/>
+                                <entity-selector selector_id="assign_project" entity="Project" hflex="true"/>
                                 <div children="@load(vm.projectSuggestions)">
                                     <template name="children">
                                         <a label="@load(each)"
@@ -36,7 +36,7 @@
                                          forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                 <hlayout>
                                     <label value="Partner"/>
-                                    <entity-selector entity="Partner"/>
+                                    <entity-selector selector_id="assign_partner" entity="Partner"/>
                                     <button label="Szerkesztés" iconSclass="z-icon-edit"
                                             onClick="@command('onEditPartner')"
                                             disabled="@bind(not vm.canEditPartner)"/>
index 9dc13d8128a3bd50bb086d65e775aa62b50ce36d..aa366c19120acaa281a0001fa266772cf9aceff6 100644 (file)
@@ -38,7 +38,8 @@
                                                 <row>
                                                     <vlayout>
                                                         <label value="Ügyfél"/>
-                                                        <entity-selector entity="Partner"/>
+                                                        <entity-selector selector_id="proj_edit_partner"
+                                                                         entity="Partner"/>
                                                     </vlayout>
                                                     <vlayout>
                                                         <label value="Kapcsolattartó"/>
index b2c4e9b2a8a7586c6126d580f0a7be955de46095..c39a2111a07bbd96c5041af7e1172dfd1c69986d 100644 (file)
                             <vlayout hflex="true">
                                 <vlayout hflex="true">
                                     <label value="Projekt"/>
-                                    <entity-selector entity="Project" hflex="true"/>
+                                    <entity-selector selector_id="sr_edit_project" entity="Project" hflex="true"/>
                                 </vlayout>
                                 <hlayout>
                                     <vlayout>
                                         <label value="Munkatárs"/>
-                                        <entity-selector entity="Associate"/>
+                                        <entity-selector selector_id="sr_edit_associate" entity="Associate"/>
                                     </vlayout>
                                     <vlayout>
                                         <label value="Munkanap"/>
index 777734fa4a1154f52d8a0868e261c170207d8274..9731e64ea14e248ba92df47e3ff2dda7d2de9f12 100644 (file)
@@ -1,4 +1,3 @@
-<?component name="partner-selector" inline="true" macroURI="~./partner-selector.zul"?>
 <zk>
     <zscript>
         import hu.user.lis.db.Currency;
index 708a52f138b4b8c9a94a747902624a9553e189fa..4a70986c7f130d0cdb6dc4bbd1d8f336453dc5a2 100644 (file)
@@ -28,7 +28,7 @@
                              forward="onOK=submit.onClick, onCancel=cancel.onClick"
                              disabled="@bind(vm.readonlyForm)"/>
                     <label value="Partner"/>
-                    <entity-selector entity="Partner" readonly="${vm.readonlyForm}"/>
+                    <entity-selector selector_id="inv_editor_partner" entity="Partner" readonly="${vm.readonlyForm}"/>
                     <hlayout>
                         <vlayout>
                             <label value="Sorszám"/>
index a3126f402c00897c9092fde110214cbbf5755f50..6d501f7519f6b01c704b1c86ad4ef03de69bb729 100644 (file)
             <center border="none" flex="true">
                 <listbox vflex="true" model="@load(vm.approveInvoicesDataModel)"
                          autopaging="true" mold="paging" pagingPosition="top" multiple="false"
-                         onSelect="@command('onListSelection')" onDoubleClick="@command('onHandleTask')">
+                         onSelect="@command('onListSelection')">
                     <listhead sizable="true">
                         <listheader label="Azonosító" sort="auto(humanId)" align="left"/>
                         <listheader label="Partner" sort="auto(partner.name)" align="left"/>
                         <listheader label="Javasolt projektek" align="left"/>
                     </listhead>
                     <template name="model">
-                        <listitem>
+                        <listitem onDoubleClick="@command('onHandleTask')">
                             <listcell label="@load(each['invoiceHumanId'])"/>
                             <listcell label="@load(each['partnerName'])"/>
                             <listcell
index 87ca06b71a3ea50004113c72c91482556ffa37b2..d776cbefcf413ef91a7a20e1cad783080bb2623e 100644 (file)
             <center border="none" flex="true">
                 <listbox vflex="true" model="@load(vm.assignInvoicesDataModel)"
                          autopaging="true" mold="paging" pagingPosition="top" multiple="false"
-                         onSelect="@command('onListSelection')" onDoubleClick="@command('onHandleTask')">
+                         onSelect="@command('onListSelection')">
                     <listhead sizable="true">
                         <listheader label="Azonosító" sort="auto(humanId)" align="left"/>
                         <listheader label="Partner" sort="auto(partner.name)" align="left"/>
                         <listheader label="Javasolt projektek" align="left"/>
                     </listhead>
                     <template name="model">
-                        <listitem>
+                        <listitem onDoubleClick="@command('onHandleTask')">
                             <listcell label="@load(each['invoiceHumanId'])"/>
                             <listcell label="@load(each['partnerName'])"/>
                             <listcell
index 1049deedf7bba012ff05f76a56ee0290b6d57b8f..150cb13de18ac8a59c08ae6ab3c82e893c78f912 100644 (file)
@@ -8,11 +8,13 @@
                     <toolbar>
                         <label value="Partner"/>
                         <separator orient="vertical"/>
-                        <entity-selector entity="Partner" style="display: inline-block;" width="300px"/>
+                        <entity-selector selector_id="inv_suspended_partner" entity="Partner"
+                                         style="display: inline-block;" width="300px"/>
                         <space bar="true"/>
                         <label value="Projekt"/>
                         <separator orient="vertical"/>
-                        <entity-selector entity="Project" style="display: inline-block;" width="300px"/>
+                        <entity-selector selector_id="inv_suspended_project" entity="Project"
+                                         style="display: inline-block;" width="300px"/>
 
                         <space bar="true"/>
                         <toolbarbutton label="Iktatás" iconSclass="z-icon-forward"
index c7dbb7336b29a0744c6abb1eb7b92237b6c8a4c3..bcd70a58bccc30575e7ae9c51a608ff72b8d50ee 100644 (file)
                     <toolbar>
                         <label value="Partner"/>
                         <separator orient="vertical"/>
-                        <entity-selector entity="Partner" style="display: inline-block;" width="300px"/>
+                        <entity-selector selector_id="inv_partner" entity="Partner" style="display: inline-block;"
+                                         width="300px"/>
 
                         <space bar="true"/>
 
                         <label value="Projekt"/>
                         <separator orient="vertical"/>
-                        <entity-selector entity="Project" style="display: inline-block;" width="300px"/>
+                        <entity-selector selector_id="inv_project" entity="Project" style="display: inline-block;"
+                                         width="300px"/>
 
                         <space bar="true"/>
 
@@ -77,7 +79,7 @@
             <center border="none" hflex="true" vflex="true">
                 <listbox id="invoicesList" vflex="true" model="@load(vm.invoicesDataModel)"
                          autopaging="true" mold="paging" pagingPosition="top" multiple="false"
-                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')">
+                         onSelect="@command('onListSelection')">
                     <listhead sizable="true">
                         <listheader width="30px" label="Terv" sort="auto(planned)" align="left"
                                     sortDirection="@load(vm.cols['planned'].sortDirection)"/>
                                     sortDirection="@load(vm.cols['incoming'].sortDirection)"/>
                     </listhead>
                     <template name="model">
-                        <listitem>
+                        <listitem onDoubleClick="@command('onEdit')">
                             <listcell>
                                 <a iconSclass="z-icon-map-marker" visible="@load(each.planned)"
                                    style="@load(each.planned ? 'color: gray' : 'color: black')"/>
index d6f1b756d9948fd0b83c5f8e51054acbe917492e..c9cb8454f9551f89da49ef476c02cd8acdcd80d3 100644 (file)
@@ -20,9 +20,9 @@
                 </toolbar>
             </north>
             <center border="none" flex="true">
-                <listbox id="partnersList" vflex="true" model="@load(vm.partnersDataModel)"
+                <listbox vflex="true" model="@load(vm.partnersDataModel)"
                          autopaging="true" mold="paging" pagingPosition="top" multiple="false"
-                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')">
+                         onSelect="@command('onListSelection')">
                     <listhead sizable="true">
                         <listheader label="Név" sort="auto(name)" align="left"
                                     sortDirection="@load(vm.cols['name'].sortDirection)"/>
@@ -35,7 +35,7 @@
 
                     </listhead>
                     <template name="model">
-                        <listitem>
+                        <listitem onDoubleClick="@command('onEdit')">
                             <listcell label="@load(each.name)"/>
                             <listcell label="@load(each.vatNr)"/>
                             <listcell label="@load(each.address)"/>
index 1a311e6b4bac0dbd32da3b27251e09df1e270152..2f9a51fd510a177cfe56ce6749bde2cc6fcfca24 100644 (file)
@@ -20,8 +20,8 @@
             </north>
             <center border="none" flex="true">
                 <listbox vflex="true" model="@load(vm.projectsDataModel)"
-                         autopaging="true" pagingPosition="top" multiple="false"
-                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')">
+                         autopaging="true" mold="paging" pagingPosition="top" multiple="false"
+                         onSelect="@command('onListSelection')">
                     <listhead sizable="true">
                         <listheader label="Azonosító" sort="auto(humanId)" align="left"
                                     sortDirection="@load(vm.cols['humanId'].sortDirection)"/>
@@ -37,7 +37,7 @@
                                     sortDirection="@load(vm.cols['active'].sortDirection)"/>
                     </listhead>
                     <template name="model">
-                        <listitem>
+                        <listitem onDoubleClick="@command('onEdit')">
                             <listcell label="@load(each.humanId)"/>
                             <listcell label="@load(each.partner.name)"/>
                             <listcell label="@load(each.projectStatus.name)"/>
index 0076d2347c1bae0a0fb6ef4afdea3838f2591dfe..20202f1b015ffe4044b988f2f588ab657dc3c786 100644 (file)
                     <separator orient="vertical"/>
                     <label value="Projekt"/>
                     <separator orient="vertical"/>
-                    <entity-selector entity="Project" style="display: inline-block;" width="300px"/>
+                    <entity-selector selector_id="sr_project" entity="Project" style="display: inline-block;"
+                                     width="300px"/>
                     <separator orient="vertical"/>
                     <label value="Munkatárs"/>
                     <separator orient="vertical"/>
-                    <entity-selector entity="Associate" style="display: inline-block;"/>
+                    <entity-selector selector_id="sr_associate" entity="Associate" style="display: inline-block;"/>
                     <toolbarbutton label="Nincs szűrés" iconSclass="z-icon-ban" onClick="@command('onClearFilters')"/>
                 </toolbar>
             </north>
             <center border="none" flex="true">
                 <listbox vflex="true" model="@load(vm.serviceRecordsDataModel)"
-                         autopaging="true" mold="paging" pagingPosition="top" onSelect="@command('onListSelection')"
-                         onDoubleClick="@command('onEdit')">
+                         autopaging="true" mold="paging" pagingPosition="top" onSelect="@command('onListSelection')">
                     <listhead sizable="true">
                         <listheader label="Projekt azonosító" sort="auto(project.humanId)" align="left"
                                     sortDirection="@load(vm.cols['project.humanId'].sortDirection)"/>
@@ -46,7 +46,7 @@
                         <listheader label="Aláírt" align="left"/>
                     </listhead>
                     <template name="model">
-                        <listitem>
+                        <listitem onDoubleClick="@command('onEdit')">
                             <listcell label="@load(each.project.humanId)"/>
                             <listcell label="@load(each.project.name)"/>
                             <listcell label="@load(each.project.partner.name)"/>
index 9fb401042b12ce5929673bea72c8e3e9a42a7518..e296048577b45dec269d78f881026372e94ca1ad 100644 (file)
@@ -24,7 +24,7 @@
                     </north>
                     <center border="none" flex="true">
                         <listbox vflex="true" model="@load(vm.projectStatusDataModel)"
-                                 autopaging="true" pagingPosition="top" multiple="false"
+                                 autopaging="true" mold="paging" pagingPosition="top" multiple="false"
                                  selectedItem="@bind(vm.selectedProjectStatus)">
                             <listhead sizable="true">
                                 <listheader label="Sorrend" align="left"/>
index 666405e896d45156cce2627c45bc8d9a8f103f40..357c1cd0b4a6c52290c23cec083d32c65353a19f 100644 (file)
@@ -1,44 +1,47 @@
 <zk xmlns:c="client">
     <hlayout viewModel="@id('vmEntity') @init(vm.getEntitySelectorRouter().getEntitySelectorModel(entity))">
-        <bandbox id="entityBandBox" autodrop="true" hflex="true" mold="rounded"
+
+        <bandbox id="entityBandBox_${selector_id}" autodrop="true" hflex="true" mold="rounded"
                  value="@load(vmEntity.selectedEntity) @converter(vmEntity.displayConverter)"
                  onChanging="@command('onEntityBandChanging')" onOpen="@command('onEntityBandOpen')"
                  forward="onOK=submit.onClick, onCancel=cancel.onClick" disabled="${readonly}" readonly="${readonly}">
             <attribute c:name="_doKeyDown">
                 <![CDATA[
                             function (evt) {
+                                var selectorId = "${selector_id}";
+                                console.log("this", this);
+
+                                var bandBox = zk.$("$entityBandBox_" + selectorId);
+                                var bandPopup = zk.$("$entityBandPopup_" + selectorId);
+
                                 var keyCode = evt.keyCode;
-                                console.log(keyCode, zk.$("$entityBandBox").getValue());
-                                if (keyCode == 13){
-                                    //zk.$.notify("Hello World");
-                                    zk.$("$entityBandBox").close();
-                                    zk.$("$entityBandBox").focus();
+
+                                console.log("keyCode", keyCode);
+
+                                if (keyCode == 13 || keyCode == 27){
+                                    bandBox.close();
+                                    bandBox.focus();
                                     return;
                                 }
+
                                 if (keyCode == 40){
-                                    if (!zk.$("$entityBandBox").isOpen()) {
-                                        zk.$("$entityBandBox").open();
-                                        zAu.send(new zk.Event(zk.Widget.$('$entityBandBox'), "onOpen", {'open': true}, {toServer:true}));
+                                    if (!bandBox.isOpen()) {
+                                        console.log("Opening");
+                                        zAu.send(new zk.Event(bandBox, "onOpen", {'open': true}, {toServer:true}));
+                                        bandBox.open();
                                     }
-                                    console.log("List", zk.$("$entityList"));
-
-                                    zk.$("$entityList").focus();
-                                    return;
-                                }
-                                if (keyCode == 27){
-                                    zk.$("$entityBandBox").close()
-                                    zk.$("$entityBandBox").focus();
+                                    bandPopup.focus();
                                     return;
                                 }
                             }
                         ]]>
             </attribute>
-            <bandpopup width="400px">
-                <listbox id="entityList" height="250px"
+            <bandpopup id="entityBandPopup_${selector_id}" width="400px">
+                <listbox id="entityList_${selector_id}" height="250px"
                          model="@bind(vmEntity.dataModel)"
                          selectedItem="@bind(vmEntity.selectedEntity)"
-                         onClick="entityBandBox.close()"
-                         onDoubleClick="entityBandBox.close()">
+                         onClick="entityBandBox_${selector_id}.close()"
+                         onDoubleClick="entityBandBox_${selector_id}.close()">
                     <listhead visible="false">
                         <listheader label="name" vflex="max"/>
                     </listhead>