From: Vásáry Dániel Date: Mon, 4 Mar 2024 15:26:55 +0000 (+0100) Subject: Net/Gross margin calculation completed X-Git-Url: http://git.useribm.hu/?a=commitdiff_plain;h=5ed0d2dc9b42f763234ac2c98e745a6c569b9d04;p=sly-crm.git Net/Gross margin calculation completed --- diff --git a/sly-crm-app/src/main/resources/logback-dev.xml b/sly-crm-app/src/main/resources/logback-dev.xml index 5773e16..b040aa4 100644 --- a/sly-crm-app/src/main/resources/logback-dev.xml +++ b/sly-crm-app/src/main/resources/logback-dev.xml @@ -3,7 +3,7 @@ - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.} \(%line\)): %msg%n%throwable diff --git a/sly-crm-db/migrations/scripts/030_add_price_exchange_fields_to_invoice.sql b/sly-crm-db/migrations/scripts/030_add_price_exchange_fields_to_invoice.sql new file mode 100644 index 0000000..b73650b --- /dev/null +++ b/sly-crm-db/migrations/scripts/030_add_price_exchange_fields_to_invoice.sql @@ -0,0 +1,16 @@ +-- // add price exchange fields to invoice +-- Migration SQL that makes the change goes here. + +ALTER TABLE invoice + ADD COLUMN net_amount_huf DOUBLE + ADD COLUMN gross_amount_huf DOUBLE + ADD COLUMN exchange_rate DOUBLE; + +-- //@UNDO +-- SQL to undo the change goes here. + +ALTER TABLE invoice + DROP COLUMN net_amount_huf + DROP COLUMN gross_amount_huf + DROP COLUMN exchange_rate; +CALL SYSPROC.ADMIN_CMD('REORG TABLE invoice'); diff --git a/sly-crm-db/migrations/scripts/031_add_price_exchange_fields_to_treasury.sql b/sly-crm-db/migrations/scripts/031_add_price_exchange_fields_to_treasury.sql new file mode 100644 index 0000000..75b3b11 --- /dev/null +++ b/sly-crm-db/migrations/scripts/031_add_price_exchange_fields_to_treasury.sql @@ -0,0 +1,18 @@ +-- // add price exchange fields to treasury +-- Migration SQL that makes the change goes here. + +ALTER TABLE treasury + ADD COLUMN buy_amount_huf DOUBLE + ADD COLUMN buy_exchange_rate DOUBLE + ADD COLUMN sell_amount_huf DOUBLE + ADD COLUMN sell_exchange_rate DOUBLE; + +-- //@UNDO +-- SQL to undo the change goes here. + +ALTER TABLE treasury + DROP COLUMN buy_amount_huf + DROP COLUMN buy_exchange_rate + DROP COLUMN sell_amount_huf + DROP COLUMN sell_exchange_rate; +CALL SYSPROC.ADMIN_CMD('REORG TABLE treasury'); diff --git a/sly-crm-db/src/main/java/hu/user/lis/db/Invoice.java b/sly-crm-db/src/main/java/hu/user/lis/db/Invoice.java index 8c5fe92..8a3f2e2 100644 --- a/sly-crm-db/src/main/java/hu/user/lis/db/Invoice.java +++ b/sly-crm-db/src/main/java/hu/user/lis/db/Invoice.java @@ -6,7 +6,15 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.SuperBuilder; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; import java.util.Date; @Getter @@ -40,6 +48,14 @@ public class Invoice extends IdEntity { private double vatAmount; + @Column(name = "net_amount_huf") + private Double netAmountHUF; + + @Column(name = "gross_amount_huf") + private Double grossAmountHUF; + + private Double exchangeRate; + private Date completionDate; private Date createDate; diff --git a/sly-crm-db/src/main/java/hu/user/lis/db/Treasury.java b/sly-crm-db/src/main/java/hu/user/lis/db/Treasury.java index a0adcd7..7756871 100644 --- a/sly-crm-db/src/main/java/hu/user/lis/db/Treasury.java +++ b/sly-crm-db/src/main/java/hu/user/lis/db/Treasury.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.SuperBuilder; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @@ -29,10 +30,20 @@ public class Treasury extends IdEntity { private double buyAmount; + @Column(name = "buy_amount_huf") + private Double buyAmountHUF; + + private Double buyExchangeRate; + private Currency buyCurrency; private double sellAmount; + @Column(name = "sell_amount_huf") + private Double sellAmountHUF; + + private Double sellExchangeRate; + private Currency sellCurrency; private Date transactionDate; diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/IncomeMargin.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/IncomeMargin.java deleted file mode 100644 index 98b119c..0000000 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/IncomeMargin.java +++ /dev/null @@ -1,15 +0,0 @@ -package hu.user.lis.ui.data; - -import hu.user.lis.db.Currency; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@Builder -public class -IncomeMargin { - Currency currency; - Double amount; -} diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java index 78c4c20..e58ed2d 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/IncomeMarginsDataModel.java @@ -1,69 +1,76 @@ package hu.user.lis.ui.data; import hu.user.lis.db.Currency; -import hu.user.lis.db.*; +import hu.user.lis.db.IncomingInvoice; +import hu.user.lis.db.Invoice; +import hu.user.lis.db.OutgoingInvoice; +import hu.user.lis.db.Project; +import hu.user.lis.db.ServiceRecord; +import hu.user.lis.db.Treasury; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.zkoss.bind.BindUtils; -import java.util.*; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; @Component @Log4j2 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class IncomeMarginsDataModel extends ArrayList { - public void recalculate(Project project, ServiceRecordsDataModel serviceRecordsDataModel) { +public class IncomeMarginsDataModel extends ArrayList { + public void recalculate(Project project, ServiceRecordsDataModel serviceRecordsDataModel) throws Exception { clear(); - Map balances = new HashMap<>(); + Map balances = new HashMap<>(); List outgoingInvoices = project.getOutgoingInvoices(); if (Objects.nonNull(outgoingInvoices)) { for (Invoice invoice : outgoingInvoices) { - addBalance(balances, invoice.getCurrency(), invoice.getNetAmount()); + addBalance(balances, MoneyAmount.fromInvoice(invoice)); } } List incomingInvoices = project.getIncomingInvoices(); if (Objects.nonNull(incomingInvoices)) { for (Invoice invoice : incomingInvoices) { - substractBalance(balances, invoice.getCurrency(), invoice.getNetAmount()); + subtractBalance(balances, MoneyAmount.fromInvoice(invoice)); } } List treasuries = project.getTreasuries(); if (Objects.nonNull(treasuries)) { for (Treasury treasury : treasuries) { - substractBalance(balances, treasury.getSellCurrency(), treasury.getSellAmount()); - addBalance(balances, treasury.getBuyCurrency(), treasury.getBuyAmount()); + subtractBalance(balances, MoneyAmount.fromTreasuryBuy(treasury)); + addBalance(balances, MoneyAmount.fromTreasurySell(treasury)); } } - for (int i = 0; i < serviceRecordsDataModel.getSize(); i++) { ServiceRecord serviceRecord = serviceRecordsDataModel.getElementAt(i); - substractBalance(balances, Currency.HUF, serviceRecord.getCost()); + subtractBalance(balances, MoneyAmount.fromServiceRecord(serviceRecord)); } - balances.entrySet().stream() - .map(s -> IncomeMargin.builder().currency(s.getKey()).amount(s.getValue()).build()) - .sorted(Comparator.comparing(IncomeMargin::getCurrency)) - .collect(Collectors.toCollection(() -> this)); - + balances.keySet().stream().sorted().forEach(currency -> this.add(balances.get(currency))); BindUtils.postNotifyChange(this, "*"); } - private void addBalance(Map balances, Currency currency, double amount) { - double currentBalance = balances.containsKey(currency) ? balances.get(currency) : 0; - currentBalance += amount; - balances.put(currency, currentBalance); + private void addBalance(Map balances, MoneyAmount moneyAmount) throws Exception { + MoneyAmount currentBalance = balances.containsKey(moneyAmount.getCurrency()) ? + balances.get(moneyAmount.getCurrency()) : + MoneyAmount.builder().currency(moneyAmount.getCurrency()).build(); + currentBalance.add(moneyAmount); + balances.put(moneyAmount.getCurrency(), currentBalance); } - private void substractBalance(Map balances, Currency currency, double amount) { - double currentBalance = balances.containsKey(currency) ? balances.get(currency) : 0; - currentBalance -= amount; - balances.put(currency, currentBalance); + private void subtractBalance(Map balances, MoneyAmount moneyAmount) throws Exception { + MoneyAmount currentBalance = balances.containsKey(moneyAmount.getCurrency()) ? + balances.get(moneyAmount.getCurrency()) : + MoneyAmount.builder().currency(moneyAmount.getCurrency()).build(); + currentBalance.subtract(moneyAmount); + balances.put(moneyAmount.getCurrency(), currentBalance); } } diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/MoneyAmount.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/MoneyAmount.java new file mode 100644 index 0000000..e1ca66a --- /dev/null +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/MoneyAmount.java @@ -0,0 +1,115 @@ +package hu.user.lis.ui.data; + +import hu.user.lis.db.Currency; +import hu.user.lis.db.Invoice; +import hu.user.lis.db.ServiceRecord; +import hu.user.lis.db.Treasury; +import hu.user.lis.db.Vat; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.Objects; + +@Getter +@Setter +@Builder +public class MoneyAmount { + Currency currency; + + @Builder.Default + Double netAmount = (double) 0; + @Builder.Default + Double grossAmount = (double) 0; + @Builder.Default + Double netAmountHUF = (double) 0; + @Builder.Default + Double grossAmountHUF = (double) 0; + @Builder.Default + Double exchangeRate = (double) 0; + + public void add(MoneyAmount money) throws Exception { + if (!money.getCurrency().equals(currency)) { + throw new Exception("Can't add different currencies"); + } + if (Objects.nonNull(money.getNetAmount())) { + netAmount += money.getNetAmount(); + } + if (Objects.nonNull(money.getGrossAmount())) { + grossAmount += money.getGrossAmount(); + } + if (Objects.nonNull(money.getNetAmountHUF())) { + netAmountHUF += money.getNetAmountHUF(); + } + if (Objects.nonNull(money.getGrossAmountHUF())) { + grossAmountHUF += money.getGrossAmountHUF(); + } + } + + public void subtract(MoneyAmount money) throws Exception { + if (!money.getCurrency().equals(currency)) { + throw new Exception("Can't subtract different currencies"); + } + if (Objects.nonNull(money.getNetAmount())) { + netAmount -= money.getNetAmount(); + } + if (Objects.nonNull(money.getGrossAmount())) { + grossAmount -= money.getGrossAmount(); + } + if (Objects.nonNull(money.getNetAmountHUF())) { + netAmountHUF -= money.getNetAmountHUF(); + } + if (Objects.nonNull(money.getGrossAmountHUF())) { + grossAmountHUF -= money.getGrossAmountHUF(); + } + } + + public static MoneyAmount fromInvoice(Invoice invoice) { + return MoneyAmount.builder() + .currency(invoice.getCurrency()) + .netAmount(invoice.getNetAmount()) + .grossAmount(invoice.getGrossAmount()) + .netAmountHUF(invoice.getNetAmountHUF()) + .grossAmountHUF(invoice.getGrossAmountHUF()) + .exchangeRate(invoice.getExchangeRate()) + .build(); + } + + public static MoneyAmount fromTreasuryBuy(Treasury treasury) { + return MoneyAmount.builder() + .currency(treasury.getBuyCurrency()) + .netAmount(treasury.getBuyAmount()) + .grossAmount(treasury.getBuyAmount()) + .netAmountHUF(treasury.getBuyAmountHUF()) + .build(); + + } + + public static MoneyAmount fromTreasurySell(Treasury treasury) { + return MoneyAmount.builder() + .currency(treasury.getSellCurrency()) + .netAmount(treasury.getSellAmount()) + .grossAmount(treasury.getSellAmount()) + .netAmountHUF(treasury.getSellAmountHUF()) + .build(); + } + + public static MoneyAmount fromServiceRecord(ServiceRecord serviceRecord) { + Vat monthlyVat = serviceRecord.getAssociate().getMonthlyVat(); + float vatPercent = monthlyVat.getVal(); + double grossAmount = serviceRecord.getCost(); + if (monthlyVat != Vat.PERCENT_0) { + grossAmount += vatPercent * serviceRecord.getCost() / 100; + } + + return MoneyAmount.builder() + .currency(Currency.HUF) + .netAmount(serviceRecord.getCost()) + .grossAmount(grossAmount) + .netAmountHUF(serviceRecord.getCost()) + .grossAmountHUF(grossAmount) + .exchangeRate((double) 1) + .build(); + + } +} diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java index 9b2de09..4a071af 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ProjectEditorModel.java @@ -1,13 +1,27 @@ package hu.user.lis.ui.editor; import com.google.common.collect.ImmutableMap; -import hu.user.lis.db.*; +import hu.user.lis.db.Associate; +import hu.user.lis.db.IncomingInvoice; +import hu.user.lis.db.Invoice; +import hu.user.lis.db.OutgoingInvoice; +import hu.user.lis.db.Partner; +import hu.user.lis.db.Project; +import hu.user.lis.db.ProjectAssociate; +import hu.user.lis.db.Treasury; import hu.user.lis.db.repository.InvoiceRepository; import hu.user.lis.service.data.EntityDocumentAction; import hu.user.lis.service.data.EntityDocumentService; import hu.user.lis.ui.Constants; import hu.user.lis.ui.converter.ProjectStatusConverter; -import hu.user.lis.ui.data.*; +import hu.user.lis.ui.data.AssociatesDataModel; +import hu.user.lis.ui.data.IncomeMarginsDataModel; +import hu.user.lis.ui.data.InvoiceDataModel; +import hu.user.lis.ui.data.ProjectAssociatesDataModel; +import hu.user.lis.ui.data.ProjectStatusDataModel; +import hu.user.lis.ui.data.ProjectsDataModel; +import hu.user.lis.ui.data.ServiceRecordsDataModel; +import hu.user.lis.ui.data.TreasuryDataModel; import hu.user.lis.ui.editor.common.Editors; import hu.user.lis.ui.editor.common.EntityEditorModel; import hu.user.lis.ui.editor.validator.FormValidator; @@ -19,7 +33,11 @@ import lombok.extern.log4j.Log4j2; import org.apache.commons.collections4.CollectionUtils; import org.springframework.transaction.annotation.Transactional; import org.zkoss.bind.BindUtils; -import org.zkoss.bind.annotation.*; +import org.zkoss.bind.annotation.BindingParam; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.Destroy; +import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.select.annotation.WireVariable; @@ -115,7 +133,7 @@ public class ProjectEditorModel extends EntityEditorModel { initAssociates(); serviceRecordsDataModel.search(getFormDocument(), true); getEntitySelectorRouter().configureSelector(Partner.class, getFormDocument(), "partner"); - incomeMarginsDataModel.recalculate(getFormDocument(), serviceRecordsDataModel); + safeRecalcMargin(); } @@ -415,7 +433,16 @@ public class ProjectEditorModel extends EntityEditorModel { @Override public void validate() { super.validate(); - incomeMarginsDataModel.recalculate(getFormDocument(), serviceRecordsDataModel); + safeRecalcMargin(); } + private void safeRecalcMargin() { + try { + incomeMarginsDataModel.recalculate(getFormDocument(), serviceRecordsDataModel); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + + } diff --git a/sly-crm-ui/src/main/resources/web/editor/project-editor.zul b/sly-crm-ui/src/main/resources/web/editor/project-editor.zul index 9fa18b9..b795876 100644 --- a/sly-crm-ui/src/main/resources/web/editor/project-editor.zul +++ b/sly-crm-ui/src/main/resources/web/editor/project-editor.zul @@ -85,24 +85,44 @@ + + + + + + + + + + + + + + + + - + + -