Minor bug fixes, service records extended, settings basics
authorelgekko <vasary@elgekko.net>
Mon, 15 May 2023 20:11:00 +0000 (22:11 +0200)
committerelgekko <vasary@elgekko.net>
Mon, 15 May 2023 20:11:00 +0000 (22:11 +0200)
38 files changed:
TODO.txt
lis-app/pom.xml
lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java [new file with mode: 0644]
lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java [new file with mode: 0644]
lis-services/src/main/java/hu/user/lis/services/data/AssociateServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/ProjectService.java
lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/ProjectStatusService.java [new file with mode: 0644]
lis-services/src/main/java/hu/user/lis/services/data/ProjectStatusServiceImpl.java [new file with mode: 0644]
lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordService.java [new file with mode: 0644]
lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java
lis-ui/src/main/java/hu/user/lis/ui/converter/AssociateToNameConverter.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/converter/ProjectToNameConverter.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/data/AssociateSelectorDataModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/data/ProjectStatusDataModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/data/ServiceRecordsDataModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.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/ProjectsViewModel.java
lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java [new file with mode: 0644]
lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java [new file with mode: 0644]
lis-ui/src/main/resources/web/associate-selector.zul [new file with mode: 0644]
lis-ui/src/main/resources/web/associates.zul
lis-ui/src/main/resources/web/index.zul
lis-ui/src/main/resources/web/partner-selector.zul
lis-ui/src/main/resources/web/partners.zul
lis-ui/src/main/resources/web/project-editor.zul
lis-ui/src/main/resources/web/project-selector.zul [new file with mode: 0644]
lis-ui/src/main/resources/web/project.zul
lis-ui/src/main/resources/web/projects.zul
lis-ui/src/main/resources/web/service-record-editor.zul [new file with mode: 0644]
lis-ui/src/main/resources/web/service-records.zul [new file with mode: 0644]
lis-ui/src/main/resources/web/settings.zul [new file with mode: 0644]
lis-ui/src/main/resources/web/static/css/webclient.css
lis-ui/src/main/resources/web/treasury-editor.zul

index 1f0623b6df6730cffd2e9e5baa8698bcc433f424..d8a843b5a9f1d425dfc483c38adf8b82db9c9518 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -6,6 +6,7 @@
 * A be és kimenő számlák felviteli képernyőjén be lehessen állítani, hogy ez egy tervezett számla-e.
 * Számlakép feltöltés: pdf csatolás
 * Munkatárs lista és szerkesztő: név, óradíj
+
 0.0.7
 * Tervezett számla esetén: a határidők nem ismertek, nem kötelező; áfa deviza esetén nem ismert, nem kötelező
 * Projekt szerkesztőben előbb van a kimenő számlák lista
 * Projekt szerkesztőben treasury műveletek lista: Eladás (aloszlop összeg és deviza), Vétel (aloszlop összeg és deviza),Üzletkötés dátuma, Értéknap
 * A treasury szerkesztőben banki visszaigazolás pdf csatolása
 
-- Munkalap: külön lista xy hány órát (mindenki önköltség) dolgozott melyik projekten
-- Projekt szerkesztőben tresaury táblázat alatt munkalap lista, ráfordítás összesítéssel (fixen 21 munkanappal számolva havonta)
-
-- Valós adatok a projekt, partner, számla nézetben (Kele Károly)
+0.0.9
+* Munkalap: külön lista xy hány órát (mindenki önköltség) dolgozott melyik projekten
+* Projekt szerkesztőben tresaury táblázat alatt munkalap lista, ráfordítás összesítéssel (fixen 21 munkanappal számolva havonta)
+* Valós adatok a projekt, partner, számla nézetben (Kele Károly)
+0.1.0
+* Treasury editor pénznem hibásan működik, mindkettő változik, ha az egyiket módosítom
+* Munkalapon: "összefoglaló" és "részletes leírás" mezők; az összefoglaló kötelező
+* Munkalaphoz: Aláírt munkalap feltöltésének lehetősége. Feltöltéskor kerüljön át a státusz "aláírt"-ba.
+* Az oszlopszélesség minden listában állítható
+* Treasury műveletek mentésénél nullpointer exception jön
+- Munkalapon: "normális" elrendezés, nézzen ki jól
+- Minden szám: legyen jobbra igazítva, oszlop fejlécek pedig középen; mindenhol két tizedes pontossággal
+- Projekt: kell egy "státusz" mező:
+    Legyen rendszerparaméter, és egy lista amiből választani lehet és a sorrend is legyen változtatható a listaban,
+    (pl.: Új, Terv, Készül az ajánlat, Ajánlat kiküldve, Megrendelve, Számlázható, Kiszámlázva, Elbuktuk) de db-ből
+- Projektekhez: Legyen kicsit normálisabb elrendezésű.
+- Nem jól kalkulálódik az "óradíj" a munkalapon
+- A projektekhez valos treasury karolytol
+- A projektben a munkalap osszesitve jelenjen meg személyenként,de navigáljon el bontott nézetbe kattintásra
+- A munkalapok lista szűrhető projektre és résztvevőre. Ezt használjuk ki, amikor a projekt összevont nézetből a munkalap
+ bontást szeretnénk látni
 - A projekt szerkesztés/részletezés tetején az adatok legyenek bal oldalon bekeretezve.
     A jobb oldalon pedig legyen látható a projekt árrése.
     Az árrés annyi sorból áll ahány devizanem van a projekt számláiban. Egy adott devizanem esetén a számolás:
     Kimenő - Bejövő - Treasury eladás + Treasury vétel
 
-- számla kiegyenlítés
+- Számla kiegyenlítés
+
 - Minden kívülről leszipkázható adat jöjjön módosítható legyen REST API-n: szla kiegyenlítés, bejövő/kimenő számlák, munkalap
     Ez emiatt kell, a szinkronizációt egy külső app végzi?
-
 - Autentikáció: AD és helyi
 - Authorizáció: SAP S3 authorization objects leírás
+- legyen felhasználó specifikus beállításokra lehetőség
+       - Táblázatok: oszlopszélesség állítható és rendezhető legyen (minden oszlopra) mencse el a felhasználó preferenciához.
 - Munkalap rögzítés úgy, hogy raktáron lévő alkatrészt is fel lehessen vinni a munkalapra.
 - Plugin: lehet egyedi testreszabási igény, de ennek valahogy el kell teljesen különülnie a "core" forráskódtól. Pl. javascript motort be lehetne építeni, a szkriptek pedig meghatározott pontokon lehetnének becsatolva a logikába. Számla részletezés volt a példa (10000EUR számla 3 részletben forintban, kérdés mennyi pl. az utsó számla összege); 10 custom mező, javascripttel futna a custom mezők módosítására.
 
index ae61ab2db25e4b25722cd55b304378776e0b6217..f33aa886d37bfff07f2b5c012c74a94e7561d85f 100644 (file)
@@ -4,7 +4,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>hu.user</groupId>
     <artifactId>lis-app</artifactId>
-    <version>0.0.8-SNAPSHOT</version>
+    <version>0.0.9-SNAPSHOT</version>
     <parent>
         <groupId>hu.user</groupId>
         <artifactId>lis</artifactId>
diff --git a/lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java b/lis-db/src/main/java/hu/user/lis/db/ProjectStatus.java
new file mode 100644 (file)
index 0000000..d0ee9ab
--- /dev/null
@@ -0,0 +1,15 @@
+package hu.user.lis.db;
+
+import lombok.*;
+
+@Getter
+@Setter
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ProjectStatus {
+    String id;
+    String name;
+    boolean active;
+    int order;
+}
diff --git a/lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java b/lis-db/src/main/java/hu/user/lis/db/ServiceRecord.java
new file mode 100644 (file)
index 0000000..0ce1fd7
--- /dev/null
@@ -0,0 +1,22 @@
+package hu.user.lis.db;
+
+import lombok.*;
+
+import java.util.Date;
+
+@Getter
+@Setter
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ServiceRecord {
+    String id;
+    Project project;
+    Associate associate;
+    Date workDay;
+    String description;
+    String details;
+    int workHours;
+    double cost;
+    byte[] file;
+}
index 8bc3e6538d0369237829ebc70db0a2fbb53f272c..6fcc976433deb38bf52734e29d7e3f2b6dbebc0f 100644 (file)
@@ -1,6 +1,5 @@
 package hu.user.lis.services.data;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import hu.user.lis.db.Associate;
 import lombok.extern.log4j.Log4j2;
 import org.apache.commons.lang3.RandomStringUtils;
@@ -16,8 +15,6 @@ import java.util.List;
 @Service
 @Log4j2
 public class AssociateServiceImpl extends DataServiceImpl<Associate> implements AssociateService {
-    @Autowired
-    ObjectMapper mapper;
     @Autowired
     DataGeneratorService dataGeneratorService;
     private List<Associate> entities;
@@ -79,47 +76,65 @@ public class AssociateServiceImpl extends DataServiceImpl<Associate> implements
 
     private List<Associate> generate2() {
         List<Associate> result = new ArrayList<>();
-
-       String id = RandomStringUtils.random(8, "0123456789abcdef");
-       String name = "Kosztolányi Árpád";
-       String login = "user1";
-       String password = "password";
-       Associate entity = Associate.builder().active(true).id(id).name(name).login(login).password(password).build();
-       result.add(entity);
+        double monthlyCost = 0;
+        String id = RandomStringUtils.random(8, "0123456789abcdef");
+        String name = "Kosztolányi Árpád";
+        String login = "user1";
+        String password = "password";
+        monthlyCost = BigDecimal.valueOf(RandomUtils.nextDouble(300000, 1500000))
+                .setScale(2, RoundingMode.CEILING).doubleValue();
+        Associate entity = Associate.builder().monthlyCost(monthlyCost)
+                .active(true).id(id).name(name).login(login).password(password).build();
+        result.add(entity);
 
         id = RandomStringUtils.random(8, "0123456789abcdef");
         name = "Lévai Tibor";
         login = "user2";
         password = "password";
-        entity = Associate.builder().active(true).id(id).name(name).login(login).password(password).build();
+        monthlyCost = BigDecimal.valueOf(RandomUtils.nextDouble(300000, 1500000))
+                .setScale(2, RoundingMode.CEILING).doubleValue();
+        entity = Associate.builder().monthlyCost(monthlyCost)
+                .active(true).id(id).name(name).login(login).password(password).build();
         result.add(entity);
 
         id = RandomStringUtils.random(8, "0123456789abcdef");
         name = "Szabó Marcell";
         login = "user3";
         password = "password";
-        entity = Associate.builder().active(true).id(id).name(name).login(login).password(password).build();
+        monthlyCost = BigDecimal.valueOf(RandomUtils.nextDouble(300000, 1500000))
+                .setScale(2, RoundingMode.CEILING).doubleValue();
+        entity = Associate.builder().monthlyCost(monthlyCost)
+                .active(true).id(id).name(name).login(login).password(password).build();
         result.add(entity);
 
         id = RandomStringUtils.random(8, "0123456789abcdef");
         name = "Gulyás Csaba";
         login = "user4";
         password = "password";
-        entity = Associate.builder().active(true).id(id).name(name).login(login).password(password).build();
+        monthlyCost = BigDecimal.valueOf(RandomUtils.nextDouble(300000, 1500000))
+                .setScale(2, RoundingMode.CEILING).doubleValue();
+        entity = Associate.builder().monthlyCost(monthlyCost)
+                .active(true).id(id).name(name).login(login).password(password).build();
         result.add(entity);
 
         id = RandomStringUtils.random(8, "0123456789abcdef");
         name = "Lévai Csilla";
         login = "user5";
         password = "password";
-        entity = Associate.builder().active(true).id(id).name(name).login(login).password(password).build();
+        monthlyCost = BigDecimal.valueOf(RandomUtils.nextDouble(300000, 1500000))
+                .setScale(2, RoundingMode.CEILING).doubleValue();
+        entity = Associate.builder().monthlyCost(monthlyCost)
+                .active(true).id(id).name(name).login(login).password(password).build();
         result.add(entity);
 
         id = RandomStringUtils.random(8, "0123456789abcdef");
         name = "Vajda Krisztina";
         login = "user6";
         password = "password";
-        entity = Associate.builder().active(true).id(id).name(name).login(login).password(password).build();
+        monthlyCost = BigDecimal.valueOf(RandomUtils.nextDouble(300000, 1500000))
+                .setScale(2, RoundingMode.CEILING).doubleValue();
+        entity = Associate.builder().monthlyCost(monthlyCost)
+                .active(true).id(id).name(name).login(login).password(password).build();
         result.add(entity);
 
         return result;
index 912afb79962fbe5821e249bc9b1134c134032276..ab2b69ed729d2280bbb031b75dd7029193ac024f 100644 (file)
@@ -1,6 +1,5 @@
 package hu.user.lis.services.data;
 
-import hu.user.lis.db.Partner;
 import hu.user.lis.db.Project;
 
 import java.util.List;
@@ -12,6 +11,8 @@ public interface ProjectService {
 
     List<Project> getByPartner(String id);
 
+    Project getRandom();
+
     Project createNew();
 
     void add(Project entity);
index 49e337a1d684c8e4462bc3e43a45235783d73001..025af620d70cf14317ee77e721b9f836d62973e4 100644 (file)
@@ -4,6 +4,7 @@ import hu.user.lis.db.Partner;
 import hu.user.lis.db.Project;
 import lombok.extern.log4j.Log4j2;
 import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -73,6 +74,11 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
         entities.add(replacementEntity);
     }
 
+    @Override
+    public Project getRandom() {
+        return getAll().get(RandomUtils.nextInt(0, entities.size()));
+    }
+
     private List<Project> generate() {
         List<Project> result = new ArrayList<>();
         DateFormat dateFormat = new SimpleDateFormat("yyyy");
@@ -114,8 +120,9 @@ 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(treasuryService.getRandom())
                 .build();
         result.add(entity);
 
@@ -131,8 +138,9 @@ 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.getRandom())
                 .build();
         result.add(entity);
 
@@ -148,8 +156,9 @@ 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.getRandom())
                 .build();
         result.add(entity);
 
@@ -167,6 +176,7 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
                 .partner(partner)
                 .incomingInvoices(invoiceService.getByHumanIds(new String[]{"17356/23"}))   // 17356/23
                 .outgoingInvoices(invoiceService.getByHumanIds(new String[]{"E-USER-2023-53"}))  // E-USER-2023-53
+                .treasuries(treasuryService.getRandom())
                 .build();
         result.add(entity);
 
@@ -184,6 +194,7 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
                 .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
+                .treasuries(treasuryService.getRandom())
                 .build();
         result.add(entity);
 
diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ProjectStatusService.java b/lis-services/src/main/java/hu/user/lis/services/data/ProjectStatusService.java
new file mode 100644 (file)
index 0000000..cfcfa67
--- /dev/null
@@ -0,0 +1,19 @@
+package hu.user.lis.services.data;
+
+import hu.user.lis.db.ProjectStatus;
+
+import java.util.List;
+
+public interface ProjectStatusService extends DataService<ProjectStatus> {
+    List<ProjectStatus> getAll();
+
+    ProjectStatus getById(String id);
+
+    ProjectStatus createNew();
+
+    void add(ProjectStatus entity);
+
+    ProjectStatus getRandom();
+
+    void replace(ProjectStatus targetEntity, ProjectStatus replacementEntity);
+}
diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ProjectStatusServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/ProjectStatusServiceImpl.java
new file mode 100644 (file)
index 0000000..8c96ade
--- /dev/null
@@ -0,0 +1,77 @@
+package hu.user.lis.services.data;
+
+import hu.user.lis.db.ProjectStatus;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Service
+@Log4j2
+public class ProjectStatusServiceImpl extends DataServiceImpl<ProjectStatus> implements ProjectStatusService {
+    private Map<String, ProjectStatus> entities;
+
+    @Override
+    public List<ProjectStatus> getAll() {
+        if (entities == null) {
+            entities = generate();
+        }
+        return entities.values().stream().sorted(Comparator.comparing(ProjectStatus::getOrder)).collect(Collectors.toList());
+    }
+
+    @Override
+    public ProjectStatus getById(String id) {
+        return entities.get(id);
+    }
+
+    @Override
+    public ProjectStatus createNew() {
+        String id = RandomStringUtils.random(8, "0123456789abcdef");
+        return ProjectStatus.builder().id(id).active(true).build();
+    }
+
+    @Override
+    public void add(ProjectStatus entity) {
+        entities.put(entity.getId(), entity);
+    }
+
+    @Override
+    public void replace(ProjectStatus targetEntity, ProjectStatus replacementEntity) {
+        entities.put(replacementEntity.getId(), replacementEntity);
+    }
+
+    @Override
+    public ProjectStatus getRandom() {
+        return getAll().get(RandomUtils.nextInt(0, entities.size()));
+    }
+
+    private void createStatus(String name, Map<String, ProjectStatus> entities) {
+        ProjectStatus entity = ProjectStatus.builder()
+                .active(true)
+                .id(RandomStringUtils.random(8, "0123456789abcdef"))
+                .name("Új")
+                .order(entities.size())
+                .build();
+        entities.put(entity.getId(), entity);
+    }
+
+    private Map<String, ProjectStatus> generate() {
+        Map<String, ProjectStatus> result = new HashMap<>();
+        createStatus("Új", result);
+        createStatus("Terv", result);
+        createStatus("Készül az ajánlat", result);
+        createStatus("Ajánlat kiküldve", result);
+        createStatus("Megrendelve", result);
+        createStatus("Számlázható", result);
+        createStatus("Kiszámlázva", result);
+        createStatus("Elbuktuk", result);
+        return result;
+    }
+
+}
diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordService.java b/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordService.java
new file mode 100644 (file)
index 0000000..a74541d
--- /dev/null
@@ -0,0 +1,30 @@
+package hu.user.lis.services.data;
+
+import hu.user.lis.db.Project;
+import hu.user.lis.db.ServiceRecord;
+
+import java.util.List;
+
+public interface ServiceRecordService {
+    List<ServiceRecord> getAll();
+
+    ServiceRecord getById(String id);
+
+    List<ServiceRecord> getByProject(String id);
+
+    ServiceRecord createNew();
+
+    List<ServiceRecord> getRandom(Project project);
+
+    void add(ServiceRecord entity);
+
+    ServiceRecord copy(ServiceRecord sourceEntity);
+
+    void calculateCost(ServiceRecord entity);
+
+    void replace(ServiceRecord targetEntity, ServiceRecord replacementEntity);
+
+    String toString(ServiceRecord sourceEntity);
+
+    ServiceRecord copy(ServiceRecord sourceEntity, String property, Object value);
+}
diff --git a/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java b/lis-services/src/main/java/hu/user/lis/services/data/ServiceRecordServiceImpl.java
new file mode 100644 (file)
index 0000000..61f16e4
--- /dev/null
@@ -0,0 +1,118 @@
+package hu.user.lis.services.data;
+
+import hu.user.lis.db.Associate;
+import hu.user.lis.db.Project;
+import hu.user.lis.db.ServiceRecord;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Service
+@Log4j2
+public class ServiceRecordServiceImpl extends DataServiceImpl<ServiceRecord> implements ServiceRecordService {
+    @Autowired
+    DataGeneratorService dataGeneratorService;
+    @Autowired
+    ProjectService projectService;
+    @Autowired
+    AssociateService associateService;
+    private HashMap<String, ServiceRecord> projectRecords = new HashMap<>();
+    private List<ServiceRecord> entities;
+
+    @Override
+    public List<ServiceRecord> getAll() {
+
+        if (entities == null) {
+            entities = generate();
+        }
+        return entities;
+    }
+
+    @Override
+    public ServiceRecord getById(String id) {
+        return getAll().stream().filter(p -> p.getId().equals(id)).findFirst().get();
+    }
+
+    @Override
+    public List<ServiceRecord> getByProject(String id) {
+        return getAll().stream().filter(p -> p.getProject().getId().equals(id)).collect(Collectors.toList());
+    }
+
+
+    @Override
+    public ServiceRecord createNew() {
+        String id = RandomStringUtils.random(8, "0123456789abcdef");
+        return ServiceRecord.builder()
+                .id(id)
+                .build();
+    }
+
+    @Override
+    public List<ServiceRecord> getRandom(Project project) {
+        return null;
+    }
+
+    @Override
+    public void add(ServiceRecord entity) {
+        calculateCost(entity);
+        entities.add(entity);
+    }
+
+    @Override
+    public void calculateCost(ServiceRecord entity) {
+        double cost = 0;
+        try {
+            cost = entity.getAssociate().getMonthlyCost() * entity.getWorkHours() / 21;
+            entity.setCost(cost);
+        } catch (Exception e) {
+            log.catching(e);
+        }
+    }
+
+    @Override
+    public void replace(ServiceRecord targetEntity, ServiceRecord replacementEntity) {
+        ServiceRecord target = entities.stream().filter(p -> p.getId().equals(targetEntity.getId())).findFirst().get();
+        entities.remove(target);
+        entities.add(replacementEntity);
+    }
+
+    private List<ServiceRecord> generate() {
+        List<ServiceRecord> result = new ArrayList<>();
+
+        projectService.getAll().forEach(p -> {
+            int serviceRecordCount = RandomUtils.nextInt(3, 10);
+            for (int i = 0; i < serviceRecordCount; i++) {
+                String id = RandomStringUtils.random(8, "0123456789abcdef");
+                Date workDay = dataGeneratorService.faker().date().past(i * 10 + 1, TimeUnit.DAYS);
+                Associate associate = associateService.getRandom();
+                String description = dataGeneratorService.faker().lorem().sentence(10);
+                int workHours = RandomUtils.nextInt(1, 9);
+                ServiceRecord entity = ServiceRecord.builder()
+                        .associate(associate)
+                        .project(p)
+                        .workDay(workDay)
+                        .workHours(workHours)
+                        .description(description)
+                        .id(id)
+                        .build();
+                calculateCost(entity);
+                result.add(entity);
+                projectRecords.put(p.getId(), entity);
+            }
+
+        });
+
+        return result;
+    }
+
+
+}
index e0dc293f8b1d9667a5867e038f70b87f115d9da1..6d9985b41420dbbe251d43c3a0307ca87e7babc3 100644 (file)
@@ -10,7 +10,7 @@ public class ResourceConfigurer {
         return "admin/index";
     }
 
-    @GetMapping({"/projects", "/associates", "/project-associates", "/project/**"})
+    @GetMapping({"/projects", "/associates", "/project-associates", "/service-records", "/settings", "/project/**"})
     public String index() {
         return "index";
     }
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/converter/AssociateToNameConverter.java b/lis-ui/src/main/java/hu/user/lis/ui/converter/AssociateToNameConverter.java
new file mode 100644 (file)
index 0000000..86a66b4
--- /dev/null
@@ -0,0 +1,19 @@
+package hu.user.lis.ui.converter;
+
+import hu.user.lis.db.Associate;
+import org.zkoss.bind.BindContext;
+import org.zkoss.bind.Converter;
+import org.zkoss.zul.Bandbox;
+
+public class AssociateToNameConverter implements Converter<String, Associate, Bandbox> {
+
+    @Override
+    public String coerceToUi(Associate Associate, Bandbox bandbox, BindContext bindContext) {
+        return Associate == null ? null : Associate.getName();
+    }
+
+    @Override
+    public Associate coerceToBean(String s, Bandbox bandbox, BindContext bindContext) {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/converter/ProjectToNameConverter.java b/lis-ui/src/main/java/hu/user/lis/ui/converter/ProjectToNameConverter.java
new file mode 100644 (file)
index 0000000..c89de12
--- /dev/null
@@ -0,0 +1,19 @@
+package hu.user.lis.ui.converter;
+
+import hu.user.lis.db.Project;
+import org.zkoss.bind.BindContext;
+import org.zkoss.bind.Converter;
+import org.zkoss.zul.Bandbox;
+
+public class ProjectToNameConverter implements Converter<String, Project, Bandbox> {
+
+    @Override
+    public String coerceToUi(Project project, Bandbox bandbox, BindContext bindContext) {
+        return project == null ? null : project.getHumanId();
+    }
+
+    @Override
+    public Project coerceToBean(String s, Bandbox bandbox, BindContext bindContext) {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/AssociateSelectorDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/AssociateSelectorDataModel.java
new file mode 100644 (file)
index 0000000..4ab3241
--- /dev/null
@@ -0,0 +1,63 @@
+package hu.user.lis.ui.data;
+
+import hu.user.lis.db.Associate;
+import hu.user.lis.services.data.AssociateService;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.zkoss.bind.BindUtils;
+import org.zkoss.zul.FieldComparator;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+@Log4j2
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class AssociateSelectorDataModel extends CachedDataModel<Associate> {
+    static private final int SEARCH_LIMIT = 10;
+    @Autowired
+    AssociateService associateService;
+    private String partialName;
+
+    private boolean filter(Associate associate) {
+        if (StringUtils.isBlank(partialName)) {
+            return true;
+        } else {
+            if (associate.getName().toLowerCase().startsWith(partialName.toLowerCase())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    protected List<Associate> getResultSet(long offset, int limit, FieldComparator sortComparator) {
+        List<Associate> result = associateService.getAll().stream()
+                .sorted(Comparator.comparing(Associate::getName))
+                .filter(s -> filter(s))
+                .limit(SEARCH_LIMIT)
+                .collect(Collectors.toList());
+        return result;
+    }
+
+    @Override
+    public int getResultSetCount() {
+        int result = (int) associateService.getAll().stream()
+                .filter(s -> filter(s))
+                .limit(SEARCH_LIMIT)
+                .count();
+        return result;
+    }
+
+    public void search(String partialName) {
+        log.info("Searching associate using filter {}", partialName);
+        this.partialName = partialName;
+        super.reset();
+        BindUtils.postNotifyChange(null, null, this, "*");
+    }
+}
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectSelectorDataModel.java
new file mode 100644 (file)
index 0000000..807334d
--- /dev/null
@@ -0,0 +1,63 @@
+package hu.user.lis.ui.data;
+
+import hu.user.lis.db.Project;
+import hu.user.lis.services.data.ProjectService;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.zkoss.bind.BindUtils;
+import org.zkoss.zul.FieldComparator;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+@Log4j2
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class ProjectSelectorDataModel extends CachedDataModel<Project> {
+    static private final int SEARCH_LIMIT = 10;
+    @Autowired
+    ProjectService projectService;
+    private String partialName;
+
+    private boolean filter(Project project) {
+        if (StringUtils.isBlank(partialName)) {
+            return true;
+        } else {
+            if (project.getHumanId().toLowerCase().startsWith(partialName.toLowerCase())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    protected List<Project> getResultSet(long offset, int limit, FieldComparator sortComparator) {
+        List<Project> result = projectService.getAll().stream()
+                .sorted(Comparator.comparing(Project::getName))
+                .filter(s -> filter(s))
+                .limit(SEARCH_LIMIT)
+                .collect(Collectors.toList());
+        return result;
+    }
+
+    @Override
+    public int getResultSetCount() {
+        int result = (int) projectService.getAll().stream()
+                .filter(s -> filter(s))
+                .limit(SEARCH_LIMIT)
+                .count();
+        return result;
+    }
+
+    public void search(String partialName) {
+        log.info("Searching project using filter {}", partialName);
+        this.partialName = partialName;
+        super.reset();
+        BindUtils.postNotifyChange(null, null, this, "*");
+    }
+}
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectStatusDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/ProjectStatusDataModel.java
new file mode 100644 (file)
index 0000000..fdaa832
--- /dev/null
@@ -0,0 +1,39 @@
+package hu.user.lis.ui.data;
+
+import hu.user.lis.db.ProjectStatus;
+import hu.user.lis.services.data.ProjectStatusService;
+import lombok.Getter;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.zkoss.bind.BindUtils;
+import org.zkoss.zul.FieldComparator;
+
+import java.util.List;
+
+@Component
+@Log4j2
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class ProjectStatusDataModel extends CachedDataModel<ProjectStatus> {
+    @Getter
+    @Autowired
+    ProjectStatusService projectStatusService;
+
+    @Override
+    protected List<ProjectStatus> getResultSet(long offset, int limit, FieldComparator sortComparator) {
+        return projectStatusService.getAll();
+    }
+
+    @Override
+    public int getResultSetCount() {
+        return projectStatusService.getAll().size();
+    }
+
+    public void listAll() {
+        super.reset();
+        BindUtils.postNotifyChange(null, null, this, "*");
+    }
+
+}
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/ServiceRecordsDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/ServiceRecordsDataModel.java
new file mode 100644 (file)
index 0000000..4063d5b
--- /dev/null
@@ -0,0 +1,92 @@
+package hu.user.lis.ui.data;
+
+import hu.user.lis.db.ServiceRecord;
+import hu.user.lis.services.data.ServiceRecordService;
+import lombok.Getter;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+import org.zkoss.bind.BindUtils;
+import org.zkoss.bind.annotation.Init;
+import org.zkoss.zk.ui.util.Clients;
+import org.zkoss.zul.FieldComparator;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+@Log4j2
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class ServiceRecordsDataModel extends CachedDataModel<ServiceRecord> {
+    @Getter
+    @Autowired
+    ServiceRecordService serviceRecordService;
+    private boolean listAll;
+    private String projectId;
+
+    @Init
+    public void init() {
+        Clients.evalJavaScript("pushNav('/service-records')");
+        log.info("Initialized");
+    }
+
+    private boolean canExecuteSearch() {
+        boolean result = listAll || !StringUtils.isBlank(projectId);
+        log.info("Can execute search: {}", result);
+        return result;
+    }
+
+    private boolean filter(ServiceRecord entity) {
+        if (listAll) {
+            return true;
+        }
+        boolean result = true;
+        if (!entity.getProject().getId().equals(projectId)) {
+            result = false;
+        }
+
+        return result;
+    }
+
+    @Override
+    protected List<ServiceRecord> getResultSet(long offset, int limit, FieldComparator sortComparator) {
+        List<ServiceRecord> result = null;
+        if (canExecuteSearch()) {
+            result = serviceRecordService.getAll().stream()
+                    .filter(s -> filter(s))
+                    .sorted(Comparator.comparing(ServiceRecord::getWorkDay))
+                    .collect(Collectors.toList());
+        }
+        return result;
+    }
+
+    @Override
+    public int getResultSetCount() {
+        int result = 0;
+        if (canExecuteSearch()) {
+            result = (int) serviceRecordService.getAll().stream()
+                    .filter(s -> filter(s))
+                    .count();
+        }
+        return result;
+    }
+
+    public void listAll() {
+        log.info("List all service records");
+        listAll = true;
+        super.reset();
+        BindUtils.postNotifyChange(null, null, this, "*");
+    }
+
+    public void search(String projectId) {
+        log.info("Searching project using filter {}", projectId);
+        this.projectId = projectId;
+        listAll = false;
+        super.reset();
+        BindUtils.postNotifyChange(null, null, this, "*");
+    }
+}
index 3c24dee251cbafc39519b71003e6b90e878fd8af..df6b8f15a71f3eab30f58cf8a672db5c2a23b34e 100644 (file)
@@ -6,13 +6,11 @@ import hu.user.lis.db.Associate;
 import hu.user.lis.db.Invoice;
 import hu.user.lis.db.Project;
 import hu.user.lis.db.Treasury;
-import hu.user.lis.services.data.InvoiceService;
-import hu.user.lis.services.data.ProjectAssociateService;
-import hu.user.lis.services.data.ProjectService;
-import hu.user.lis.services.data.TreasuryService;
+import hu.user.lis.services.data.*;
 import hu.user.lis.ui.Constants;
 import hu.user.lis.ui.data.AssociatesDataModel;
 import hu.user.lis.ui.data.PartnerSelectorDataModel;
+import hu.user.lis.ui.data.ServiceRecordsDataModel;
 import hu.user.lis.ui.event.EventBus;
 import lombok.Getter;
 import lombok.Setter;
@@ -47,6 +45,8 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     AssociatesDataModel associatesDataModel;
     @WireVariable
     ProjectAssociateService projectAssociateServiceImpl;
+    @WireVariable
+    ServiceRecordService serviceRecordServiceImpl;
     private Project formDocument;
     private Project origDocument;
     private Map<String, Boolean> origAssociates;
@@ -60,6 +60,9 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
 
     @WireVariable
     private TreasuryService treasuryServiceImpl;
+
+    @WireVariable
+    private ServiceRecordsDataModel serviceRecordsDataModel;
     @WireVariable
     private EventBus eventBus;
     private boolean formInvalid = true;
@@ -297,7 +300,7 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     }
 
     @Command
-    public void onEditTreasury() throws JsonProcessingException {
+    public void onEditTreasury() {
         String page = "~./treasury-editor.zul";
         Treasury editEntity = treasuryServiceImpl.copy(selectedTreasury);
         Map<String, Object> arg = ImmutableMap.of("origDocument", selectedTreasury, "formDocument", editEntity);
@@ -343,6 +346,8 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
             formDocument = (Project) data.get("formDocument");
             BindUtils.postNotifyChange(this, "formDocument");
             associatesDataModel.listAll();
+
+            serviceRecordsDataModel.search(formDocument.getId());
         }
     }
 
@@ -395,4 +400,5 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         log.info("Associate checked");
         validate(projectServiceImpl.copy(formDocument));
     }
+
 }
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java
new file mode 100644 (file)
index 0000000..294b83f
--- /dev/null
@@ -0,0 +1,141 @@
+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;
+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.*;
+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 ServiceRecordEditorModel extends AbstractValidator {
+    @WireVariable
+    ServiceRecordService serviceRecordServiceImpl;
+    @WireVariable
+    private AssociateSelectorDataModel associateSelectorDataModel;
+    @WireVariable
+    private ProjectSelectorDataModel projectSelectorDataModel;
+    private ServiceRecord formDocument;
+    private ServiceRecord origDocument;
+    private boolean formInvalid = true;
+
+    @Init
+    public void init() {
+        log.info("Initialized");
+        origDocument = (ServiceRecord) Executions.getCurrent().getArg().get("origDocument");
+        formDocument = (ServiceRecord) Executions.getCurrent().getArg().get("formDocument");
+    }
+
+    @Command
+    public void onProjectBandChanging(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) {
+        InputEvent event = (InputEvent) ctx.getTriggerEvent();
+        log.info("onProjectBandChanging: {}", event.getValue());
+        projectSelectorDataModel.search(event.getValue());
+    }
+
+    @Command
+    public void onProjectBandOpen(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) {
+        OpenEvent event = (OpenEvent) ctx.getTriggerEvent();
+        log.info("onProjectBandOpen: {}", event.isOpen());
+        projectSelectorDataModel.search(null);
+    }
+
+    @Command
+    public void onAssociatetBandChanging(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) {
+        InputEvent event = (InputEvent) ctx.getTriggerEvent();
+        log.info("onAssociatetBandChanging: {}", event.getValue());
+        associateSelectorDataModel.search(event.getValue());
+    }
+
+    @Command
+    public void onAssociateBandOpen(@ContextParam(ContextType.BIND_CONTEXT) BindContext ctx) {
+        OpenEvent event = (OpenEvent) ctx.getTriggerEvent();
+        log.info("onAssociateBandOpen: {}", event.isOpen());
+        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);
+        }
+    }
+
+    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) {
+        UploadEvent evt = (UploadEvent) ctx.getTriggerEvent();
+        if (!evt.getMedia().getName().toLowerCase().endsWith(".pdf")) {
+            Messagebox.show("Csak PDF állomány feltöltése támogatott.", "Error", Messagebox.OK, Messagebox.ERROR);
+            return;
+        }
+        formDocument.setFile(evt.getMedia().getByteData());
+        BindUtils.postNotifyChange(this.formDocument, "file");
+        validate(serviceRecordServiceImpl.copy(formDocument));
+    }
+
+    @Command
+    public void onRemoveFile() {
+        formDocument.setFile(null);
+        BindUtils.postNotifyChange(this.formDocument, "file");
+        validate(serviceRecordServiceImpl.copy(formDocument));
+    }
+}
index 6bad32b9e739183f540f04a15cd6119b8d26c262..96c02c7bb98793c71f6ea2f1e84772596e8a90e1 100644 (file)
@@ -31,6 +31,8 @@ public class IndexViewModel implements EventListener {
     private static final String PROJECT_EDITOR = "~./project-editor.zul";
     private static final String ASSOCIATES_LIST = "~./associates.zul";
     private static final String PROJECT_ASSOCIATES_LIST = "~./project-associates.zul";
+    private static final String SERVICE_RECORDS_LIST = "~./service-records.zul";
+    private static final String SETTINGS_LIST = "~./settings.zul";
 
     @WireVariable
     BuildProperties buildProperties;
@@ -42,7 +44,10 @@ public class IndexViewModel implements EventListener {
             "/projects", PROJECTS_LIST,
             "/project", PROJECT_EDITOR,
             "/associates", ASSOCIATES_LIST,
-            "/project-associates", PROJECT_ASSOCIATES_LIST
+            "/project-associates", PROJECT_ASSOCIATES_LIST,
+            "/service-records", SERVICE_RECORDS_LIST,
+            "/settings", SETTINGS_LIST
+
     );
 
     @Init
index 90eb386860e00a430847dc09f15aeb00bb7e8d4f..ca3a44930fd75dbca2fcef58c2a710ca1debddbb 100644 (file)
@@ -77,7 +77,6 @@ public class ProjectsViewModel extends AsyncBaseModel implements EventListener {
 
     @Command
     public void onAdd() {
-        String page = "~./project.zul";
         Project newEntity = projectsDataModel.getProjectService().createNew();
         eventBus.showProjectEditor(ImmutableMap.of("formDocument", newEntity));
     }
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/ServiceRecordsViewModel.java
new file mode 100644 (file)
index 0000000..ac36317
--- /dev/null
@@ -0,0 +1,110 @@
+package hu.user.lis.ui.view;
+
+import com.google.common.collect.ImmutableMap;
+import hu.user.lis.db.ServiceRecord;
+import hu.user.lis.ui.data.ServiceRecordsDataModel;
+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.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.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.Set;
+
+
+@Log4j2
+@VariableResolver(DelegatingVariableResolver.class)
+public class ServiceRecordsViewModel {
+    @WireVariable
+    @Getter
+    ServiceRecordsDataModel serviceRecordsDataModel;
+    @WireVariable
+    EventBus eventBus;
+    @Getter
+    private ServiceRecord selectedEntity;
+
+    @AfterCompose
+    public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) {
+        Selectors.wireComponents(view, this, false);
+        Selectors.wireEventListeners(view, this);
+    }
+
+    @Init
+    public void init() {
+        Clients.evalJavaScript("pushNav('/service-records')");
+        refresh();
+        log.info("Initialized");
+    }
+
+    private void refresh() {
+        serviceRecordsDataModel.clearSelection();
+        selectedEntity = null;
+        serviceRecordsDataModel.listAll();
+    }
+
+    @Command
+    @NotifyChange("selectedProject")
+    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";
+        ServiceRecord newEntity = serviceRecordsDataModel.getServiceRecordService().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());
+                serviceRecordsDataModel.getServiceRecordService().add(newEntity);
+                serviceRecordsDataModel.clearSelection();
+                refresh();
+                serviceRecordsDataModel.addToSelection(newEntity);
+                selectedEntity = newEntity;
+            }
+        });
+        editorWindow.doModal();
+    }
+
+    @Command
+    public void onEdit() {
+        String page = "~./service-record-editor.zul";
+        ServiceRecord editEntity = serviceRecordsDataModel.getServiceRecordService().copy(selectedEntity);
+        Map<String, Object> arg = ImmutableMap.of("origDocument", selectedEntity, "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());
+                ServiceRecord modifiedEntity = (ServiceRecord) e.getData();
+                serviceRecordsDataModel.clearSelection();
+                serviceRecordsDataModel.getServiceRecordService().replace(selectedEntity, modifiedEntity);
+                refresh();
+                serviceRecordsDataModel.addToSelection(modifiedEntity);
+                selectedEntity = modifiedEntity;
+            }
+        });
+        editorWindow.doModal();
+    }
+
+
+}
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java
new file mode 100644 (file)
index 0000000..3c6472b
--- /dev/null
@@ -0,0 +1,168 @@
+package hu.user.lis.ui.view;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import hu.user.lis.db.Partner;
+import hu.user.lis.ui.data.PartnersDataModel;
+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.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.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+@Log4j2
+@VariableResolver(DelegatingVariableResolver.class)
+public class SettingsViewModel extends AsyncBaseModel {
+    @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);
+    }
+
+    @Init
+    public void init() {
+        setFilterShowActive(true);
+        Clients.evalJavaScript("pushNav('/settings')");
+        log.info("Initialized");
+    }
+
+    private void refresh() {
+        partnersDataModel.clearSelection();
+        selectedPartner = null;
+        if (filterShowBoth) {
+            partnersDataModel.search(true, true);
+        } else {
+            partnersDataModel.search(filterShowActive, filterShowInActive);
+        }
+    }
+
+    @Command
+    @NotifyChange("selectedPartner")
+    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.getPartnerService().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.getPartnerService().add(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(() -> {
+//                });
+            }
+        });
+        editorWindow.doModal();
+    }
+
+    @Command
+    public void onEdit() throws JsonProcessingException {
+        String page = "~./partner-editor.zul";
+        Partner editEntity = partnersDataModel.getPartnerService().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.getPartnerService().replace(selectedPartner, modifiedEntity);
+                refresh();
+                partnersDataModel.addToSelection(modifiedEntity);
+                selectedPartner = modifiedEntity;
+            }
+        });
+        editorWindow.doModal();
+    }
+
+
+    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/resources/web/associate-selector.zul b/lis-ui/src/main/resources/web/associate-selector.zul
new file mode 100644 (file)
index 0000000..4ec56ad
--- /dev/null
@@ -0,0 +1,52 @@
+<zk xmlns:c="client">
+    <hlayout hflex="true">
+        <bandbox id="associateBandBox" autodrop="true" iconSclass="z-icon-sort-down"
+                 value="@load(vm.formDocument.associate) @converter('hu.user.lis.ui.converter.AssociateToNameConverter')"
+                 onChanging="@command('onAssociateBandChanging')" onOpen="@command('onAssociateBandOpen')"
+                 forward="onOK=submit.onClick, onCancel=cancel.onClick">
+            <attribute c:name="_doKeyDown">
+                <![CDATA[
+                            function (evt) {
+                                var keyCode = evt.keyCode;
+                                console.log(keyCode);
+                                if (keyCode == 13){
+                                    zk.$("$associateBandBox").close();
+                                    zk.$("$associateBandBox").focus();
+                                    return;
+                                }
+                                if (keyCode == 40){
+                                    if (!zk.$("$associateBandBox").isOpen()) {
+                                        zk.$("$associateBandBox").open();
+                                        zAu.send(new zk.Event(zk.Widget.$('$associateBandBox'), "onOpen", {'open': true}, {toServer:true}));
+                                    }
+                                    zk.$("$associateList").focus();
+                                    return;
+                                }
+                                if (keyCode == 27){
+                                    zk.$("$associateBandBox").close()
+                                    zk.$("$associateBandBox").focus();
+                                    return;
+                                }
+                            }
+                        ]]>
+            </attribute>
+            <bandpopup>
+                <listbox id="associateList" height="250px" width="450px"
+                         model="@bind(vm.associateSelectorDataModel)"
+                         selectedItem="@bind(vm.formDocument.associate) @validator(vm)"
+                         onClick="associateBandBox.close()"
+                         onDoubleClick="associateBandBox.close()">
+                    <listhead visible="false">
+                        <listheader label="name" vflex="max"/>
+                    </listhead>
+                    <template name="model">
+                        <listitem>
+                            <listcell label="@load(each.name)"/>
+                        </listitem>
+                    </template>
+                </listbox>
+            </bandpopup>
+        </bandbox>
+
+    </hlayout>
+</zk>
\ No newline at end of file
index 9168afae94cc07637de3c59b8e77a483c3b5d2c8..d446f2c57ec5b0293593c641c61a8abbda28a82e 100644 (file)
@@ -28,9 +28,7 @@
                          autopaging="true" pagingPosition="top" multiple="false"
                          onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')"
                          onAfterRender="@command('onAfterRenderList')">
-                    <custom-attributes org.zkoss.zul.listbox.selectOnHighlight.disabled="true"/>
-
-                    <listhead>
+                    <listhead sizable="true">
                         <listheader label="Név" align="left"/>
                         <listheader label="Login" align="left"/>
                         <listheader label="Aktív" align="left"/>
index c169f42d2175b683ef115673df2a0abbeeac23c2..afa7f49d9e8b0d684396716cbdd9bdcfe56f45f1 100644 (file)
@@ -1,5 +1,5 @@
-<!--<?component name="partners" inline="true" macroURI="~./partners.zul"?>-->
-<!--<?component name="projects" inline="true" macroURI="~./projects.zul"?>-->
+<?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
+<?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <zk>
     <style>
         .z-window-header {
                                   onClick="@command(vm.selectPage('~./partners.zul'))"/>
                         <menuitem iconSclass="z-icon-tasks" label="Projektek"
                                   onClick="@command(vm.selectPage('~./projects.zul'))"/>
-                        <menuitem iconSclass="z-icon-th" label="Munkalapok" disabled="true"
-                                  onClick="@command(vm.selectPage('~./worksheets.zul'))"/>
+                        <menuitem iconSclass="z-icon-th" label="Munkalapok"
+                                  onClick="@command(vm.selectPage('~./service-records.zul'))"/>
                         <menuseparator/>
                         <menuitem iconSclass="z-icon-user" label="Munkatársak"
                                   onClick="@command(vm.selectPage('~./associates.zul'))"/>
+                        <menuseparator/>
+                        <menuitem iconSclass="z-icon-cogs" label="Beállítások"
+                                  onClick="@command(vm.selectPage('~./settings.zul'))"/>
                     </menubar>
                     <hbox hflex="min" pack="right">
                         <textbox value="@bind(vm.searchPhrase)" onOK="@command('search')"></textbox>
index 208196044fd52452a80099239a8299647b432732..21f89e9e286a90e1ad2facacedbc17cf7b4b8680 100644 (file)
@@ -1,6 +1,6 @@
 <zk xmlns:c="client">
     <hlayout hflex="true">
-        <bandbox id="bd" autodrop="true" iconSclass="z-icon-sort-down"
+        <bandbox id="partnerBandBox" autodrop="true" iconSclass="z-icon-sort-down"
                  value="@load(vm.formDocument.partner) @converter('hu.user.lis.ui.converter.PartnerToNameConverter')"
                  onChanging="@command('onPartnerBandChanging')" onOpen="@command('onPartnerBandOpen')"
                  forward="onOK=submit.onClick, onCancel=cancel.onClick">
                                 var keyCode = evt.keyCode;
                                 console.log(keyCode);
                                 if (keyCode == 13){
-                                    zk.$("$bd").close();
-                                    zk.$("$bd").focus();
+                                    zk.$("$partnerBandBox").close();
+                                    zk.$("$partnerBandBox").focus();
                                     return;
                                 }
                                 if (keyCode == 40){
-                                    if (!zk.$("$bd").isOpen()) {
-                                        zk.$("$bd").open();
-                                        zAu.send(new zk.Event(zk.Widget.$('$bd'), "onOpen", {'open': true}, {toServer:true}));
+                                    if (!zk.$("$partnerBandBox").isOpen()) {
+                                        zk.$("$partnerBandBox").open();
+                                        zAu.send(new zk.Event(zk.Widget.$('$partnerBandBox'), "onOpen", {'open': true}, {toServer:true}));
                                     }
-                                    zk.$("$bd-list").focus();
+                                    zk.$("$partenerList").focus();
                                     return;
                                 }
                                 if (keyCode == 27){
-                                    zk.$("$bd").close()
-                                    zk.$("$bd").focus();
+                                    zk.$("$partnerBandBox").close()
+                                    zk.$("$partnerBandBox").focus();
                                     return;
                                 }
                             }
                         ]]>
             </attribute>
             <bandpopup>
-                <listbox id="bd-list" height="250px" width="450px"
+                <listbox id="partenerlist" height="250px" width="450px"
                          model="@bind(vm.partnerSelectorDataModel)"
                          selectedItem="@bind(vm.formDocument.partner) @validator(vm)"
-                         onClick="bd.close()"
-                         onDoubleClick="bd.close()">
+                         onClick="partnerBandBox.close()"
+                         onDoubleClick="partnerBandBox.close()">
                     <listhead visible="false">
                         <listheader label="name" vflex="max"/>
                     </listhead>
index 19292ed83063cfaaf51249bf8ad1fb0b2c30cd5a..94ecda65c37d5f269a98e482afcd88727a529dc6 100644 (file)
@@ -1,11 +1,4 @@
-<?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
-<?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <zk>
-    <style>
-        .z-listitem-selected>.z-listcell>.z-listcell-content {
-        font-weight: bold;
-        }
-    </style>
     <window vflex="true" viewModel="@id('vm') @init('hu.user.lis.ui.view.PartnersViewModel')">
         <!--        <timer id="timer" delay="500" repeats="true" onTimer="@command('uiTick')"/>-->
         <caption label="Partnerek"/>
@@ -29,9 +22,7 @@
                          autopaging="true" pagingPosition="top" multiple="false"
                          onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')"
                          onAfterRender="@command('onAfterRenderPartners')">
-                    <custom-attributes org.zkoss.zul.listbox.selectOnHighlight.disabled="true"/>
-
-                    <listhead>
+                    <listhead sizable="true">
                         <listheader label="Név" align="left"/>
                         <listheader label="Adószám" align="left"/>
                         <listheader label="Cím" align="left"/>
index 22bbb9a9dc7e257f9399b04df99e49fc633ff04e..4f6ed2e35f275cbd1ac3c41d29e34033dc2b1d74 100644 (file)
@@ -1,5 +1,3 @@
-<?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
-<?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <?component name="partner-selector" inline="true" macroURI="~./partner-selector.zul"?>
 <zk>
     <window id="projectEditor" hflex="true" vflex="true"
@@ -49,9 +47,7 @@
                                         <listbox model="@load(vm.associatesDataModel)"
                                                  multiple="false" vflex="true"
                                                  onAfterRender="@command('onAfterRenderAssociates')">
-                                            <custom-attributes org.zkoss.zul.listbox.selectOnHighlight.disabled="true"/>
-
-                                            <listhead>
+                                            <listhead sizable="true">
                                                 <listheader hflex="min" label="Tag" align="left"/>
                                                 <listheader label="Név" align="left"/>
                                                 <listheader label="Login" align="left"/>
@@ -92,7 +88,7 @@
                                          selectedItem="@bind(vm.selectedOutgoingInvoice)"
                                          onDoubleClick="@command('onEditOutgoing')"
                                          forward="onOK=submit.onClick, onCancel=cancel.onClick">
-                                    <listhead>
+                                    <listhead sizable="true">
                                         <listheader label="Vevő" align="left"/>
                                         <listheader label="Sorszám" align="left"/>
                                         <listheader label="Megnevezés" align="left"/>
                                                    onClick="@command('onRemoveIncoming')"
                                                    disabled="@load(empty vm.selectedIncomingInvoice)"/>
                                 </toolbar>
-
                                 <listbox model="@load(vm.formDocument.incomingInvoices)"
                                          selectedItem="@bind(vm.selectedIncomingInvoice)"
                                          onDoubleClick="@command('onEditIncoming')"
                                          forward="onOK=submit.onClick, onCancel=cancel.onClick">
-                                    <listhead>
+                                    <listhead sizable="true">
                                         <listheader label="Szállító" align="left"/>
                                         <listheader label="Sorszám" align="left"/>
                                         <listheader label="Megnevezés" align="left"/>
                                         <auxheader label="Vétel" colspan="2"/>
                                         <auxheader colspan="2"/>
                                     </auxhead>
-                                    <listhead>
+                                    <listhead sizable="true">
                                         <listheader label="Összeg" align="left"/>
                                         <listheader label="Pénznem" align="left"/>
                                         <listheader label="Összeg" align="left"/>
                         </panelchildren>
                     </panel>
 
+                    <panel collapsible="true" open="false" border="rounded"
+                           onOpen="@command('onOpenFormPanel', parentPanel=centerPanel)">
+                        <caption label="Munkalapok"
+                                 onClick="@command('onClickFormPanel', parentPanel=centerPanel, panel=self.parent)"/>
+                        <panelchildren>
+                            <listbox model="@load(vm.serviceRecordsDataModel)"
+                                     forward="onOK=submit.onClick, onCancel=cancel.onClick">
+                                <listhead sizable="true">
+                                    <listheader label="Projekt" align="left"/>
+                                    <listheader label="Munkatárs" align="left"/>
+                                    <listheader label="Munkanap" align="left"/>
+                                    <listheader label="Óraszám" align="left"/>
+                                    <listheader label="Ráfordítás" align="left"/>
+                                </listhead>
+                                <template name="model">
+                                    <listitem>
+                                        <listcell label="@load(each.project.humanId)"/>
+                                        <listcell label="@load(each.associate.name)"/>
+                                        <listcell
+                                                label="@load(each.workDay) @converter('hu.user.lis.ui.converter.DateToStringConverter')"/>
+                                        <listcell label="@load(each.workHours)"/>
+                                        <listcell
+                                                label="@load(each.cost) @converter('hu.user.lis.ui.converter.DoubleToStringConverter')"/>
+                                    </listitem>
+                                </template>
+                            </listbox>
+                        </panelchildren>
+                    </panel>
+
                 </vlayout>
             </center>
             <south border="none" flex="true" style="text-align: right; padding: 10px;">
diff --git a/lis-ui/src/main/resources/web/project-selector.zul b/lis-ui/src/main/resources/web/project-selector.zul
new file mode 100644 (file)
index 0000000..171f46e
--- /dev/null
@@ -0,0 +1,52 @@
+<zk xmlns:c="client">
+    <hlayout hflex="true">
+        <bandbox id="projectBandBox" autodrop="true" iconSclass="z-icon-sort-down"
+                 value="@load(vm.formDocument.project) @converter('hu.user.lis.ui.converter.ProjectToNameConverter')"
+                 onChanging="@command('onProjectBandChanging')" onOpen="@command('onProjectBandOpen')"
+                 forward="onOK=submit.onClick, onCancel=cancel.onClick">
+            <attribute c:name="_doKeyDown">
+                <![CDATA[
+                            function (evt) {
+                                var keyCode = evt.keyCode;
+                                console.log(keyCode);
+                                if (keyCode == 13){
+                                    zk.$("$projectBandBox").close();
+                                    zk.$("$projectBandBox").focus();
+                                    return;
+                                }
+                                if (keyCode == 40){
+                                    if (!zk.$("$projectBandBox").isOpen()) {
+                                        zk.$("$projectBandBox").open();
+                                        zAu.send(new zk.Event(zk.Widget.$('$projectBandBox'), "onOpen", {'open': true}, {toServer:true}));
+                                    }
+                                    zk.$("$projectList").focus();
+                                    return;
+                                }
+                                if (keyCode == 27){
+                                    zk.$("$projectBandBox").close()
+                                    zk.$("$projectBandBox").focus();
+                                    return;
+                                }
+                            }
+                        ]]>
+            </attribute>
+            <bandpopup>
+                <listbox id="projectList" height="250px" width="450px"
+                         model="@bind(vm.projectSelectorDataModel)"
+                         selectedItem="@bind(vm.formDocument.project) @validator(vm)"
+                         onClick="projectBandBox.close()"
+                         onDoubleClick="projectBandBox.close()">
+                    <listhead visible="false">
+                        <listheader label="name" vflex="max"/>
+                    </listhead>
+                    <template name="model">
+                        <listitem>
+                            <listcell label="@load(each.humanId)"/>
+                        </listitem>
+                    </template>
+                </listbox>
+            </bandpopup>
+        </bandbox>
+
+    </hlayout>
+</zk>
\ No newline at end of file
index 8356b45ef0dde2da9aa972b10e0857b978265a6f..f3680f8eacf9d3fcd919d9aee2d73baebf11349c 100644 (file)
@@ -1,5 +1,3 @@
-<?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
-<?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <?component name="partner-selector" inline="true" macroURI="~./partner-selector.zul"?>
 <zk>
     <window id="projectEditor" width="60%" height="80%" closable="true"
index ea7dcbc102015f5e8b2699d3e1947ff2201ea34a..a77efb560387e18bb32ef2cd84936397248379e9 100644 (file)
@@ -1,11 +1,4 @@
-<?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
-<?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <zk>
-    <style>
-        .z-listitem-selected>.z-listcell>.z-listcell-content {
-        font-weight: bold;
-        }
-    </style>
     <window vflex="true" viewModel="@id('vm') @init('hu.user.lis.ui.view.ProjectsViewModel')">
         <caption label="Projektek"/>
         <borderlayout>
@@ -27,9 +20,7 @@
                 <listbox id="partnersList" vflex="true" model="@load(vm.projectsDataModel)"
                          autopaging="true" pagingPosition="top" onSelect="@command('onListSelection')"
                          onDoubleClick="@command('onEdit')">
-                    <custom-attributes org.zkoss.zul.listbox.selectOnHighlight.disabled="true"/>
-
-                    <listhead>
+                    <listhead sizable="true">
                         <listheader label="Azonosító" align="left"/>
                         <listheader label="Ügyfél" align="left"/>
                         <listheader label="Megnevezés" align="left"/>
diff --git a/lis-ui/src/main/resources/web/service-record-editor.zul b/lis-ui/src/main/resources/web/service-record-editor.zul
new file mode 100644 (file)
index 0000000..695d42d
--- /dev/null
@@ -0,0 +1,71 @@
+<?component name="associate-selector" inline="true" macroURI="~./associate-selector.zul"?>
+<?component name="project-selector" inline="true" macroURI="~./project-selector.zul"?>
+<zk>
+    <window id="serviceRecordPopup" width="60%" height="500px" closable="true"
+            viewModel="@id('vm') @init('hu.user.lis.ui.editor.ServiceRecordEditorModel')">
+        <caption label="Munkalap szerkesztés"/>
+        <borderlayout>
+            <center border="none" vflex="true" hflex="true">
+                <tabbox vflex="true" hflex="true">
+                    <tabs>
+                        <tab label="Adatok" selected="true"/>
+                        <tab label="Munkalap"/>
+                    </tabs>
+                    <tabpanels>
+                        <tabpanel>
+                            <vlayout hflex="true">
+                                <label value="Projekt"/>
+                                <project-selector/>
+                                <label value="Munkatárs"/>
+                                <associate-selector/>
+                                <label value="Munkanap"/>
+                                <datebox instant="true" format="yyyy. MM. dd."
+                                         value="@bind(vm.formDocument.workDay) @validator(vm)"
+                                         forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                                <label value="Leírás"/>
+                                <textbox instant="true" hflex="true"
+                                         value="@bind(vm.formDocument.description) @validator(vm)"
+                                         forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                                <label value="Óraszám"/>
+                                <intbox value="@bind(vm.formDocument.workHours) @validator(vm)"
+                                        format="locale:hu-HU" instant="true"
+                                        forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                                <label value="Részletek"/>
+                                <textbox instant="true" multiline="true" inplace="false" rows="5"
+                                         hflex="true"
+                                         value="@bind(vm.formDocument.details) @validator(vm)"
+                                         forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                            </vlayout>
+                        </tabpanel>
+                        <tabpanel>
+                            <borderlayout>
+                                <north flex="true">
+                                    <toolbar>
+                                        <toolbarbutton label="Feltöltés" iconSclass="z-icon-plus" upload="true"
+                                                       onUpload="@command('onUploadFile')"/>
+                                        <toolbarbutton label="Törlés" iconSclass="z-icon-remove"
+                                                       onClick="@command('onRemoveFile')"
+                                                       disabled="@load(empty vm.formDocument.file)"/>
+                                    </toolbar>
+                                </north>
+                                <center border="none" flex="true">
+                                    <iframe hflex="true" vflex="true"
+                                            content="@load(vm.formDocument.file) @converter('hu.user.lis.ui.converter.ByteArrayToAMediaConverter')"/>
+                                </center>
+                            </borderlayout>
+                        </tabpanel>
+                    </tabpanels>
+                </tabbox>
+            </center>
+            <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)"/>
+                    <button id="submit" label="Mentés"
+                            onClick="@command('onCloseWindow', target=serviceRecordPopup, select=true)"
+                            disabled="@bind(vm.formInvalid)"/>
+                </hlayout>
+            </south>
+        </borderlayout>
+    </window>
+</zk>
\ No newline at end of file
diff --git a/lis-ui/src/main/resources/web/service-records.zul b/lis-ui/src/main/resources/web/service-records.zul
new file mode 100644 (file)
index 0000000..d0392f2
--- /dev/null
@@ -0,0 +1,45 @@
+<zk>
+    <window vflex="true" viewModel="@id('vm') @init('hu.user.lis.ui.view.ServiceRecordsViewModel')">
+        <caption label="Munkalapok"/>
+        <borderlayout>
+            <north flex="true">
+                <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.selectedEntity)"/>
+                </toolbar>
+            </north>
+            <center border="none" flex="true">
+                <listbox vflex="true" model="@load(vm.serviceRecordsDataModel)"
+                         autopaging="true" pagingPosition="top" onSelect="@command('onListSelection')"
+                         onDoubleClick="@command('onEdit')">
+                    <listhead sizable="true">
+                        <listheader label="Projekt" align="left"/>
+                        <listheader label="Munkatárs" align="left"/>
+                        <listheader label="Munkanap" align="left"/>
+                        <listheader label="Leírás" align="left"/>
+                        <listheader label="Óraszám" align="center"/>
+                        <listheader label="ALáírt" align="left"/>
+                    </listhead>
+                    <template name="model">
+                        <listitem>
+                            <listcell label="@load(each.project.humanId)"/>
+                            <listcell label="@load(each.associate.name)"/>
+                            <listcell
+                                    label="@load(each.workDay) @converter('hu.user.lis.ui.converter.DateToStringConverter')"/>
+                            <listcell label="@load(each.description)"/>
+                            <listcell>
+                                <label value="@load(each.workHours)" sclass="right-aligned"/>
+                            </listcell>
+                            <listcell>
+                                <a iconSclass="z-icon-check" visible="@load(not empty each.file)"/>
+                                <a iconSclass="z-icon-ban" visible="@load(empty each.file)"/>
+                            </listcell>
+                        </listitem>
+                    </template>
+                </listbox>
+            </center>
+        </borderlayout>
+
+    </window>
+</zk>
\ No newline at end of file
diff --git a/lis-ui/src/main/resources/web/settings.zul b/lis-ui/src/main/resources/web/settings.zul
new file mode 100644 (file)
index 0000000..c74badc
--- /dev/null
@@ -0,0 +1,46 @@
+<zk>
+    <window vflex="true" viewModel="@id('vm') @init('hu.user.lis.ui.view.SettingsViewModel')">
+        <caption label="Partnerek"/>
+        <borderlayout>
+            <north flex="true">
+                <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)"/>
+                    <separator orient="vertical"/>
+                    <toolbarbutton mode="toggle" iconSclass="z-icon-check" label="Aktív"
+                                   checked="@bind(vm.filterShowActive)"/>
+                    <toolbarbutton mode="toggle" iconSclass="z-icon-ban" label="Inaktív"
+                                   checked="@bind(vm.filterShowInActive)"/>
+                    <toolbarbutton mode="toggle" iconSclass="z-icon-adjust" label="Mind"
+                                   checked="@bind(vm.filterShowBoth)"/>
+                </toolbar>
+            </north>
+            <center border="none" flex="true">
+                <listbox id="partnersList" vflex="true" model="@load(vm.partnersDataModel)"
+                         autopaging="true" pagingPosition="top" multiple="false"
+                         onSelect="@command('onListSelection')" onDoubleClick="@command('onEdit')"
+                         onAfterRender="@command('onAfterRenderPartners')">
+                    <listhead sizable="true">
+                        <listheader label="Név" align="left"/>
+                        <listheader label="Adószám" align="left"/>
+                        <listheader label="Cím" align="left"/>
+                        <listheader label="Aktív" align="left"/>
+                    </listhead>
+                    <template name="model">
+                        <listitem>
+                            <listcell label="@load(each.name)"/>
+                            <listcell label="@load(each.vatNr)"/>
+                            <listcell label="@load(each.address)"/>
+                            <listcell>
+                                <a iconSclass="z-icon-check" visible="@load(each.active)"/>
+                                <a iconSclass="z-icon-ban" visible="@load(!each.active)"/>
+                            </listcell>
+                        </listitem>
+                    </template>
+                </listbox>
+            </center>
+        </borderlayout>
+
+    </window>
+</zk>
\ No newline at end of file
index 15292f51e1d7bb59de6a84846c03fd7463800fef..6e431f4ea1a98910f29daa0b62f320d8f2b87a87 100644 (file)
@@ -9,6 +9,20 @@
 */
 }
 
+.right-aligned {
+    display: inline-block;
+    text-align: right;
+    width: 100%;
+}
+
+textarea {
+    resize: none;
+}
+
+.z-listitem-selected>.z-listcell>.z-listcell-content {
+    font-weight: bold;
+}
+
 .container .form-label {
        font-family: "Calibri";
        line-height: 1.5em;
index 1e13b5c9c8176c9b16b12fb8563330ab27586450..f78ebf840865c5675e3eda98ef788c784291428a 100644 (file)
@@ -1,10 +1,9 @@
-<?link rel="stylesheet" type="text/css" href="~./static/css/skeleton.css" ?>
-<?link rel="stylesheet" type="text/css" href="~./static/css/webclient.css" ?>
 <?component name="partner-selector" inline="true" macroURI="~./partner-selector.zul"?>
 <zk>
     <zscript>
         import hu.user.lis.db.Currency;
-        ListModelList currencies = new ListModelList(Currency.values());
+        ListModelList buyCurrencies = new ListModelList(Currency.values());
+        ListModelList sellCurrencies = new ListModelList(Currency.values());
     </zscript>
     <window id="invoicePopup" width="50%" height="500px" closable="true"
             maximizable="true" sizable="true" viewModel="@id('vm') @init('hu.user.lis.ui.editor.TreasuryEditorModel')">
@@ -23,7 +22,7 @@
                                     <hlayout>
                                         <vlayout>
                                             <label value="Pénznem"/>
-                                            <combobox instant="true" model="${currencies}"
+                                            <combobox instant="true" model="${sellCurrencies}"
                                                       selectedItem="@bind(vm.formDocument.sellCurrency) @validator(vm)"
                                                       forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
 
@@ -40,7 +39,7 @@
                                     <hlayout>
                                         <vlayout>
                                             <label value="Pénznem"/>
-                                            <combobox instant="true" model="${currencies}"
+                                            <combobox instant="true" model="${buyCurrencies}"
                                                       selectedItem="@bind(vm.formDocument.buyCurrency) @validator(vm)"
                                                       forward="onOK=submit.onClick, onCancel=cancel.onClick"/>