Treasury list and editor added
authorelgekko <vasary@elgekko.net>
Wed, 3 May 2023 22:18:24 +0000 (00:18 +0200)
committerelgekko <vasary@elgekko.net>
Wed, 3 May 2023 22:18:24 +0000 (00:18 +0200)
TODO.txt
lis-db/src/main/java/hu/user/lis/db/Treasury.java
lis-services/src/main/java/hu/user/lis/services/data/ProjectServiceImpl.java
lis-services/src/main/java/hu/user/lis/services/data/TreasuryServiceImpl.java
lis-ui/src/main/java/hu/user/lis/ui/data/AssociatesDataModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java
lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java [new file with mode: 0644]
lis-ui/src/main/resources/web/incoming-invoice-editor.zul
lis-ui/src/main/resources/web/outgoing-invoice-editor.zul
lis-ui/src/main/resources/web/project-editor.zul
lis-ui/src/main/resources/web/treasury-editor.zul [new file with mode: 0644]

index 5ddebc58534b157c92af3d8e45b5b84a14eb0a58..a2ac5ec665be7274c212eb1444c8002e800f53e7 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -19,9 +19,9 @@
 * A projektszám formátuma más kell, hogy legyen (Csabi).
 * Számlához kellene a számla sorszám: a szerkesztőben és/vagy a listában?
 * A be és kimenő számlák táblázatban szerepeljen a teljesítés dátuma a fizetési határidő oszlop előtt.
-- Projekt résztvevők így nagy helyet foglalnak el.
+* Projekt résztvevők így nagy helyet foglalnak el.
     Inkább legyen egy nyomógomb a projekt szerkesztő tetején egy dialógus ablakban lehet szerkeszteni a résztvevőket.
-    A felugró ablak helyett inkáb plusz tab lett az adatok mellett, maradhat? Layout para
+    A felugró ablak helyett inkáb plusz tab lett az adatok mellett, maradhat?
 * Munkatárs táblázatban a szerkesztés gomb nem aktív.
 
 - 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
index b4d8a3c6fbc4e6f313d40eea1f83186333393966..9572229b66a5ec176f294550d29b061597c4c57e 100644 (file)
@@ -17,4 +17,5 @@ public class Treasury {
     Currency sellCurrency;
     Date transactionDate;
     Date valueDate;
+    byte[] file;
 }
index a83b16f158e741e5a060bee58f3054f7421acb2b..1212e6a49eeb5a3f3a0fb8aa61891bb7f5307643 100644 (file)
@@ -1,6 +1,5 @@
 package hu.user.lis.services.data;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import hu.user.lis.db.Partner;
 import hu.user.lis.db.Project;
 import lombok.extern.log4j.Log4j2;
@@ -18,14 +17,14 @@ import java.util.concurrent.TimeUnit;
 @Service
 @Log4j2
 public class ProjectServiceImpl extends DataServiceImpl<Project> implements ProjectService {
-    @Autowired
-    ObjectMapper mapper;
     @Autowired
     DataGeneratorService dataGeneratorService;
     @Autowired
     PartnerService partnerService;
     @Autowired
     InvoiceService invoiceService;
+    @Autowired
+    TreasuryService treasuryService;
     private List<Project> entities;
 
     @Override
@@ -45,6 +44,7 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
                 .humanId(humanId)
                 .incomingInvoices(new ArrayList<>())
                 .outgoingInvoices(new ArrayList<>())
+                .treasuries(new ArrayList<>())
                 .active(true)
                 .build();
     }
@@ -56,8 +56,8 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
 
     @Override
     public void replace(Project targetEntity, Project replacementEntity) {
-        Project partnerInList = entities.stream().filter(p -> p.getId().equals(targetEntity.getId())).findFirst().get();
-        entities.remove(partnerInList);
+        Project target = entities.stream().filter(p -> p.getId().equals(targetEntity.getId())).findFirst().get();
+        entities.remove(target);
         entities.add(replacementEntity);
     }
 
@@ -80,6 +80,7 @@ public class ProjectServiceImpl extends DataServiceImpl<Project> implements Proj
                     .partner(partner)
                     .incomingInvoices(invoiceService.getRandom(true))
                     .outgoingInvoices(invoiceService.getRandom(false))
+                    .treasuries(treasuryService.getRandom())
                     .build();
             result.add(entity);
         }
index 8cd9bef9109460c7e9b7f11965b22f7781d36279..57402bbc4a616b8a5c07e9dd32e8e61e8ede15c1 100644 (file)
@@ -83,9 +83,9 @@ public class TreasuryServiceImpl extends DataServiceImpl<Treasury> implements Tr
         int count = RandomUtils.nextInt(2, 5);
         List<Treasury> result = new ArrayList<>();
         for (int i = 0; i < count; i++) {
-            int index = RandomUtils.nextInt(0, entities.size());
-            result.add(entities.get(index));
-            entities.remove(index);
+            int index = RandomUtils.nextInt(0, getAll().size());
+            result.add(getAll().get(index));
+            getAll().remove(index);
         }
         return result;
     }
index ce702f78e6d4dc01cb57a42b6a9adc5e4ba20cf9..7c73dff083ca653a5da70ab13072c49d8ced97dc 100644 (file)
@@ -84,6 +84,8 @@ public class AssociatesDataModel extends CachedDataModel<Associate> {
     public void search(String partialName) {
         log.info("Searching associate using filters: name LIKE {}", partialName);
         listAll = false;
+        this.filterShowActive = true;
+        this.filterShowInActive = true;
         this.partialName = partialName;
         super.reset();
         BindUtils.postNotifyChange(null, null, this, "*");
index 3ad7b22f06431a0dbc1c04b3178267f2af1f6b1d..3c24dee251cbafc39519b71003e6b90e878fd8af 100644 (file)
@@ -67,20 +67,27 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     private Invoice selectedOutgoingInvoice;
 
     private Treasury selectedTreasury;
-
     private String partialAssociateName;
 
-
-    public ProjectEditorModel() {
-
-    }
-
     @Init
     public void init() {
         eventBus.register(this);
         log.info("Initialized");
     }
 
+    @NotifyChange("associatesDataModel")
+    public void setPartialAssociateName(String partialAssociateName) {
+        this.partialAssociateName = partialAssociateName;
+        log.info("Filter assosiates: {}", partialAssociateName);
+        associatesDataModel.search(partialAssociateName);
+    }
+
+    @Command
+    @NotifyChange({"associatesDataModel", "partialAssociateName"})
+    public void onResetAssociateFilter() {
+        this.partialAssociateName = null;
+        associatesDataModel.listAll();
+    }
 
     @Command
     public void onEndEdit(@BindingParam("target") Window target, @BindingParam("select") boolean select) {
@@ -273,16 +280,16 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
 
     @Command
     public void onAddTreasury() {
-        String page = "~./outgoing-invoice-editor.zul";
-        Invoice editEntity = invoiceServiceImpl.createNew();
+        String page = "~./treasury-editor.zul";
+        Treasury editEntity = treasuryServiceImpl.createNew();
         Window editorWindow = (Window) Executions.createComponents(page, null,
                 Collections.singletonMap("formDocument", editEntity));
         editorWindow.addEventListener("onClose", e -> {
             if (e.getData() != null) {
-                formDocument.getOutgoingInvoices().add(editEntity);
-                selectedOutgoingInvoice = editEntity;
-                BindUtils.postNotifyChange(this, "selectedOutgoingInvoice");
-                BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices");
+                formDocument.getTreasuries().add(editEntity);
+                selectedTreasury = editEntity;
+                BindUtils.postNotifyChange(this, "selectedTreasury");
+                BindUtils.postNotifyChange(this.formDocument, "treasuries");
                 validate(projectServiceImpl.copy(formDocument));
             }
         });
@@ -291,22 +298,20 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
 
     @Command
     public void onEditTreasury() throws JsonProcessingException {
-        String page = "~./outgoing-invoice-editor.zul";
-        Invoice editEntity = invoiceServiceImpl.copy(selectedOutgoingInvoice);
-        Map<String, Object> arg = new HashMap<>();
-        arg.put("origDocument", selectedOutgoingInvoice);
-        arg.put("formDocument", editEntity);
+        String page = "~./treasury-editor.zul";
+        Treasury editEntity = treasuryServiceImpl.copy(selectedTreasury);
+        Map<String, Object> arg = ImmutableMap.of("origDocument", selectedTreasury, "formDocument", editEntity);
         Window editorWindow = (Window) Executions.createComponents(page, null, arg);
         editorWindow.addEventListener("onClose", e -> {
             if (e.getData() != null) {
-                Invoice modifiedEntity = (Invoice) e.getData();
-                List<Invoice> outgoingInvoices = formDocument.getOutgoingInvoices();
-                int index = outgoingInvoices.indexOf(selectedOutgoingInvoice);
-                outgoingInvoices.remove(selectedOutgoingInvoice);
-                outgoingInvoices.add(index, modifiedEntity);
-                selectedOutgoingInvoice = modifiedEntity;
-                BindUtils.postNotifyChange(this, "selectedOutgoingInvoice");
-                BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices");
+                Treasury modifiedEntity = (Treasury) e.getData();
+                List<Treasury> treasuries = formDocument.getTreasuries();
+                int index = treasuries.indexOf(selectedTreasury);
+                treasuries.remove(selectedTreasury);
+                treasuries.add(index, modifiedEntity);
+                selectedTreasury = modifiedEntity;
+                BindUtils.postNotifyChange(this, "selectedTreasury");
+                BindUtils.postNotifyChange(this.formDocument, "treasuries");
                 validate(projectServiceImpl.copy(formDocument));
             }
         });
@@ -318,10 +323,10 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
         if (selectedOutgoingInvoice == null) {
             return;
         }
-        formDocument.getOutgoingInvoices().remove(selectedOutgoingInvoice);
-        selectedOutgoingInvoice = null;
-        BindUtils.postNotifyChange(this, "selectedOutgoingInvoice");
-        BindUtils.postNotifyChange(this.formDocument, "outgoingInvoices");
+        formDocument.getTreasuries().remove(selectedTreasury);
+        selectedTreasury = null;
+        BindUtils.postNotifyChange(this, "selectedTreasury");
+        BindUtils.postNotifyChange(this.formDocument, "treasuries");
         validate(projectServiceImpl.copy(formDocument));
     }
 
@@ -348,14 +353,14 @@ public class ProjectEditorModel extends AbstractValidator implements EventListen
     }
 
     @Command
-    public void onOpenInvoicePanel(@BindingParam("parentPanel") Center parentPanel) {
-        log.info("Invoice panel open/close");
+    public void onOpenFormPanel(@BindingParam("parentPanel") Center parentPanel) {
+        log.info("Panel open/close");
         parentPanel.invalidate();
     }
 
     @Command
-    public void onClickInvoicePanel(@BindingParam("parentPanel") Center parentPanel, @BindingParam("panel") Panel panel) {
-        log.info("Invoice panel click");
+    public void onClickFormPanel(@BindingParam("parentPanel") Center parentPanel, @BindingParam("panel") Panel panel) {
+        log.info("Panel click");
         panel.setOpen(!panel.isOpen());
         parentPanel.invalidate();
     }
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java b/lis-ui/src/main/java/hu/user/lis/ui/editor/TreasuryEditorModel.java
new file mode 100644 (file)
index 0000000..b4f818b
--- /dev/null
@@ -0,0 +1,115 @@
+package hu.user.lis.ui.editor;
+
+import hu.user.lis.db.Treasury;
+import hu.user.lis.services.data.TreasuryService;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.log4j.Log4j2;
+import org.zkoss.bind.BindContext;
+import org.zkoss.bind.BindUtils;
+import org.zkoss.bind.ValidationContext;
+import org.zkoss.bind.annotation.*;
+import org.zkoss.bind.validator.AbstractValidator;
+import org.zkoss.zk.ui.Component;
+import org.zkoss.zk.ui.Executions;
+import org.zkoss.zk.ui.event.Event;
+import org.zkoss.zk.ui.event.Events;
+import org.zkoss.zk.ui.event.UploadEvent;
+import org.zkoss.zk.ui.select.annotation.VariableResolver;
+import org.zkoss.zk.ui.select.annotation.WireVariable;
+import org.zkoss.zkplus.spring.DelegatingVariableResolver;
+import org.zkoss.zul.Messagebox;
+import org.zkoss.zul.Window;
+
+import java.util.Objects;
+
+@Log4j2
+@Getter
+@Setter
+@VariableResolver(DelegatingVariableResolver.class)
+public class TreasuryEditorModel extends AbstractValidator {
+    private Treasury origDocument;
+    private Treasury formDocument;
+    @WireVariable
+    private TreasuryService treasuryServiceImpl;
+    private boolean formInvalid = true;
+
+    @Init
+    public void init() {
+        log.info("Initialized");
+        origDocument = (Treasury) Executions.getCurrent().getArg().get("origDocument");
+        formDocument = (Treasury) Executions.getCurrent().getArg().get("formDocument");
+    }
+
+    @Command
+    public void onCloseWindow(@BindingParam("target") Window target, @BindingParam("select") boolean select) {
+        if (select && formInvalid) {
+            return;
+        }
+        Event closeEvent = new Event("onClose", target, select ? formDocument : null);
+        Events.postEvent(closeEvent);
+    }
+
+    @Override
+    @NotifyChange("formInvalid")
+    public void validate(ValidationContext ctx) {
+        Component target = ctx.getBindContext().getComponent();
+        String property = ctx.getProperty().getProperty();
+        Object value = ctx.getProperty().getValue();
+        log.info("Validating caused by {} {} {}", target.getId(), property, value);
+        try {
+            Treasury newData = treasuryServiceImpl.copy(formDocument, property, value);
+            validate(newData);
+        } catch (Exception e) {
+            log.catching(e);
+        }
+
+    }
+
+    private void validate(Treasury newData) {
+        updateFormInvalid(false);
+        if (!Objects.isNull(origDocument) && treasuryServiceImpl.toString(origDocument).equals(treasuryServiceImpl.toString(newData))) {
+            log.info("Document not changed");
+            updateFormInvalid(true);
+            return;
+        }
+
+        boolean invalid = false;
+        if (newData.getBuyAmount() <= 0 ||
+                newData.getSellAmount() <= 0 ||
+                Objects.isNull(newData.getValueDate()) ||
+                Objects.isNull(newData.getTransactionDate())
+        ) {
+            invalid = true;
+        }
+
+        if (invalid) {
+            log.info("Document is not valid");
+            updateFormInvalid(true);
+        }
+    }
+
+    private void updateFormInvalid(boolean invalid) {
+        setFormInvalid(invalid);
+        BindUtils.postNotifyChange(this, "formInvalid");
+    }
+
+    @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(treasuryServiceImpl.copy(formDocument));
+    }
+
+    @Command
+    public void onRemoveFile() {
+        formDocument.setFile(null);
+        BindUtils.postNotifyChange(this.formDocument, "file");
+        validate(treasuryServiceImpl.copy(formDocument));
+    }
+}
index c1f115feb1c0aa193aa601068c039122608a85ee..285a3f92fffa0a49194ae0bbc378227bde025194 100644 (file)
@@ -30,7 +30,7 @@
                                 <hlayout>
                                     <vlayout>
                                         <label value="Sorszám"/>
-                                        <datebox instant="true" value="@bind(vm.formDocument.humanId) @validator(vm)"
+                                        <textbox instant="true" value="@bind(vm.formDocument.humanId) @validator(vm)"
                                                  forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                     <vlayout>
index 1c49907b0d52ceb9b45cd9d05d4dbc8c78a5a453..416fd6ff50631ea7f5376ce4b27ae4fc37bc8e19 100644 (file)
@@ -30,7 +30,7 @@
                                 <hlayout>
                                     <vlayout>
                                         <label value="Sorszám"/>
-                                        <datebox instant="true" value="@bind(vm.formDocument.humanId) @validator(vm)"
+                                        <textbox instant="true" value="@bind(vm.formDocument.humanId) @validator(vm)"
                                                  forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
                                     </vlayout>
                                     <vlayout>
index 28c573c09f524219266b021e198401db4954d3c0..22bbb9a9dc7e257f9399b04df99e49fc633ff04e 100644 (file)
@@ -9,7 +9,7 @@
             <center id="centerPanel" border="none" vflex="true" hflex="true" autoscroll="true">
                 <vlayout hflex="true" vflex="min">
 
-                    <tabbox height="400px">
+                    <tabbox height="300px">
                         <tabs>
                             <tab label="Adatok" selected="true"/>
                             <tab label="Résztvevők"/>
                                 </vlayout>
                             </tabpanel>
                             <tabpanel>
-                                <vlayout>
-                                    <toolbar>
-                                        <textbox value="@bind(vm.partialAssociateName)" instant="true"
-                                                 onChanging="@command('searchAssociate')"/>
-                                    </toolbar>
-                                    <listbox model="@load(vm.associatesDataModel)"
-                                             multiple="false"
-                                             onAfterRender="@command('onAfterRenderAssociates')">
-                                        <custom-attributes org.zkoss.zul.listbox.selectOnHighlight.disabled="true"/>
+                                <borderlayout>
+                                    <!--                                    <north flex="true">-->
+                                    <!--                                        <toolbar>-->
+                                    <!--                                            <textbox instant="true" value="@bind(vm.partialAssociateName)"/>-->
+                                    <!--                                            <toolbarbutton iconSclass="z-icon-remove"-->
+                                    <!--                                                           onClick="@command('onResetAssociateFilter')"/>-->
+                                    <!--                                        </toolbar>-->
+                                    <!--                                    </north>-->
+                                    <center border="none" flex="true">
+                                        <listbox model="@load(vm.associatesDataModel)"
+                                                 multiple="false" vflex="true"
+                                                 onAfterRender="@command('onAfterRenderAssociates')">
+                                            <custom-attributes org.zkoss.zul.listbox.selectOnHighlight.disabled="true"/>
 
-                                        <listhead>
-                                            <listheader hflex="min" label="Tag" align="left"/>
-                                            <listheader label="Név" align="left"/>
-                                            <listheader label="Login" align="left"/>
-                                        </listhead>
-                                        <template name="model">
-                                            <listitem>
-                                                <listcell>
-                                                    <checkbox checked="@bind(vm.formAssociates[each.id])"
-                                                              onCheck="@command('onAssociateChecked')"/>
-                                                </listcell>
-                                                <listcell label="@load(each.name)"/>
-                                                <listcell label="@load(each.login)"/>
-                                            </listitem>
-                                        </template>
-                                    </listbox>
-                                </vlayout>
+                                            <listhead>
+                                                <listheader hflex="min" label="Tag" align="left"/>
+                                                <listheader label="Név" align="left"/>
+                                                <listheader label="Login" align="left"/>
+                                            </listhead>
+                                            <template name="model">
+                                                <listitem>
+                                                    <listcell>
+                                                        <checkbox checked="@bind(vm.formAssociates[each.id])"
+                                                                  onCheck="@command('onAssociateChecked')"/>
+                                                    </listcell>
+                                                    <listcell label="@load(each.name)"/>
+                                                    <listcell label="@load(each.login)"/>
+                                                </listitem>
+                                            </template>
+                                        </listbox>
+                                    </center>
+                                </borderlayout>
                             </tabpanel>
                         </tabpanels>
                     </tabbox>
                     <panel collapsible="true" open="false" border="rounded"
-                           onOpen="@command('onOpenInvoicePanel', parentPanel=centerPanel)">
+                           onOpen="@command('onOpenFormPanel', parentPanel=centerPanel)">
                         <caption label="Kimenő számlák"
-                                 onClick="@command('onClickInvoicePanel', parentPanel=centerPanel, panel=self.parent)"/>
+                                 onClick="@command('onClickFormPanel', parentPanel=centerPanel, panel=self.parent)"/>
                         <panelchildren>
                             <vlayout>
                                 <toolbar>
                     </panel>
 
                     <panel collapsible="true" open="false" border="rounded"
-                           onOpen="@command('onOpenInvoicePanel', parentPanel=centerPanel)">
+                           onOpen="@command('onOpenFormPanel', parentPanel=centerPanel)">
                         <caption label="Bejövő számlák"
-                                 onClick="@command('onClickInvoicePanel', parentPanel=centerPanel, panel=self.parent)"/>
+                                 onClick="@command('onClickFormPanel', parentPanel=centerPanel, panel=self.parent)"/>
                         <panelchildren>
                             <vlayout>
                                 <toolbar>
                     </panel>
 
                     <panel collapsible="true" open="false" border="rounded"
-                           onOpen="@command('onOpenInvoicePanel', parentPanel=centerPanel)">
+                           onOpen="@command('onOpenFormPanel', parentPanel=centerPanel)">
                         <caption label="Treasury műveletek"
-                                 onClick="@command('onClickInvoicePanel', parentPanel=centerPanel, panel=self.parent)"/>
+                                 onClick="@command('onClickFormPanel', parentPanel=centerPanel, panel=self.parent)"/>
                         <panelchildren>
                             <vlayout>
                                 <toolbar>
diff --git a/lis-ui/src/main/resources/web/treasury-editor.zul b/lis-ui/src/main/resources/web/treasury-editor.zul
new file mode 100644 (file)
index 0000000..1e13b5c
--- /dev/null
@@ -0,0 +1,104 @@
+<?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());
+    </zscript>
+    <window id="invoicePopup" width="50%" height="500px" closable="true"
+            maximizable="true" sizable="true" viewModel="@id('vm') @init('hu.user.lis.ui.editor.TreasuryEditorModel')">
+        <caption label="Treasury szerkesztés"/>
+        <borderlayout>
+            <center border="none" vflex="true" hflex="true">
+                <tabbox vflex="true" hflex="true">
+                    <tabs>
+                        <tab label="Adatok" selected="true"/>
+                        <tab label="Számlakép"/>
+                    </tabs>
+                    <tabpanels>
+                        <tabpanel>
+                            <vlayout hflex="true">
+                                <groupbox title="Eladás" hflex="true">
+                                    <hlayout>
+                                        <vlayout>
+                                            <label value="Pénznem"/>
+                                            <combobox instant="true" model="${currencies}"
+                                                      selectedItem="@bind(vm.formDocument.sellCurrency) @validator(vm)"
+                                                      forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+
+                                        </vlayout>
+                                        <vlayout>
+                                            <label value="Összeg"/>
+                                            <doublebox value="@bind(vm.formDocument.sellAmount) @validator(vm)"
+                                                       format="locale:hu-HU" instant="true"
+                                                       forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                                        </vlayout>
+                                    </hlayout>
+                                </groupbox>
+                                <groupbox title="Vétel" hflex="true">
+                                    <hlayout>
+                                        <vlayout>
+                                            <label value="Pénznem"/>
+                                            <combobox instant="true" model="${currencies}"
+                                                      selectedItem="@bind(vm.formDocument.buyCurrency) @validator(vm)"
+                                                      forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+
+                                        </vlayout>
+                                        <vlayout>
+                                            <label value="Összeg"/>
+                                            <doublebox value="@bind(vm.formDocument.buyAmount) @validator(vm)"
+                                                       format="locale:hu-HU" instant="true"
+                                                       forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                                        </vlayout>
+                                    </hlayout>
+                                </groupbox>
+                                <hlayout>
+                                    <vlayout>
+                                        <label value="Üzletkötés dátuma"/>
+                                        <datebox instant="true" format="yyyy. MM. dd."
+                                                 value="@bind(vm.formDocument.transactionDate) @validator(vm)"
+                                                 forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                                    </vlayout>
+                                    <vlayout>
+                                        <label value="Értéknap"/>
+                                        <datebox instant="true" format="yyyy. MM. dd."
+                                                 value="@bind(vm.formDocument.valueDate) @validator(vm)"
+                                                 forward="onOK=submit.onClick, onCancel=cancel.onClick"/>
+                                    </vlayout>
+                                </hlayout>
+                            </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=invoicePopup, select=false)"/>
+                    <button id="submit" label="Mentés"
+                            onClick="@command('onCloseWindow', target=invoicePopup, select=true)"
+                            disabled="@bind(vm.formInvalid)"/>
+                </hlayout>
+            </south>
+        </borderlayout>
+    </window>
+</zk>
\ No newline at end of file