* 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.
<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>
--- /dev/null
+package hu.user.lis.db;
+
+import lombok.*;
+
+@Getter
+@Setter
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ProjectStatus {
+ String id;
+ String name;
+ boolean active;
+ int order;
+}
--- /dev/null
+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;
+}
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;
@Service
@Log4j2
public class AssociateServiceImpl extends DataServiceImpl<Associate> implements AssociateService {
- @Autowired
- ObjectMapper mapper;
@Autowired
DataGeneratorService dataGeneratorService;
private List<Associate> entities;
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;
package hu.user.lis.services.data;
-import hu.user.lis.db.Partner;
import hu.user.lis.db.Project;
import java.util.List;
List<Project> getByPartner(String id);
+ Project getRandom();
+
Project createNew();
void add(Project entity);
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;
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");
.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);
.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);
.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);
.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);
.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);
--- /dev/null
+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);
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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);
+}
--- /dev/null
+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;
+ }
+
+
+}
return "admin/index";
}
- @GetMapping({"/projects", "/associates", "/project-associates", "/project/**"})
+ @GetMapping({"/projects", "/associates", "/project-associates", "/service-records", "/settings", "/project/**"})
public String index() {
return "index";
}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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, "*");
+ }
+}
--- /dev/null
+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, "*");
+ }
+}
--- /dev/null
+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, "*");
+ }
+
+}
--- /dev/null
+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, "*");
+ }
+}
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;
AssociatesDataModel associatesDataModel;
@WireVariable
ProjectAssociateService projectAssociateServiceImpl;
+ @WireVariable
+ ServiceRecordService serviceRecordServiceImpl;
private Project formDocument;
private Project origDocument;
private Map<String, Boolean> origAssociates;
@WireVariable
private TreasuryService treasuryServiceImpl;
+
+ @WireVariable
+ private ServiceRecordsDataModel serviceRecordsDataModel;
@WireVariable
private EventBus eventBus;
private boolean formInvalid = true;
}
@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);
formDocument = (Project) data.get("formDocument");
BindUtils.postNotifyChange(this, "formDocument");
associatesDataModel.listAll();
+
+ serviceRecordsDataModel.search(formDocument.getId());
}
}
log.info("Associate checked");
validate(projectServiceImpl.copy(formDocument));
}
+
}
--- /dev/null
+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));
+ }
+}
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;
"/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
@Command
public void onAdd() {
- String page = "~./project.zul";
Project newEntity = projectsDataModel.getProjectService().createNew();
eventBus.showProjectEditor(ImmutableMap.of("formDocument", newEntity));
}
--- /dev/null
+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();
+ }
+
+
+}
--- /dev/null
+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();
+ }
+}
--- /dev/null
+<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
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"/>
-<!--<?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>
<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>
-<?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"/>
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"/>
-<?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"
<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"/>
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;">
--- /dev/null
+<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
-<?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"
-<?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>
<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"/>
--- /dev/null
+<?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
--- /dev/null
+<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
--- /dev/null
+<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
*/
}
+.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;
-<?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')">
<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"/>
<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"/>