Excel export completed an all views
authorVásáry Dániel <vasary@elgekko.net>
Sat, 2 Mar 2024 23:19:19 +0000 (00:19 +0100)
committerVásáry Dániel <vasary@elgekko.net>
Sat, 2 Mar 2024 23:19:19 +0000 (00:19 +0100)
17 files changed:
sly-crm-app/src/main/resources/application-prod.yaml
sly-crm-app/src/test/java/hu/user/lis/EventIT.java
sly-crm-ui/src/main/java/hu/user/lis/ui/TypeUtils.java [new file with mode: 0644]
sly-crm-ui/src/main/java/hu/user/lis/ui/data/AssignInvoicesDataModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/data/AssociatesDataModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/data/InvoicesDataModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/data/PartnersDataModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/data/ProjectsDataModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/data/ServiceRecordsDataModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/data/common/CachedDataModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/view/PartnersViewModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/view/ProjectsViewModel.java
sly-crm-ui/src/main/java/hu/user/lis/ui/view/common/EntityViewModel.java
sly-crm-ui/src/main/resources/web/associates.zul
sly-crm-ui/src/main/resources/web/invoices.zul
sly-crm-ui/src/main/resources/web/projects.zul
sly-crm-ui/src/main/resources/web/service-records.zul

index 036708a7c50324b78abfb0f3443f0333887d781c..502cf240bedded74e6814fbb51e96f038e058fef 100644 (file)
@@ -1,5 +1,5 @@
 server:
-  port: 80
+  port: 8080
   servlet:
     context-path: /
 zk:
@@ -52,8 +52,10 @@ logging:
     logging.level.httpclient.wire: ERROR
 application:
   ui:
-    user-name:
-    password:
+    user-name: user
+    password: password
+    export-temp-path: /temp
+    disable-profile-save: true
   workflow:
     import-invoice:
       input-path: /temp/invoice-import
index 4d96ecd353433908a5d770364b4ffe7b77fee962..f4b331f34a7004930aa77090a25884884648aec3 100644 (file)
@@ -6,22 +6,44 @@
 
 package hu.user.lis;
 
+import hu.user.lis.db.Partner;
+import hu.user.lis.db.Project;
+import hu.user.lis.ui.TypeUtils;
 import lombok.extern.log4j.Log4j2;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 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 java.util.Optional;
+
 
 @Log4j2
 @RunWith(SpringRunner.class)
 @ComponentScan("hu.user.lis")
 @SpringBootTest
+@ActiveProfiles("dev")
+@TestPropertySource("classpath:application-dev.yaml")
 public class EventIT {
     @Test
-    public void testSaveEntityEvent() {
-        String data = "";
+    public void testOptional() {
+        Partner partner = Partner.builder().name("Partner Name").build();
+        Project project1 = Project.builder().partner(partner).build();
+        Project project2 = Project.builder().build();
+
+        Optional<String> optionalString = Optional.ofNullable(project1).map(Project::getPartner).map(Partner::getName);
+        log.info(TypeUtils.formatOptional(optionalString));
+
+        optionalString = Optional.ofNullable(project2).map(Project::getPartner).map(Partner::getName);
+        log.info(TypeUtils.formatOptional(optionalString));
+
+
+        log.info(TypeUtils.formatOptional(null));
+        log.info(TypeUtils.formatOptional(5));
+
     }
 
 
diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/TypeUtils.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/TypeUtils.java
new file mode 100644 (file)
index 0000000..7eb0f60
--- /dev/null
@@ -0,0 +1,19 @@
+package hu.user.lis.ui;
+
+import org.zkoss.lang.Strings;
+
+public class TypeUtils {
+
+    private TypeUtils() {
+    }
+
+    public static String formatOptional(Object optionalValue) {
+        return String.valueOf(optionalValue)
+                .replace("Optional.", "")
+                .replace("Optional", "")
+                .replace("[", "")
+                .replace("]", "")
+                .replace("null", Strings.EMPTY)
+                .replace("empty", Strings.EMPTY);
+    }
+}
index c465bb1364e84bf33d16a175c3f623568b565de0..30b0c7506ca41bb131de165da9f885330b5dc99c 100644 (file)
@@ -23,6 +23,7 @@ public class AssignInvoicesDataModel extends CachedSpringDataModel<JSONObject> {
     @Autowired
     WorkflowManagerService workflowManagerService;
 
+
     public void refresh() {
         super.reset();
     }
index 4570d75c6ffc7c57324982812ce52e36bd6d879b..d0e5e1498da78b27769f7245bb9a6f5de4181216 100644 (file)
@@ -6,6 +6,7 @@ import hu.user.lis.service.data.AssociateService;
 import hu.user.lis.service.data.EntityDataService;
 import hu.user.lis.ui.data.common.CachedSpringDataModel;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.context.annotation.Scope;
@@ -35,6 +36,11 @@ public class AssociatesDataModel extends CachedSpringDataModel<Associate> {
 
     private boolean filterShowActive;
 
+    @Override
+    public String getShortName() {
+        return "associates";
+    }
+
     @Override
     public List<Associate> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
         Pageable pageable = createPageable(page, pageSize, sortComparator);
@@ -98,4 +104,23 @@ public class AssociatesDataModel extends CachedSpringDataModel<Associate> {
     public void delete(Associate selectedEntity) {
         associateRepository.delete(selectedEntity);
     }
+
+    @Override
+    public String[] mapHeaders() {
+        return ArrayUtils.toArray(
+                "Név", "Login", "Havi önköltség", "Havi önköltség ÁFA", "Aktív"
+        );
+    }
+
+    @Override
+    public Object[] mapRowData(Associate data) {
+        return ArrayUtils.toArray(
+                data.getName(),
+                data.getLogin(),
+                data.getMonthlyCost(),
+                data.getMonthlyVat(),
+                data.isActive()
+        );
+    }
+
 }
index e5d2f1eb3d0529f015a8c84ffcfb33cd22a57a75..4672d49d75690ab6a6f8e48edfae2b6291ee82da 100644 (file)
@@ -1,10 +1,13 @@
 package hu.user.lis.ui.data;
 
 import hu.user.lis.db.Invoice;
+import hu.user.lis.db.Partner;
+import hu.user.lis.db.Project;
 import hu.user.lis.db.repository.InvoiceRepository;
 import hu.user.lis.db.repository.filter.InvoiceFilter;
 import hu.user.lis.ui.data.common.CachedSpringDataModel;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.context.annotation.Scope;
@@ -25,6 +28,11 @@ public class InvoicesDataModel extends CachedSpringDataModel<Invoice> {
 
     private InvoiceFilter filter;
 
+    @Override
+    public String getShortName() {
+        return "invoices";
+    }
+
     @Override
     public List<Invoice> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
         Pageable pageable = createPageable(page, pageSize, sortComparator);
@@ -43,4 +51,34 @@ public class InvoicesDataModel extends CachedSpringDataModel<Invoice> {
         this.filter = filter;
         super.reset();
     }
+
+    @Override
+    public String[] mapHeaders() {
+        return ArrayUtils.toArray(
+                "Terv",
+                "Sorszám",
+                "Partner név",
+                "Projekt azonosító",
+                "Projekt név",
+                "Fizetési határidő",
+                "Bruttó összeg",
+                "Pénznem",
+                "Költség/Bevétel"
+        );
+    }
+
+    @Override
+    public Object[] mapRowData(Invoice data) {
+        return ArrayUtils.toArray(
+                data.isPlanned(),
+                data.getHumanId(),
+                Optional.ofNullable(data.getPartner()).map(Partner::getName),
+                Optional.ofNullable(data.getProject()).map(Project::getHumanId),
+                Optional.ofNullable(data.getProject()).map(Project::getName),
+                data.getPaymentDeadline(),
+                data.getGrossAmount(),
+                data.getCurrency(),
+                data.isIncoming()
+        );
+    }
 }
index 7c7885e639eda3085ba00daf067020f57633c386..e67ac12a5602ec1405c5cc9b3ef2bb0f19f9959c 100644 (file)
@@ -5,9 +5,8 @@ import hu.user.lis.db.repository.PartnerRepository;
 import hu.user.lis.service.data.EntityDataService;
 import hu.user.lis.service.data.PartnerService;
 import hu.user.lis.ui.data.common.CachedSpringDataModel;
-import hu.user.lis.ui.data.common.IDataHeaderProvider;
-import hu.user.lis.ui.data.common.IRowDataProvider;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.context.annotation.Scope;
@@ -20,7 +19,7 @@ import java.util.List;
 @Component
 @Log4j2
 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
-public class PartnersDataModel extends CachedSpringDataModel<Partner> implements IDataHeaderProvider, IRowDataProvider<Partner> {
+public class PartnersDataModel extends CachedSpringDataModel<Partner> {
     @Autowired
     PartnerRepository partnerRepository;
 
@@ -39,6 +38,11 @@ public class PartnersDataModel extends CachedSpringDataModel<Partner> implements
     private boolean filterShowActive;
 
 
+    @Override
+    public String getShortName() {
+        return "partners";
+    }
+
     @Override
     public List<Partner> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
         Pageable pageable = createPageable(page, pageSize, sortComparator);
@@ -94,21 +98,20 @@ public class PartnersDataModel extends CachedSpringDataModel<Partner> implements
         partnerRepository.delete(selectedEntity);
     }
 
-    public void export() {
-        super.export("partners", this, this);
-    }
-
     @Override
     public String[] mapHeaders() {
-        return new String[]{
+        return ArrayUtils.toArray(
                 "Név", "Adószám", "Cím", "Aktív"
-        };
+        );
     }
 
     @Override
-    public String[] mapRowData(Partner data) {
-        return new String[]{
-                data.getName(), data.getVatNr(), data.getAddress(), String.valueOf(data.isActive())
-        };
+    public Object[] mapRowData(Partner data) {
+        return ArrayUtils.toArray(
+                data.getName(),
+                data.getVatNr(),
+                data.getAddress(),
+                data.isActive()
+        );
     }
 }
index 2793a5050c7e6f7ea29ee5df65a6fcdeb443ba02..b1a4a1710e964e6080af567dadbde656aa27f10b 100644 (file)
@@ -1,5 +1,6 @@
 package hu.user.lis.ui.data;
 
+import hu.user.lis.db.Partner;
 import hu.user.lis.db.Project;
 import hu.user.lis.db.ProjectStatus;
 import hu.user.lis.db.repository.InvoiceRepository;
@@ -7,6 +8,7 @@ import hu.user.lis.db.repository.ProjectRepository;
 import hu.user.lis.service.data.EntityDataService;
 import hu.user.lis.ui.data.common.CachedSpringDataModel;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.context.annotation.Scope;
@@ -20,6 +22,7 @@ import java.time.Year;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 
 @Component
 @Log4j2
@@ -45,6 +48,11 @@ public class ProjectsDataModel extends CachedSpringDataModel<Project> {
 
     private boolean filterShowActive;
 
+    @Override
+    public String getShortName() {
+        return "projects";
+    }
+
     @Override
     public List<Project> getResultSet(int page, int pageSize, FieldComparator sortComparator) {
         Pageable pageable = createPageable(page, pageSize, sortComparator);
@@ -128,4 +136,34 @@ public class ProjectsDataModel extends CachedSpringDataModel<Project> {
     public void delete(Project selectedEntity) {
         projectRepository.delete(selectedEntity);
     }
+
+    @Override
+    public String[] mapHeaders() {
+        return ArrayUtils.toArray(
+                "Azonosító",
+                "Ügyfél",
+                "Státusz",
+                "Megnevezés",
+                "Kapcsolattartó",
+                "Beszerzési ár (HUF)",
+                "Eladási ár (HUF)",
+                "Árrés (HUF)",
+                "Aktív"
+        );
+    }
+
+    @Override
+    public Object[] mapRowData(Project data) {
+        return ArrayUtils.toArray(
+                data.getHumanId(),
+                Optional.ofNullable(data.getPartner()).map(Partner::getName),
+                Optional.ofNullable(data.getProjectStatus()).map(ProjectStatus::getName),
+                data.getName(),
+                data.getContactName(),
+                data.getSupplyPrice(),
+                data.getSellingPrice(),
+                data.getMargin(),
+                data.isActive()
+        );
+    }
 }
index e56221b3f8a9b7e7cfc208564efe373b89880187..393c516daedebea9a8999ae29a45f7f46be37b97 100644 (file)
@@ -1,6 +1,7 @@
 package hu.user.lis.ui.data;
 
 import hu.user.lis.db.Associate;
+import hu.user.lis.db.Partner;
 import hu.user.lis.db.Project;
 import hu.user.lis.db.ServiceRecord;
 import hu.user.lis.db.repository.ServiceRecordRepository;
@@ -8,6 +9,7 @@ import hu.user.lis.service.data.EntityDataService;
 import hu.user.lis.service.data.ServiceRecordService;
 import hu.user.lis.ui.data.common.CachedSpringDataModel;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.context.annotation.Scope;
@@ -20,6 +22,7 @@ import org.zkoss.zul.FieldComparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 @Component
@@ -42,6 +45,11 @@ public class ServiceRecordsDataModel extends CachedSpringDataModel<ServiceRecord
 
     private boolean groupByAssociate;
 
+    @Override
+    public String getShortName() {
+        return "service-records";
+    }
+
     @Init
     public void init() {
         Clients.evalJavaScript("pushNav('/service-records')");
@@ -126,4 +134,28 @@ public class ServiceRecordsDataModel extends CachedSpringDataModel<ServiceRecord
     public void delete(ServiceRecord entity) {
         serviceRecordRepository.delete(entity);
     }
+
+    @Override
+    public String[] mapHeaders() {
+        return ArrayUtils.toArray(
+                "Projekt azonosító",
+                "Projekt név",
+                "Partner név",
+                "Munkatárs",
+                "Munkanap",
+                "Leírás",
+                "Óraszám"
+        );
+    }
+
+    @Override
+    public Object[] mapRowData(ServiceRecord data) {
+        return ArrayUtils.toArray(
+                Optional.ofNullable(data.getProject()).map(Project::getName),
+                Optional.ofNullable(data.getProject()).map(Project::getPartner).map(Partner::getName),
+                Optional.ofNullable(data.getAssociate()).map(Associate::getName),
+                data.getWorkDay(),
+                data.getWorkHours()
+        );
+    }
 }
index f0195c6cbc2ddd28d39bdd550ca03314003ac89b..ca047acc22dbe03d20cefb980de35b1fbb42b3a7 100644 (file)
@@ -1,5 +1,6 @@
 package hu.user.lis.ui.data.common;
 
+import hu.user.lis.ui.TypeUtils;
 import hu.user.lis.ui.properties.ApplicationUIProperties;
 import lombok.Setter;
 import lombok.extern.log4j.Log4j2;
@@ -11,6 +12,7 @@ import org.zkoss.bind.BindUtils;
 import org.zkoss.zul.FieldComparator;
 import org.zkoss.zul.Filedownload;
 import org.zkoss.zul.ListModelList;
+import org.zkoss.zul.Messagebox;
 import org.zkoss.zul.event.ListDataEvent;
 
 import java.io.OutputStream;
@@ -49,9 +51,11 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
     private ApplicationUIProperties applicationUIProperties;
 
     public CachedDataModel() {
-
         setMultiple(false);
+    }
 
+    public String getShortName() {
+        return "short-name-not-defined";
     }
 
     public void reset() {
@@ -171,9 +175,9 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
         }
     }
 
-    abstract public List<T> getResultSet(int page, int pageSize, FieldComparator sortComparator);
+    public abstract List<T> getResultSet(int page, int pageSize, FieldComparator sortComparator);
 
-    abstract public int getResultSetCount();
+    public abstract int getResultSetCount();
 
     @Override
     public String getSortDirection(Comparator comparator) {
@@ -191,22 +195,23 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
         reset();
     }
 
-    public Path export(String name, IDataHeaderProvider headerProvider, IRowDataProvider<T> rowDataProvider) {
+    public void export() {
         String timestamp = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss").format(LocalDateTime.now());
-        Path result = Paths.get(applicationUIProperties.getExportTempPath(), String.format("%s-%s.xlsx", name, timestamp));
+        Path destinationTempPath = Paths.get(applicationUIProperties.getExportTempPath(), String.format("%s-%s.xlsx", getShortName(), timestamp));
         int resultSetCount = getResultSetCount();
         if (resultSetCount == 0) {
-            return null;
+            Messagebox.show("Nincs exportálható adat.");
+            return;
         }
         int pageCount = resultSetCount / CACHE_SIZE;
         if (resultSetCount % CACHE_SIZE > 0) {
             pageCount++;
         }
         int row = 0;
-        try (OutputStream os = Files.newOutputStream(result)) {
+        try (OutputStream os = Files.newOutputStream(destinationTempPath)) {
             Workbook wb = new Workbook(os, "SLY-CRM", "1.0");
             Worksheet ws = wb.newWorksheet("Sheet 1");
-            String[] headers = headerProvider.mapHeaders();
+            String[] headers = mapHeaders();
             for (int h = 0; h < headers.length; h++) {
                 ws.value(row, h, headers[h]);
             }
@@ -214,20 +219,33 @@ public abstract class CachedDataModel<T> extends ListModelList<T> {
                 List<T> datas = getResultSet(i, CACHE_SIZE, sortComparator);
                 log.info("Got {} records", datas.size());
                 for (T data : datas) {
-                    String[] rowData = rowDataProvider.mapRowData(data);
+                    Object[] rowData = mapRowData(data);
                     row++;
                     for (int o = 0; o < rowData.length; o++) {
-                        ws.value(row, o, rowData[o]);
+                        ws.value(row, o, TypeUtils.formatOptional(rowData[o]));
                     }
                 }
             }
+            ws.freezePane(headers.length, 1);
+            ws.range(0, 0, 0, headers.length).style().fillColor("888888").set();
+            ws.finish();
             wb.finish();
 
-            Filedownload.save(result.toFile(), "application/vnd.ms-excel");
+            Filedownload.save(destinationTempPath.toFile(), "application/vnd.ms-excel");
         } catch (Exception e) {
             log.error(e.getMessage());
         }
-        return result;
     }
+
+    protected String[] mapHeaders() {
+        return new String[]{
+        };
+    }
+
+    protected Object[] mapRowData(T data) {
+        return new Object[]{
+        };
+    }
+
 }
 
index e66457d4eb459095820f13e74e616cd96caa65dc..25aa2d8d6962b3edf3e505a376c21a3c4a202665 100644 (file)
@@ -87,8 +87,4 @@ public class PartnersViewModel extends FilterActiveViewModel<Partner> {
                 });
     }
 
-    @Command
-    public void onExport() {
-        partnersDataModel.export();
-    }
 }
index 34e8401bdeec9c3f34038cdca5b8b2bb2e8b2107..818bd967024590dcc9a6efc22ba07b6a1a981106 100644 (file)
@@ -58,7 +58,7 @@ public class ProjectsViewModel extends FilterActiveViewModel<Project> implements
                 "contactName,Kapcsolattartó,natural,left,true",
                 "supplyPrice,Beszerzési ár (HUF),natural,left,true",
                 "sellingPrice,Eladási ár (HUF),natural,left,true",
-                "margin,Árrés (HUF) ,natural,left,true",
+                "margin,Árrés (HUF),natural,left,true",
                 "active,Aktív,natural,left,true"
         ));
     }
index 887796e7bbcc63766cd69384bc8fbbfd1e7f6298..a4c0845ad940651f2dee963c7335807c955da151 100644 (file)
@@ -115,4 +115,9 @@ public abstract class EntityViewModel<T extends Serializable> {
         getDataModel().onHeaderReorder(dragged, dropped);
     }
 
+    @Command
+    public void onExport() {
+        getDataModel().export();
+    }
+
 }
index e899edf29725239c786ab5f89ae6cf60618c97da..7caeeb679071e437e0b1f9b8efe9c06aa88f7483 100644 (file)
                             </listitem>
                         </template>
                     </listbox>
+                    <hbox pack="stretch" hflex="true">
+                        <toolbar align="end">
+                            <toolbarbutton label="Export" iconSclass="z-icon-file-excel-o"
+                                           onClick="@command('onExport')"/>
+                        </toolbar>
+                    </hbox>
                 </vlayout>
             </center>
         </borderlayout>
index 3addacf778a142a5bb5a6c5e25d09ba739cb2d38..4436c7e87a0316bea5533c87afc8e1fd5d88171f 100644 (file)
                             </listitem>
                         </template>
                     </listbox>
+                    <hbox pack="stretch" hflex="true">
+                        <toolbar align="end">
+                            <toolbarbutton label="Export" iconSclass="z-icon-file-excel-o"
+                                           onClick="@command('onExport')"/>
+                        </toolbar>
+                    </hbox>
                 </vlayout>
             </center>
         </borderlayout>
index 08ccc30ede737504a51c135a4a1d23e5f244e261..d5cb86e56684c8747f48a5e373077390520f27bb 100644 (file)
                             </listitem>
                         </template>
                     </listbox>
+                    <hbox pack="stretch" hflex="true">
+                        <toolbar align="end">
+                            <toolbarbutton label="Export" iconSclass="z-icon-file-excel-o"
+                                           onClick="@command('onExport')"/>
+                        </toolbar>
+                    </hbox>
                 </vlayout>
             </center>
         </borderlayout>
index fd9f02e14e5634d88588b19ec4905f8a4665d524..f1021a1fe3b1f4dfc80b9eb8f74ef9272ed6c11c 100644 (file)
                             </listitem>
                         </template>
                     </listbox>
+                    <hbox pack="stretch" hflex="true">
+                        <toolbar align="end">
+                            <toolbarbutton label="Export" iconSclass="z-icon-file-excel-o"
+                                           onClick="@command('onExport')"/>
+                        </toolbar>
+                    </hbox>
                 </vlayout>
             </center>
         </borderlayout>