From: Vásáry Dániel Date: Thu, 7 Mar 2024 15:26:14 +0000 (+0100) Subject: Project margin updater completed using GeneralSettings X-Git-Url: http://git.useribm.hu/?a=commitdiff_plain;p=sly-crm.git Project margin updater completed using GeneralSettings --- diff --git a/sly-crm-db/migrations/scripts/032_insert_general_settings.sql b/sly-crm-db/migrations/scripts/032_insert_general_settings.sql new file mode 100644 index 0000000..62ee4e2 --- /dev/null +++ b/sly-crm-db/migrations/scripts/032_insert_general_settings.sql @@ -0,0 +1,9 @@ +-- // add price exchange fields to treasury +-- Migration SQL that makes the change goes here. + +INSERT INTO profile (type, setting) VALUES ('General', '{"autoProjectMarginUpdate": true}'); + +-- //@UNDO +-- SQL to undo the change goes here. + +DELETE FROM profile WHERE type="General"; diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/auth/CurrentProfile.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/auth/CurrentProfile.java index bef741a..4eb0f83 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/auth/CurrentProfile.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/auth/CurrentProfile.java @@ -3,7 +3,10 @@ package hu.user.lis.ui.auth; import hu.user.lis.db.Associate; import hu.user.lis.db.Profile; import hu.user.lis.db.repository.ProfileRepository; +import hu.user.lis.service.data.EntityDataService; +import hu.user.lis.ui.data.common.ObjectDictionary; import hu.user.lis.ui.session.SessionSettings; +import lombok.Getter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -17,25 +20,40 @@ public class CurrentProfile { public static final String ASSOCIATE = "ASSOCIATE"; public static final String SETTINGS = "SETTINGS"; + @Autowired private ProfileRepository profileRepository; @Autowired private SessionSettings sessionSettings; + @Getter + private ObjectDictionary generalSettings; + + @Autowired + private EntityDataService entityDataService; public Associate getAssociate() { return (Associate) sessionSettings.getAttribute(ASSOCIATE); } -// @Getter -// Map settings = new HashMap<>(); public void setAssociate(Associate associate) { sessionSettings.setAttribute(ASSOCIATE, associate); + profileRepository.findByLoginAndType(null, "General").ifPresent(profile -> { + generalSettings = entityDataService.fromJSON(profile.getSetting(), ObjectDictionary.class); + }); loadSettings(); } + public void saveGeneralSettings() { + profileRepository.findByLoginAndType(null, "General").ifPresent(profile -> { + String setting = entityDataService.toJSON(generalSettings); + profile.setSetting(setting); + profileRepository.save(profile); + }); + } + private void loadSettings() { if (Objects.isNull(getAssociate())) { return; 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 e58ed2d..3017fe2 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 @@ -7,7 +7,10 @@ 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 hu.user.lis.ui.editor.ExchangedRateValueUpdater; +import hu.user.lis.ui.properties.GeneralSettings; 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; @@ -17,44 +20,75 @@ 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 { + @Autowired + private GeneralSettings generalSettings; + + @Autowired + private ExchangedRateValueUpdater exchangedRateValueUpdater; + public void recalculate(Project project, ServiceRecordsDataModel serviceRecordsDataModel) throws Exception { + boolean autoUpdateProjectMargin = generalSettings.getAutoProjectMarginUpdate(); + + MoneyBalance projectHUFBalance = MoneyBalance.builder().build(); clear(); + Map balances = new HashMap<>(); List outgoingInvoices = project.getOutgoingInvoices(); - if (Objects.nonNull(outgoingInvoices)) { - for (Invoice invoice : outgoingInvoices) { - addBalance(balances, MoneyAmount.fromInvoice(invoice)); + for (Invoice invoice : outgoingInvoices) { + addBalance(balances, MoneyAmount.fromInvoice(invoice)); + if (autoUpdateProjectMargin) { + double income = exchangedRateValueUpdater.updateInvoiceExchangedValues(invoice); + projectHUFBalance.addIncome(income); } } List incomingInvoices = project.getIncomingInvoices(); - if (Objects.nonNull(incomingInvoices)) { - for (Invoice invoice : incomingInvoices) { - subtractBalance(balances, MoneyAmount.fromInvoice(invoice)); + for (Invoice invoice : incomingInvoices) { + subtractBalance(balances, MoneyAmount.fromInvoice(invoice)); + if (autoUpdateProjectMargin) { + double expense = exchangedRateValueUpdater.updateInvoiceExchangedValues(invoice); + projectHUFBalance.addExpense(expense); } } List treasuries = project.getTreasuries(); - if (Objects.nonNull(treasuries)) { - for (Treasury treasury : treasuries) { - subtractBalance(balances, MoneyAmount.fromTreasuryBuy(treasury)); - addBalance(balances, MoneyAmount.fromTreasurySell(treasury)); + for (Treasury treasury : treasuries) { + subtractBalance(balances, MoneyAmount.fromTreasuryBuy(treasury)); + addBalance(balances, MoneyAmount.fromTreasurySell(treasury)); + if (autoUpdateProjectMargin) { + double margin = exchangedRateValueUpdater.updateTreasuryExchangedValues(treasury); + if (margin < 0) { + projectHUFBalance.addExpense(-1 * margin); + } else { + projectHUFBalance.addIncome(margin); + } } } for (int i = 0; i < serviceRecordsDataModel.getSize(); i++) { ServiceRecord serviceRecord = serviceRecordsDataModel.getElementAt(i); - subtractBalance(balances, MoneyAmount.fromServiceRecord(serviceRecord)); + MoneyAmount moneyAmount = MoneyAmount.fromServiceRecord(serviceRecord); + subtractBalance(balances, moneyAmount); + if (autoUpdateProjectMargin) { + projectHUFBalance.addExpense(moneyAmount.getGrossAmountHUF()); + } } balances.keySet().stream().sorted().forEach(currency -> this.add(balances.get(currency))); BindUtils.postNotifyChange(this, "*"); + + if (autoUpdateProjectMargin) { + project.setSellingPrice(projectHUFBalance.getIncome()); + project.setSupplyPrice(projectHUFBalance.getExpense()); + project.setMargin(projectHUFBalance.getIncome() - projectHUFBalance.getExpense()); + BindUtils.postNotifyChange(project, "sellingPrice", "supplyPrice", "margin"); + } + } diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/MoneyBalance.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/MoneyBalance.java index 0d362d7..87f0bf5 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/MoneyBalance.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/MoneyBalance.java @@ -8,8 +8,19 @@ import lombok.Setter; @Setter @Builder public class MoneyBalance { + @Builder.Default - Double income = (double) 0; + private Double income = (double) 0; + @Builder.Default - Double expense = (double) 0; + private Double expense = (double) 0; + + + public void addIncome(double income) { + this.income += income; + } + + public void addExpense(double expanse) { + this.expense += expanse; + } } diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/data/common/ObjectDictionary.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/common/ObjectDictionary.java new file mode 100644 index 0000000..4d7a3ab --- /dev/null +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/data/common/ObjectDictionary.java @@ -0,0 +1,6 @@ +package hu.user.lis.ui.data.common; + +import java.util.HashMap; + +public class ObjectDictionary extends HashMap { +} diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ExchangedRateValueUpdater.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ExchangedRateValueUpdater.java index fc05278..4b8a121 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ExchangedRateValueUpdater.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ExchangedRateValueUpdater.java @@ -1,9 +1,15 @@ package hu.user.lis.ui.editor; -import hu.user.lis.db.*; +import hu.user.lis.db.Currency; +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.Treasury; import hu.user.lis.service.mnb.ExchangeRateService; import hu.user.lis.ui.data.MoneyBalance; import lombok.extern.log4j.Log4j2; +import org.apache.http.annotation.Obsolete; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -18,6 +24,7 @@ public class ExchangedRateValueUpdater { @Autowired private ExchangeRateService exchangeRateService; + @Obsolete public MoneyBalance update(Project project) { MoneyBalance result = MoneyBalance.builder().build(); for (IncomingInvoice incomingInvoice : project.getIncomingInvoices()) { @@ -37,7 +44,9 @@ public class ExchangedRateValueUpdater { return result; } - private void updateTreasuryExchangedValues(Treasury treasury) { + public double updateTreasuryExchangedValues(Treasury treasury) { + double result = 0; + Date initialDate = treasury.getTransactionDate(); Currency currency = treasury.getBuyCurrency(); if (!Currency.HUF.equals(currency) && Objects.isNull(treasury.getBuyExchangeRate())) { @@ -59,9 +68,11 @@ public class ExchangedRateValueUpdater { treasury.setSellAmountHUF(treasury.getBuyAmount() * exchangeRate); } } + + return treasury.getSellAmountHUF() - treasury.getBuyAmountHUF(); } - private double updateInvoiceExchangedValues(Invoice invoice) { + public double updateInvoiceExchangedValues(Invoice invoice) { if (!Currency.HUF.equals(invoice.getCurrency()) && Objects.isNull(invoice.getExchangeRate())) { Date initialDate = invoice.getPaymentDeadline(); LocalDate exchangeDate = Objects.isNull(initialDate) ? LocalDate.now() : diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java index e9f9722..fcf816c 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/InvoiceEditorModel.java @@ -10,7 +10,11 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; import org.zkoss.bind.BindUtils; -import org.zkoss.bind.annotation.*; +import org.zkoss.bind.annotation.AfterCompose; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.ContextParam; +import org.zkoss.bind.annotation.ContextType; +import org.zkoss.bind.annotation.Init; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.select.annotation.WireVariable; @@ -70,7 +74,7 @@ public class InvoiceEditorModel extends EntityAttachmentEditorModel { @Override public void onEvent(Event evt) { - if (isEventForCurrentDocument(evt)) { + if (isPropertyChangedEventForCurrentDocument(evt)) { // PropertyChangeEvent propertyEvent = (PropertyChangeEvent) evt; // String[] dates = {"completionDate", "createDate", "paymentDeadline"}; // if (Arrays.asList(dates).contains(propertyEvent.getProperty())) { 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 8248b90..9807d56 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 @@ -16,7 +16,6 @@ import hu.user.lis.ui.converter.ProjectStatusConverter; 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.MoneyBalance; import hu.user.lis.ui.data.ProjectAssociatesDataModel; import hu.user.lis.ui.data.ProjectStatusDataModel; import hu.user.lis.ui.data.ProjectsDataModel; @@ -46,6 +45,7 @@ import org.zkoss.zk.ui.util.Notification; import org.zkoss.zul.Panel; import org.zkoss.zul.Window; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -134,6 +134,12 @@ public class ProjectEditorModel extends EntityEditorModel { projectStatusDataModel.listActive(); } + @Override + protected boolean canPropertyCauseValidation(String property) { + List prohibitedNames = Arrays.asList("sellingPrice", "supplyPrice", "margin"); + return !prohibitedNames.contains(property); + } + @Override public void onEvent(Event evt) { super.onEvent(evt); @@ -141,7 +147,6 @@ public class ProjectEditorModel extends EntityEditorModel { Object data = evt.getData(); initDocuments(data); initDetails(); - //validate(); } } @@ -149,7 +154,7 @@ public class ProjectEditorModel extends EntityEditorModel { initAssociates(); serviceRecordsDataModel.search(getFormDocument(), true); getEntitySelectorRouter().configureSelector(Partner.class, getFormDocument(), "partner"); - safeRecalcMargin(); + safeRecalculateMargin(); } @@ -437,7 +442,10 @@ public class ProjectEditorModel extends EntityEditorModel { @Override protected boolean areDifferent(Project entity) { - return super.areDifferent(entity) || isAssociatesChanged() || !invoiceDocumentActions.isEmpty() || !treasuryDocumentActions.isEmpty(); + return super.areDifferent(entity) || + isAssociatesChanged() || + !invoiceDocumentActions.isEmpty() || + !treasuryDocumentActions.isEmpty(); } @Command @@ -449,23 +457,10 @@ public class ProjectEditorModel extends EntityEditorModel { @Override public void validate() { super.validate(); - //updateExchangeRateBasedValues(); - safeRecalcMargin(); - } - - private void updateExchangeRateBasedValues() { - try { - MoneyBalance balance = exchangedRateValueUpdater.update(getFormDocument()); - getFormDocument().setSellingPrice(balance.getIncome()); - getFormDocument().setSupplyPrice(balance.getExpense()); - getFormDocument().setMargin(balance.getIncome() - balance.getExpense()); - BindUtils.postNotifyChange(getFormDocument(), "sellingPrice", "supplyPrice", "margin"); - } catch (Exception e) { - log.error(e.getMessage()); - } + safeRecalculateMargin(); } - private void safeRecalcMargin() { + private void safeRecalculateMargin() { try { incomeMarginsDataModel.recalculate(getFormDocument(), serviceRecordsDataModel); } catch (Exception e) { diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java index 2575d4f..ddb4016 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/editor/ServiceRecordEditorModel.java @@ -17,7 +17,12 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.log4j.Log4j2; import org.zkoss.bind.PropertyChangeEvent; -import org.zkoss.bind.annotation.*; +import org.zkoss.bind.annotation.AfterCompose; +import org.zkoss.bind.annotation.BindingParam; +import org.zkoss.bind.annotation.Command; +import org.zkoss.bind.annotation.ContextParam; +import org.zkoss.bind.annotation.ContextType; +import org.zkoss.bind.annotation.Init; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Events; @@ -27,7 +32,11 @@ import org.zkoss.zul.Window; import java.time.LocalDate; import java.time.ZoneId; -import java.util.*; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; @Log4j2 @@ -119,7 +128,7 @@ public class ServiceRecordEditorModel extends EntityAttachmentEditorModel extends Abstract @Override public void onEvent(Event evt) { - if (isEventForCurrentDocument(evt)) { + if (isPropertyChangedEventForCurrentDocument(evt)) { validate(); } } - protected boolean isEventForCurrentDocument(Event evt) { + protected boolean canPropertyCauseValidation(String property) { + return true; + } + + protected boolean isPropertyChangedEventForCurrentDocument(Event evt) { if (evt instanceof PropertyChangeEvent) { PropertyChangeEvent propertyEvent = (PropertyChangeEvent) evt; - return (Objects.nonNull(propertyEvent.getBase()) && Objects.nonNull(formDocument) && propertyEvent.getBase().equals(formDocument)); + return canPropertyCauseValidation(propertyEvent.getProperty()) && + (Objects.nonNull(propertyEvent.getBase()) && Objects.nonNull(formDocument) && propertyEvent.getBase().equals(formDocument)); } return false; } diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/properties/GeneralSettings.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/properties/GeneralSettings.java new file mode 100644 index 0000000..225f39a --- /dev/null +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/properties/GeneralSettings.java @@ -0,0 +1,16 @@ +package hu.user.lis.ui.properties; + +import hu.user.lis.ui.auth.CurrentProfile; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class GeneralSettings { + @Autowired + private CurrentProfile currentProfile; + + public boolean getAutoProjectMarginUpdate() { + return (boolean) currentProfile.getGeneralSettings().get("autoProjectMarginUpdate"); + } + +} diff --git a/sly-crm-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java b/sly-crm-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java index 882fe3d..264cdb2 100644 --- a/sly-crm-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java +++ b/sly-crm-ui/src/main/java/hu/user/lis/ui/view/SettingsViewModel.java @@ -1,6 +1,7 @@ package hu.user.lis.ui.view; import hu.user.lis.db.ProjectStatus; +import hu.user.lis.ui.auth.CurrentProfile; import hu.user.lis.ui.data.ProjectStatusDataModel; import hu.user.lis.ui.view.common.AsyncBaseModel; import lombok.Getter; @@ -19,13 +20,18 @@ import org.zkoss.zul.Panel; @Log4j2 @VariableResolver(DelegatingVariableResolver.class) public class SettingsViewModel extends AsyncBaseModel { - @WireVariable + @Getter + @WireVariable ProjectStatusDataModel projectStatusDataModel; @Getter private ProjectStatus selectedProjectStatus; + @Getter + @WireVariable + private CurrentProfile currentProfile; + @Init public void init() { Clients.evalJavaScript("pushNav('/settings')"); @@ -74,11 +80,16 @@ public class SettingsViewModel extends AsyncBaseModel { projectStatusDataModel.save(entity); projectStatusDataModel.listAll(); } catch (Exception e) { - Messagebox.show("A mentés sikertelen! A elvárt az egyedi státusz elnevezés.", "Hiba", Messagebox.OK , Messagebox.ERROR); + Messagebox.show("A mentés sikertelen! A elvárt az egyedi státusz elnevezés.", "Hiba", Messagebox.OK, Messagebox.ERROR); } } - public void setSelectedProjectStatus(ProjectStatus selectedProjectStatus) { - this.selectedProjectStatus = selectedProjectStatus; + @Command + public void onGeneralSettingsChanged() { + try { + currentProfile.saveGeneralSettings(); + } catch (Exception e) { + Messagebox.show("A mentés sikertelen!", "Hiba", Messagebox.OK, Messagebox.ERROR); + } } } 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 8e0b61d..eebc953 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 @@ -87,12 +87,12 @@
- Bevétel: + Kiadás:
- Kiadás: + Bevétel:
diff --git a/sly-crm-ui/src/main/resources/web/settings.zul b/sly-crm-ui/src/main/resources/web/settings.zul index f0fe429..2145396 100644 --- a/sly-crm-ui/src/main/resources/web/settings.zul +++ b/sly-crm-ui/src/main/resources/web/settings.zul @@ -6,7 +6,20 @@
- + + + + + + + + +