From 98990c8fdc0b745a9c12bb99dded5afbc9aec13a Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1s=C3=A1ry=20D=C3=A1niel?= Date: Fri, 24 Nov 2023 22:35:19 +0100 Subject: [PATCH] InvoiceImport V2 completed --- ...oice.sql => 015_add_status_to_invoice.sql} | 6 +- .../src/main/java/hu/user/lis/db/Invoice.java | 16 +- .../java/hu/user/lis/db/InvoiceStatus.java | 16 ++ .../repository/InvoiceImportRepository.java | 3 + .../InvoiceRepositorySearchImpl.java | 2 +- .../db/repository/filter/InvoiceFilter.java | 3 + .../main/java/hu/user/lis/ui/Constants.java | 1 + .../lis/ui/config/ResourceConfigurer.java | 1 + .../hu/user/lis/ui/data/InvoiceDataModel.java | 5 +- .../lis/ui/view/ApproveInvoicesViewModel.java | 9 +- .../lis/ui/view/AssignInvoicesViewModel.java | 7 +- .../ImportInvoicesSuspendedViewModel.java | 172 ++++++++++++++++++ .../user/lis/ui/view/InvoicesViewModel.java | 6 +- .../web/import-invoices-suspended.zul | 68 +++++++ lis-ui/src/main/resources/web/index.zul | 4 + lis-ui/src/main/resources/web/invoices.zul | 72 ++++---- .../workflow/invoice/DownloadInvoiceData.java | 29 ++- 17 files changed, 369 insertions(+), 51 deletions(-) rename lis-db/migrations/scripts/{015_add_active_to_invoice.sql => 015_add_status_to_invoice.sql} (56%) create mode 100644 lis-db/src/main/java/hu/user/lis/db/InvoiceStatus.java create mode 100644 lis-ui/src/main/java/hu/user/lis/ui/view/ImportInvoicesSuspendedViewModel.java create mode 100644 lis-ui/src/main/resources/web/import-invoices-suspended.zul diff --git a/lis-db/migrations/scripts/015_add_active_to_invoice.sql b/lis-db/migrations/scripts/015_add_status_to_invoice.sql similarity index 56% rename from lis-db/migrations/scripts/015_add_active_to_invoice.sql rename to lis-db/migrations/scripts/015_add_status_to_invoice.sql index 07fb06b..c261fab 100644 --- a/lis-db/migrations/scripts/015_add_active_to_invoice.sql +++ b/lis-db/migrations/scripts/015_add_status_to_invoice.sql @@ -1,11 +1,11 @@ -- // add active to invoice -- Migration SQL that makes the change goes here. -ALTER TABLE invoice ADD COLUMN active SMALLINT NOT NULL DEFAULT 0; -UPDATE invoice SET active=1; +ALTER TABLE invoice ADD COLUMN status INTEGER NOT NULL DEFAULT 0; +UPDATE invoice SET status=1; -- //@UNDO -- SQL to undo the change goes here. -ALTER TABLE invoice DROP COLUMN active; +ALTER TABLE invoice DROP COLUMN status; CALL SYSPROC.ADMIN_CMD('REORG TABLE invoice'); diff --git a/lis-db/src/main/java/hu/user/lis/db/Invoice.java b/lis-db/src/main/java/hu/user/lis/db/Invoice.java index bb72eeb..3be87a4 100644 --- a/lis-db/src/main/java/hu/user/lis/db/Invoice.java +++ b/lis-db/src/main/java/hu/user/lis/db/Invoice.java @@ -21,20 +21,34 @@ public class Invoice implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; + String humanId; + String title; + Currency currency; + double netAmount; + double grossAmount; + double vatAmount; + Date completionDate; + Date createDate; + Date paymentDeadline; + @Column(nullable = false, insertable = false, updatable = false) boolean incoming; - boolean active; + + InvoiceStatus status; + boolean paid; + boolean planned; + byte[] file; @OneToOne diff --git a/lis-db/src/main/java/hu/user/lis/db/InvoiceStatus.java b/lis-db/src/main/java/hu/user/lis/db/InvoiceStatus.java new file mode 100644 index 0000000..c7387c0 --- /dev/null +++ b/lis-db/src/main/java/hu/user/lis/db/InvoiceStatus.java @@ -0,0 +1,16 @@ +package hu.user.lis.db; + + +import lombok.Getter; + +@Getter +public enum InvoiceStatus { + INACTIVE(0), ACTIVE(1), SUSPENDED(2); + final int val; + + InvoiceStatus(int val) { + this.val = val; + } + + +} diff --git a/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceImportRepository.java b/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceImportRepository.java index 0994af8..b6e73e2 100644 --- a/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceImportRepository.java +++ b/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceImportRepository.java @@ -1,5 +1,6 @@ package hu.user.lis.db.repository; +import hu.user.lis.db.Invoice; import hu.user.lis.db.InvoiceImport; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,4 +10,6 @@ public interface InvoiceImportRepository extends JpaRepository findTopByOrderByInvoiceCreateDate(); + + Optional findByInvoice(Invoice selectedEntity); } diff --git a/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceRepositorySearchImpl.java b/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceRepositorySearchImpl.java index 47b9d6d..1c4be4f 100644 --- a/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceRepositorySearchImpl.java +++ b/lis-db/src/main/java/hu/user/lis/db/repository/InvoiceRepositorySearchImpl.java @@ -24,7 +24,7 @@ public class InvoiceRepositorySearchImpl implements InvoiceRepositorySearch { Predicate[] getPredicates(CriteriaBuilder cb, Root root, InvoiceFilter filter) { List predicates = new ArrayList<>(); - predicates.add(cb.equal(root.get("active"), true)); + predicates.add(cb.equal(root.get("status"), filter.getStatus())); if (Objects.nonNull(filter.getPartner())) { predicates.add(cb.equal(root.get("partner"), filter.getPartner())); diff --git a/lis-db/src/main/java/hu/user/lis/db/repository/filter/InvoiceFilter.java b/lis-db/src/main/java/hu/user/lis/db/repository/filter/InvoiceFilter.java index f4b1fbd..09c2732 100644 --- a/lis-db/src/main/java/hu/user/lis/db/repository/filter/InvoiceFilter.java +++ b/lis-db/src/main/java/hu/user/lis/db/repository/filter/InvoiceFilter.java @@ -1,5 +1,6 @@ package hu.user.lis.db.repository.filter; +import hu.user.lis.db.InvoiceStatus; import hu.user.lis.db.Partner; import hu.user.lis.db.Project; import lombok.*; @@ -22,6 +23,8 @@ public class InvoiceFilter extends PageableFilter { private boolean paid; + private InvoiceStatus status; + private Date paymentDeadLineFrom; private Date paymentDeadLineTo; diff --git a/lis-ui/src/main/java/hu/user/lis/ui/Constants.java b/lis-ui/src/main/java/hu/user/lis/ui/Constants.java index cbf9e29..5587187 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/Constants.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/Constants.java @@ -27,6 +27,7 @@ public class Constants { public static final String NAV_SETTINGS = "/settings"; public static final String NAV_IMPORT_INVOICES_ASSIGN = "/import-invoices-assign"; public static final String NAV_IMPORT_INVOICES_APPROVE = "/import-invoices-approve"; + public static final String NAV_IMPORT_INVOICES_SUSPENDED = "/import-invoices-suspended"; public static final String NAV_LOGIN = "/login"; public static final String NAV_LOGOUT = "/logout"; public static final String NAV_ROOT = "/"; diff --git a/lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java b/lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java index cf7a390..946301d 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/config/ResourceConfigurer.java @@ -24,6 +24,7 @@ public class ResourceConfigurer { Constants.NAV_SERVICE_RECORDS, Constants.NAV_IMPORT_INVOICES_ASSIGN, Constants.NAV_IMPORT_INVOICES_APPROVE, + Constants.NAV_IMPORT_INVOICES_SUSPENDED, Constants.NAV_INVOICES, Constants.NAV_INVOICE_PAYMENT, Constants.NAV_SETTINGS, diff --git a/lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java b/lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java index faafc11..90cb340 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/data/InvoiceDataModel.java @@ -2,6 +2,7 @@ package hu.user.lis.ui.data; import hu.user.lis.db.IncomingInvoice; import hu.user.lis.db.Invoice; +import hu.user.lis.db.InvoiceStatus; import hu.user.lis.db.OutgoingInvoice; import hu.user.lis.db.repository.InvoiceRepository; import hu.user.lis.service.data.EntityDataService; @@ -34,11 +35,11 @@ public class InvoiceDataModel { } public IncomingInvoice createNewIncomingInvoice() { - return IncomingInvoice.builder().incoming(true).active(true).build(); + return IncomingInvoice.builder().incoming(true).status(InvoiceStatus.ACTIVE).build(); } public OutgoingInvoice createNewOutgoingInvoice() { - return OutgoingInvoice.builder().active(true).build(); + return OutgoingInvoice.builder().status(InvoiceStatus.ACTIVE).build(); } public void save(Invoice modifiedEntity) { diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/ApproveInvoicesViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/ApproveInvoicesViewModel.java index c410c57..ebe3e19 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/ApproveInvoicesViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/ApproveInvoicesViewModel.java @@ -2,6 +2,7 @@ package hu.user.lis.ui.view; import com.google.common.collect.ImmutableMap; import hu.user.lis.db.Invoice; +import hu.user.lis.db.InvoiceStatus; import hu.user.lis.db.repository.InvoiceRepository; import hu.user.lis.db.repository.PartnerRepository; import hu.user.lis.ui.Constants; @@ -86,16 +87,20 @@ public class ApproveInvoicesViewModel extends EntityViewModel implem editorWindow.addEventListener("onClose", e -> { if (Objects.nonNull(e.getData())) { Map results = (Map) e.getData(); + Invoice modifiedEntity = (Invoice) results.get("modifiedEntity"); InvoiceImportStatus status = (InvoiceImportStatus) results.get("status"); if (InvoiceImportStatus.APPROVE.equals(status)) { - Invoice modifiedEntity = (Invoice) results.get("modifiedEntity"); - modifiedEntity.setActive(true); + modifiedEntity.setStatus(InvoiceStatus.ACTIVE); invoiceRepository.save(modifiedEntity); approveInvoicesDataModel.completeTask(getSelectedEntity(), ImmutableMap.of( "invoiceEntity", modifiedEntity, "status", status )); } else { + if (InvoiceImportStatus.SKIP.equals(status)) { + modifiedEntity.setStatus(InvoiceStatus.SUSPENDED); + invoiceRepository.save(modifiedEntity); + } approveInvoicesDataModel.completeTask(getSelectedEntity(), ImmutableMap.of( "status", status )); diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/AssignInvoicesViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/AssignInvoicesViewModel.java index 68d8e6c..ec73c91 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/AssignInvoicesViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/AssignInvoicesViewModel.java @@ -2,6 +2,7 @@ package hu.user.lis.ui.view; import com.google.common.collect.ImmutableMap; import hu.user.lis.db.Invoice; +import hu.user.lis.db.InvoiceStatus; import hu.user.lis.db.repository.InvoiceRepository; import hu.user.lis.ui.Constants; import hu.user.lis.ui.data.AssignInvoicesDataModel; @@ -88,15 +89,19 @@ public class AssignInvoicesViewModel extends EntityViewModel impleme editorWindow.addEventListener("onClose", e -> { if (Objects.nonNull(e.getData())) { Map results = (Map) e.getData(); + Invoice modifiedEntity = (Invoice) results.get("modifiedEntity"); InvoiceImportStatus status = (InvoiceImportStatus) results.get("status"); if (InvoiceImportStatus.ASSIGN.equals(status)) { - Invoice modifiedEntity = (Invoice) results.get("modifiedEntity"); invoiceRepository.save(modifiedEntity); assignInvoicesDataModel.completeTask(getSelectedEntity(), ImmutableMap.of( "invoiceEntity", modifiedEntity, "status", status )); } else { + if (InvoiceImportStatus.SKIP.equals(status)) { + modifiedEntity.setStatus(InvoiceStatus.SUSPENDED); + invoiceRepository.save(modifiedEntity); + } assignInvoicesDataModel.completeTask(getSelectedEntity(), ImmutableMap.of( "status", status )); diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/ImportInvoicesSuspendedViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/ImportInvoicesSuspendedViewModel.java new file mode 100644 index 0000000..942f64a --- /dev/null +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/ImportInvoicesSuspendedViewModel.java @@ -0,0 +1,172 @@ +package hu.user.lis.ui.view; + +import com.google.common.collect.ImmutableMap; +import hu.user.lis.db.*; +import hu.user.lis.db.repository.InvoiceImportRepository; +import hu.user.lis.db.repository.InvoiceRepository; +import hu.user.lis.db.repository.filter.InvoiceFilter; +import hu.user.lis.ui.Constants; +import hu.user.lis.ui.data.InvoiceDataModel; +import hu.user.lis.ui.data.InvoicesDataModel; +import hu.user.lis.ui.data.common.CachedSpringDataModel; +import hu.user.lis.ui.editor.common.Editors; +import hu.user.lis.ui.editor.selector.EntitySelectorRouter; +import hu.user.lis.ui.event.EventBus; +import hu.user.lis.ui.view.common.EntityViewModel; +import hu.user.lis.workflow.invoice.service.WorkflowManagerService; +import lombok.Getter; +import lombok.extern.log4j.Log4j2; +import org.zkoss.bind.PropertyChangeEvent; +import org.zkoss.bind.annotation.*; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.select.annotation.WireVariable; + +import java.util.Objects; +import java.util.Optional; + +import static hu.user.lis.ui.data.common.CachedDataModel.ASCENDING; +import static hu.user.lis.ui.data.common.CachedDataModel.NATURAL; + +@Log4j2 +public class ImportInvoicesSuspendedViewModel extends EntityViewModel implements EventListener { + @Getter + private InvoiceFilter invoiceFilter; + + @WireVariable + private EventBus eventBus; + + @Getter + @WireVariable + private EntitySelectorRouter entitySelectorRouter; + + @Getter + @WireVariable + private InvoicesDataModel invoicesDataModel; + + @WireVariable + private InvoiceDataModel invoiceDataModel; + + @WireVariable + private InvoiceImportRepository invoiceImportRepository; + + @WireVariable + private WorkflowManagerService workflowManagerService; + + @WireVariable + private InvoiceRepository invoiceRepository; + + @Init + @Override + public void init() { + super.init(); + invoiceFilter = InvoiceFilter.builder() + .incoming(true) + .status(InvoiceStatus.SUSPENDED) + .build(); + + eventBus.register(this); + eventBus.registerForBinding(this); + addColumns(ImmutableMap.of( + "partner.humanId", NATURAL, + "partner.name", NATURAL, + "partner.vatNr", NATURAL, + "project.name", NATURAL, + "paymentDeadline", ASCENDING, + "grossAmount", NATURAL, + "currency", NATURAL, + "incoming", NATURAL + )); + refresh(); + } + + @Override + @AfterCompose + public void onAfterCompose(@ContextParam(ContextType.VIEW) Component view) { + entitySelectorRouter.configureSelector(Partner.class, this, "invoiceFilter.partner"); + entitySelectorRouter.configureSelector(Project.class, this, "invoiceFilter.project"); + } + + @Override + protected CachedSpringDataModel getDataModel() { + return invoicesDataModel; + } + + @Override + protected String getNavigation() { + return Constants.NAV_IMPORT_INVOICES_SUSPENDED; + } + + @Command + public void refresh() { + invoicesDataModel.clearSelection(); + invoicesDataModel.search(invoiceFilter); + } + + @Command + public void search() { + refresh(); + } + + @Override + public void onEvent(Event evt) throws Exception { + if (evt instanceof PropertyChangeEvent) { + PropertyChangeEvent propertyEvent = (PropertyChangeEvent) evt; +// (this.equals(propertyEvent.getBase()) && propertyEvent.getProperty().startsWith("invoiceFilter"))) + if (invoiceFilter.equals(propertyEvent.getBase())) { + log.info("Refresh needed, {} changed", propertyEvent.getProperty()); + + refresh(); + } + } + } + + @Destroy + public void onDestroy() { + log.info("Destroy {}", getClass().getSimpleName()); + eventBus.unregister(this); + } + + @Command + public void onEdit() { + Invoice invoice = getSelectedEntity(); + if (invoice.isIncoming()) { + onEditIncoming(); + } else { + onEditOutgoing(); + } + } + + public void onEditIncoming() { + IncomingInvoice selectedIncomingInvoice = (IncomingInvoice) getSelectedEntity(); + IncomingInvoice entity = invoiceDataModel.clone(selectedIncomingInvoice); + Editors.doEdit(Editors.INCOMING_INVOICE, entity, selectedIncomingInvoice, modifiedEntity -> { + invoiceDataModel.save(modifiedEntity); + refresh(); + }); + } + + public void onEditOutgoing() { + OutgoingInvoice selectedOutgoingInvoice = (OutgoingInvoice) getSelectedEntity(); + OutgoingInvoice entity = invoiceDataModel.clone((OutgoingInvoice) getSelectedEntity()); + Editors.doEdit(Editors.OUTGOING_INVOICE, entity, selectedOutgoingInvoice, modifiedEntity -> { + invoiceDataModel.save(modifiedEntity); + refresh(); + }); + } + + @Command + public void onStartAssignment() { + Invoice invoice = getSelectedEntity(); + if (Objects.nonNull(invoice)) { + Optional opInvoiceImport = invoiceImportRepository.findByInvoice(invoice); + opInvoiceImport.ifPresent(invoiceImport -> { + workflowManagerService.startAssignIncomingInvoiceProcess(invoiceImport); + invoice.setStatus(InvoiceStatus.INACTIVE); + invoiceRepository.save(invoice); + refresh(); + }); + } + } +} diff --git a/lis-ui/src/main/java/hu/user/lis/ui/view/InvoicesViewModel.java b/lis-ui/src/main/java/hu/user/lis/ui/view/InvoicesViewModel.java index 97e5c7b..1b4a0d6 100644 --- a/lis-ui/src/main/java/hu/user/lis/ui/view/InvoicesViewModel.java +++ b/lis-ui/src/main/java/hu/user/lis/ui/view/InvoicesViewModel.java @@ -27,7 +27,7 @@ import static hu.user.lis.ui.data.common.CachedDataModel.NATURAL; @Log4j2 public class InvoicesViewModel extends EntityViewModel implements EventListener { @Getter - private final InvoiceFilter invoiceFilter = InvoiceFilter.builder().incoming(true).build(); + private InvoiceFilter invoiceFilter; @WireVariable private EventBus eventBus; @@ -47,6 +47,10 @@ public class InvoicesViewModel extends EntityViewModel implements Event @Override public void init() { super.init(); + invoiceFilter = InvoiceFilter.builder() + .incoming(true) + .status(InvoiceStatus.ACTIVE) + .build(); eventBus.register(this); eventBus.registerForBinding(this); addColumns(ImmutableMap.of( diff --git a/lis-ui/src/main/resources/web/import-invoices-suspended.zul b/lis-ui/src/main/resources/web/import-invoices-suspended.zul new file mode 100644 index 0000000..1049dee --- /dev/null +++ b/lis-ui/src/main/resources/web/import-invoices-suspended.zul @@ -0,0 +1,68 @@ + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+
+
+
\ No newline at end of file diff --git a/lis-ui/src/main/resources/web/index.zul b/lis-ui/src/main/resources/web/index.zul index b303ce1..3682756 100644 --- a/lis-ui/src/main/resources/web/index.zul +++ b/lis-ui/src/main/resources/web/index.zul @@ -110,6 +110,10 @@ label="@bind(vm.approveInvoicesLabel)" onClick="@command(vm.selectPage('~./import-invoices-approve.zul'))" sclass="@bind(vm.approveInvoiceMenuClassName)"/> + + diff --git a/lis-ui/src/main/resources/web/invoices.zul b/lis-ui/src/main/resources/web/invoices.zul index 5ac7d57..0eb1629 100644 --- a/lis-ui/src/main/resources/web/invoices.zul +++ b/lis-ui/src/main/resources/web/invoices.zul @@ -4,43 +4,45 @@ - - - - - - - +
projectSuggestions = new ArrayList<>(); IncomingInvoice invoice = incomingInvoiceFetcherService.getInvoiceDataOnline(invoiceXml, projectSuggestions); + invoice.setStatus(InvoiceStatus.INACTIVE); + Optional partnerEntity = partnerRepository.findByVatNr(invoice.getPartner().getVatNr()); if (partnerEntity.isPresent()) { if (isInvoiceImported(invoice.getHumanId(), partnerEntity.get())) { log.info("Skipping already imported {} {}, {}", partnerEntity.get().getName(), partnerEntity.get().getVatNr(), invoice.getHumanId()); - return; + return null; } invoice.setPartner(partnerEntity.get()); } else { @@ -55,13 +74,13 @@ public class DownloadInvoiceData implements JavaDelegate { partnerRepository.save(invoice.getPartner()); } invoiceRepository.save(invoice); + InvoiceImport invoiceImport = InvoiceImport.builder() .invoice(invoice) .suggestedProjects(projectSuggestions) .build(); invoiceImportRepository.save(invoiceImport); - workflowManagerService.startAssignIncomingInvoiceProcess(invoiceImport); - log.info("Invoice {} {} processed", invoice.getHumanId(), invoice.getPartner().getName()); + return invoiceImport; } private boolean isInvoiceImported(String humanId, Partner partner) { -- 2.54.0