Java tutorial
/* * Copyright 2003 - 2017 The eFaps Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.efaps.esjp.accounting.transaction; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import org.apache.commons.text.StringEscapeUtils; import org.efaps.admin.datamodel.Classification; import org.efaps.admin.datamodel.Status; import org.efaps.admin.datamodel.Type; import org.efaps.admin.datamodel.ui.IUIValue; import org.efaps.admin.dbproperty.DBProperties; import org.efaps.admin.event.Parameter; import org.efaps.admin.event.Parameter.ParameterValues; import org.efaps.admin.event.Return; import org.efaps.admin.event.Return.ReturnValues; import org.efaps.admin.program.esjp.EFapsApplication; import org.efaps.admin.program.esjp.EFapsUUID; import org.efaps.api.ui.IUserInterface; import org.efaps.db.AttributeQuery; import org.efaps.db.Context; import org.efaps.db.Insert; import org.efaps.db.Instance; import org.efaps.db.InstanceQuery; import org.efaps.db.MultiPrintQuery; import org.efaps.db.PrintQuery; import org.efaps.db.QueryBuilder; import org.efaps.db.SelectBuilder; import org.efaps.esjp.accounting.util.Accounting; import org.efaps.esjp.accounting.util.AccountingSettings; import org.efaps.esjp.ci.CIAccounting; import org.efaps.esjp.ci.CIERP; import org.efaps.esjp.ci.CIFormAccounting; import org.efaps.esjp.ci.CISales; import org.efaps.esjp.erp.Currency; import org.efaps.esjp.erp.CurrencyInst; import org.efaps.esjp.erp.RateFormatter; import org.efaps.esjp.erp.RateInfo; import org.efaps.esjp.sales.PriceUtil; import org.efaps.esjp.sales.document.AbstractDocumentSum; import org.efaps.ui.wicket.util.EFapsKey; import org.efaps.util.EFapsException; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; /** * TODO comment! * * @author The eFaps Team */ @EFapsUUID("3748924a-3e33-45d5-805e-9c749d9fb1d6") @EFapsApplication("eFapsApp-Accounting") public abstract class Recalculate_Base extends Transaction { /** * Method to obtain html with information of the document selected. * * @param _parameter Parameter as passed from the eFaps API. * @return ret Return Sniplett. * @throws EFapsException on error. */ public Return transactionOnRecalculateFieldValue(final Parameter _parameter) throws EFapsException { final Return ret = new Return(); final Instance docInst = Instance.get(_parameter.getParameterValue("selectedRow")); if (docInst.getType().isKindOf(CISales.DocumentSumAbstract.getType())) { final IUIValue fieldValue = (IUIValue) _parameter.get(ParameterValues.UIOBJECT); final StringBuilder html = new StringBuilder(); html.append("<span name=\"").append(fieldValue.getField().getName()).append("\" ") .append(IUserInterface.EFAPSTMPTAG).append(">").append(getRecalculateInfo(_parameter, docInst)) .append("</span>"); ret.put(ReturnValues.SNIPLETT, html.toString()); } return ret; } /** * Method for recalculate and return string. * * @param _parameter Parameter as passed from the eFaps API. * @param _docInst Instance of the document selected. * @return String. * @throws EFapsException on error. */ protected String getRecalculateInfo(final Parameter _parameter, final Instance _docInst) throws EFapsException { final StringBuilder html = new StringBuilder(); final PrintQuery print = new PrintQuery(_docInst); print.addAttribute(CISales.DocumentSumAbstract.RateCrossTotal, CISales.DocumentSumAbstract.CrossTotal, CISales.DocumentSumAbstract.RateCurrencyId, CISales.DocumentSumAbstract.CurrencyId, CISales.DocumentSumAbstract.Date, CISales.DocumentSumAbstract.Name); print.execute(); final BigDecimal rateCross = print.<BigDecimal>getAttribute(CISales.DocumentSumAbstract.RateCrossTotal); final BigDecimal crossTotal = print.<BigDecimal>getAttribute(CISales.DocumentSumAbstract.CrossTotal); final String nameDoc = print.<String>getAttribute(CISales.DocumentSumAbstract.Name); final Instance targetCurrInst = Instance.get(CIERP.Currency.getType(), print.<Long>getAttribute(CISales.DocumentSumAbstract.RateCurrencyId)); final Instance currentInst = Instance.get(CIERP.Currency.getType(), print.<Long>getAttribute(CISales.DocumentSumAbstract.CurrencyId)); final CurrencyInst tarCurr = new CurrencyInst(targetCurrInst); final CurrencyInst curr = new CurrencyInst(currentInst); final PriceUtil priceUtil = new PriceUtil(); final BigDecimal[] rates = priceUtil.getRates(_parameter, targetCurrInst, currentInst); final BigDecimal rate = rates[2]; final BigDecimal newCrossTotal = rateCross.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rateCross.divide(rate, BigDecimal.ROUND_HALF_UP); final BigDecimal gainloss = newCrossTotal.subtract(crossTotal); final Map<String, String[]> map = validateInfo(_parameter, gainloss); final String[] accs = map.get("accs"); final String[] check = map.get("check"); html.append("<table>").append("<tr>").append("<td>").append(DBProperties.getProperty("Sales_Invoice.Label")) .append("</td>").append("<td colspan=\"2\">").append(nameDoc).append("</td>").append("</tr>") .append("<td>").append(DBProperties.getProperty("Sales_DocumentAbstract/RateCrossTotal.Label")) .append("</td>").append("<td>").append(rateCross).append(" ").append(tarCurr.getSymbol()) .append("</td>").append("<td>").append(crossTotal).append(" ").append(curr.getSymbol()) .append("</td>").append("</tr>").append("<tr>").append("<td>") .append(DBProperties.getProperty("Accounting_TransactionRecalculateForm.newTotal.Label")) .append("</td>").append("<td colspan=\"2\" align=\"right\">").append(newCrossTotal).append(" ") .append(curr.getSymbol()).append("</td>").append("</tr>").append("<tr>").append("<td>"); if (gainloss.compareTo(BigDecimal.ZERO) == -1) { html.append(DBProperties.getProperty("Accounting_TransactionRecalculateForm.loss.Label")); } else { html.append(DBProperties.getProperty("Accounting_TransactionRecalculateForm.gain.Label")); } html.append("</td>").append("<td colspan=\"2\" align=\"right\">").append(gainloss.abs()).append(" ") .append(curr.getSymbol()).append("</td>").append("</tr>").append("<tr>").append("<td>") .append(DBProperties.getProperty("Accounting_TransactionPositionDebit.Label")).append("</td>") .append("<td colspan=\"2\" align=\"right\">"); if (checkAccounts(accs, 0, check).length() > 0) { html.append(checkAccounts(accs, 0, check)); } else { html.append(DBProperties.getProperty("Accounting_TransactionRecalculateForm.reviseConfig.Label")); } html.append("</td>").append("</tr>").append("<tr>").append("<td>") .append(DBProperties.getProperty("Accounting_TransactionPositionCredit.Label")).append("</td>") .append("<td colspan=\"2\" align=\"right\">"); if (checkAccounts(accs, 1, check).length() > 0) { html.append(checkAccounts(accs, 1, check)); } else { html.append(DBProperties.getProperty("Accounting_TransactionRecalculateForm.reviseConfig.Label")); } html.append("</td>").append("</tr>").append("</table>"); return html.toString(); } /** * Method for update rate and transactions if changed date to return html and rate amount. * * @param _parameter Parameter as passed from the eFaps API. * @return ret with values. * @throws EFapsException on error. */ public Return update4DateOnRecalculate(final Parameter _parameter) throws EFapsException { final Return retVal = new Return(); final Instance docInst = Instance.get(_parameter.getParameterValue("docInst")); if (docInst.getType().isKindOf(CISales.DocumentSumAbstract.getType())) { final PrintQuery print = new PrintQuery(docInst); print.addAttribute(CISales.DocumentSumAbstract.Rate); print.execute(); final Object[] rateObj = print.getAttribute(CISales.DocumentSumAbstract.Rate); final Currency currency = getCurrency(_parameter); final RateInfo rateInfo = currency.evaluateRateInfo(_parameter, rateObj); final RateFormatter frmt = getRateFormatter(_parameter); final String rateStr = frmt.getFrmt4Rate().format(rateInfo.getRate()); final List<Map<String, String>> list = new ArrayList<>(); final Map<String, String> map = new HashMap<>(); map.put("rate", rateStr); final StringBuilder js = new StringBuilder(); js.append("document.getElementsByName('transactions')[0].innerHTML='") .append(StringEscapeUtils.escapeEcmaScript(getRecalculateInfo(_parameter, docInst))) .append("';"); map.put(EFapsKey.FIELDUPDATE_JAVASCRIPT.getKey(), js.toString()); list.add(map); retVal.put(ReturnValues.VALUES, list); } return retVal; } /** * Method to recalculate rate. * * @param _parameter Parameter as passed from the eFaps API. * @return new Return. * @throws EFapsException on error. */ public Return recalculateRate(final Parameter _parameter) throws EFapsException { final Instance docInst = Instance.get(_parameter.getParameterValue("docInst")); final PrintQuery print = new PrintQuery(docInst); print.addAttribute(CISales.DocumentSumAbstract.RateCrossTotal, CISales.DocumentSumAbstract.CrossTotal, CISales.DocumentSumAbstract.RateCurrencyId, CISales.DocumentSumAbstract.CurrencyId, CISales.DocumentSumAbstract.Date, CISales.DocumentSumAbstract.Name); print.execute(); final BigDecimal rateCross = print.<BigDecimal>getAttribute(CISales.DocumentSumAbstract.RateCrossTotal); final BigDecimal crossTotal = print.<BigDecimal>getAttribute(CISales.DocumentSumAbstract.CrossTotal); final DateTime dateDoc = print.<DateTime>getAttribute(CISales.DocumentSumAbstract.Date); final String nameDoc = print.<String>getAttribute(CISales.DocumentSumAbstract.Name); final Instance targetCurrInst = Instance.get(CIERP.Currency.getType(), print.<Long>getAttribute(CISales.DocumentSumAbstract.RateCurrencyId)); final Instance currentInst = Instance.get(CIERP.Currency.getType(), print.<Long>getAttribute(CISales.DocumentSumAbstract.CurrencyId)); final CurrencyInst tarCurr = new CurrencyInst(targetCurrInst); final CurrencyInst curr = new CurrencyInst(currentInst); final PriceUtil priceUtil = new PriceUtil(); final BigDecimal[] rates = priceUtil.getRates(_parameter, targetCurrInst, currentInst); final BigDecimal rate = rates[2]; final BigDecimal newCrossTotal = rateCross.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : rateCross.divide(rate, BigDecimal.ROUND_HALF_UP); final BigDecimal gainloss = newCrossTotal.subtract(crossTotal); final Map<String, String[]> map = validateInfo(_parameter, gainloss); final String[] accs = map.get("accs"); final String[] check = map.get("check"); if (checkAccounts(accs, 0, check).length() > 0 && checkAccounts(accs, 1, check).length() > 0) { if (gainloss.compareTo(BigDecimal.ZERO) != 0) { if (!tarCurr.equals(curr)) { final String[] accOids = map.get("accountOids"); final Insert insert = new Insert(CIAccounting.Transaction); final StringBuilder description = new StringBuilder(); final DateTimeFormatter formater = DateTimeFormat.mediumDate(); final String dateStr = dateDoc.withChronology(Context.getThreadContext().getChronology()) .toString(formater.withLocale(Context.getThreadContext().getLocale())); description .append(DBProperties .getProperty("Accounting_TransactionRecalculateForm.TxnRecalculate.Label")) .append(" ").append(nameDoc).append(" ").append(dateStr); insert.add(CIAccounting.Transaction.Description, description); insert.add(CIAccounting.Transaction.Date, _parameter.getParameterValue("date")); insert.add(CIAccounting.Transaction.PeriodLink, _parameter.getInstance().getId()); insert.add(CIAccounting.Transaction.Status, Status.find(CIAccounting.TransactionStatus.uuid, "Open").getId()); insert.execute(); final Instance instance = insert.getInstance(); new Create().connectDocs2Transaction(_parameter, instance, docInst); final Insert insert2 = new Insert(CIAccounting.TransactionPositionCredit); insert2.add(CIAccounting.TransactionPositionCredit.TransactionLink, instance.getId()); insert2.add(CIAccounting.TransactionPositionCredit.AccountLink, Instance.get(accOids[1]).getId()); insert2.add(CIAccounting.TransactionPositionCredit.CurrencyLink, curr.getInstance().getId()); insert2.add(CIAccounting.TransactionPositionCredit.RateCurrencyLink, curr.getInstance().getId()); insert2.add(CIAccounting.TransactionPositionCredit.Rate, new Object[] { 1, 1 }); insert2.add(CIAccounting.TransactionPositionCredit.RateAmount, gainloss.abs()); insert2.add(CIAccounting.TransactionPositionCredit.Amount, gainloss.abs()); insert2.execute(); final Insert insert3 = new Insert(CIAccounting.TransactionPositionDebit); insert3.add(CIAccounting.TransactionPositionDebit.TransactionLink, instance.getId()); insert3.add(CIAccounting.TransactionPositionDebit.AccountLink, Instance.get(accOids[0]).getId()); insert3.add(CIAccounting.TransactionPositionDebit.CurrencyLink, curr.getInstance().getId()); insert3.add(CIAccounting.TransactionPositionDebit.RateCurrencyLink, curr.getInstance().getId()); insert3.add(CIAccounting.TransactionPositionDebit.Rate, new Object[] { 1, 1 }); insert3.add(CIAccounting.TransactionPositionDebit.RateAmount, gainloss.abs().negate()); insert3.add(CIAccounting.TransactionPositionDebit.Amount, gainloss.abs().negate()); insert3.execute(); _parameter.put(ParameterValues.INSTANCE, docInst); new Accounting4DocSum().recalculateRate(_parameter); } } } return new Return(); } /** * Method for check if account name exits for proceed to create. * * @param _accountValues String array with values. * @param _pos position if type credit or debit. * @param _checkValues values true or false. * @return str String. */ protected String checkAccounts(final String[] _accountValues, final int _pos, final String[] _checkValues) { final StringBuilder str = new StringBuilder(); if (_checkValues[_pos] != null && "true".equals(_checkValues[_pos])) { str.append(_accountValues[_pos]); } return str.toString(); } /** * Method for obtain map with values to validate accounts. * * @param _parameter Parameter as passed from the eFaps API. * @param _gainloss BigDecimal of the gain or loss in the document. * @return map. * @throws EFapsException on error. */ private Map<String, String[]> validateInfo(final Parameter _parameter, final BigDecimal _gainloss) throws EFapsException { final Properties gainLoss = Accounting.getSysConfig() .getObjectAttributeValueAsProperties(_parameter.getInstance()); final String accStr; if (_gainloss.signum() > 0) { accStr = gainLoss.getProperty(AccountingSettings.PERIOD_EXCHANGELOSS); } else { accStr = gainLoss.getProperty(AccountingSettings.PERIOD_EXCHANGEGAIN); } String[] accs = new String[2]; final String[] check = new String[2]; final String[] accOids = new String[2]; if (accStr != null) { accs = accStr.split(";"); if (accs.length > 0) { for (int i = 0; i < accs.length; i++) { final QueryBuilder queryBldr = new QueryBuilder(CIAccounting.AccountAbstract); queryBldr.addWhereAttrEqValue(CIAccounting.AccountAbstract.PeriodAbstractLink, _parameter.getInstance().getId()); queryBldr.addWhereAttrEqValue(CIAccounting.AccountAbstract.Name, accs[i].toString()); final MultiPrintQuery multi = queryBldr.getPrint(); multi.addAttribute(CIAccounting.AccountAbstract.OID); multi.execute(); while (multi.next()) { check[i] = "true"; accOids[i] = multi.<String>getAttribute(CIAccounting.AccountAbstract.OID); } } } } final Map<String, String[]> map = new HashMap<>(); map.put("check", check); map.put("accs", accs); map.put("accountOids", accOids); return map; } /** * Validate that on ly simple accounts are selected. * @param _parameter Parameter as passed by the eFasp API * @return new Return * @throws EFapsException on error */ public Return validate4SimpleAccount(final Parameter _parameter) throws EFapsException { final Return ret = new Return(); boolean check = true; final String[] relOIDs = (String[]) Context.getThreadContext() .getSessionAttribute(CIFormAccounting.Accounting_GainLoss4SimpleAccountForm.config2period.name); for (final String oid : relOIDs) { final Instance relInst = Instance.get(oid); if (!(relInst.isValid() && relInst.getType().isKindOf(CIAccounting.AccountConfigSimple2Period.getType()))) { check = false; break; } } if (check) { ret.put(ReturnValues.TRUE, true); } else { ret.put(ReturnValues.SNIPLETT, DBProperties.getProperty(Recalculate.class.getName() + ".validate4SimpleAccount")); } return ret; } /** * @param _parameter Parameter as passed by the eFasp API * @return new Return * @throws EFapsException on error */ public Return createGainLoss4SimpleAccount(final Parameter _parameter) throws EFapsException { final PrintQuery printPer = new PrintQuery(_parameter.getInstance()); final SelectBuilder selCurrInst = SelectBuilder.get().linkto(CIAccounting.Period.CurrencyLink).instance(); printPer.addSelect(selCurrInst); printPer.addAttribute(CIAccounting.Period.FromDate, CIAccounting.Period.CurrencyLink); printPer.execute(); final DateTime dateFrom = printPer.<DateTime>getAttribute(CIAccounting.Period.FromDate); final Instance currencyInst = printPer.<Instance>getSelect(selCurrInst); final String[] relOIDs = (String[]) Context.getThreadContext() .getSessionAttribute(CIFormAccounting.Accounting_GainLoss4SimpleAccountForm.config2period.name); final DateTime dateTo = new DateTime(_parameter .getParameterValue(CIFormAccounting.Accounting_GainLoss4SimpleAccountForm.transactionDate.name)); final DateTime dateEx = new DateTime(_parameter .getParameterValue(CIFormAccounting.Accounting_GainLoss4SimpleAccountForm.exchangeDate.name)); Insert insert = null; BigDecimal totalSum = BigDecimal.ZERO; for (final String oid : relOIDs) { Instance tarCurInst = null; final Instance relInst = Instance.get(oid); final PrintQuery print = new PrintQuery(relInst); final SelectBuilder selAccount = new SelectBuilder() .linkto(CIAccounting.AccountConfigSimple2Period.FromLink).oid(); print.addSelect(selAccount); print.addAttribute(CIAccounting.AccountConfigSimple2Period.IsSale); if (print.execute()) { final Instance instAcc = Instance.get(print.<String>getSelect(selAccount)); final boolean isSale = print.<Boolean>getAttribute(CIAccounting.AccountConfigSimple2Period.IsSale); final QueryBuilder attrQuerBldr = new QueryBuilder(CIAccounting.Transaction); attrQuerBldr.addWhereAttrEqValue(CIAccounting.Transaction.PeriodLink, _parameter.getInstance()); attrQuerBldr.addWhereAttrGreaterValue(CIAccounting.Transaction.Date, dateFrom.minusMinutes(1)); attrQuerBldr.addWhereAttrLessValue(CIAccounting.Transaction.Date, dateTo.plusDays(1)); final AttributeQuery attrQuery = attrQuerBldr.getAttributeQuery(CIAccounting.Transaction.ID); final QueryBuilder queryBldr = new QueryBuilder(CIAccounting.TransactionPositionAbstract); queryBldr.addWhereAttrEqValue(CIAccounting.TransactionPositionAbstract.AccountLink, instAcc); queryBldr.addWhereAttrInQuery(CIAccounting.TransactionPositionAbstract.TransactionLink, attrQuery); final MultiPrintQuery multi = queryBldr.getPrint(); final SelectBuilder selTRInst = SelectBuilder.get() .linkto(CIAccounting.TransactionPositionAbstract.RateCurrencyLink).instance(); multi.addSelect(selTRInst); multi.addAttribute(CIAccounting.TransactionPositionAbstract.Amount, CIAccounting.TransactionPositionAbstract.RateAmount); BigDecimal gainlossSum = BigDecimal.ZERO; multi.execute(); while (multi.next()) { final BigDecimal oldRateAmount = multi .<BigDecimal>getAttribute(CIAccounting.TransactionPositionAbstract.RateAmount); final BigDecimal oldAmount = multi .<BigDecimal>getAttribute(CIAccounting.TransactionPositionAbstract.Amount); final Instance targetCurrInst = multi.<Instance>getSelect(selTRInst); final BigDecimal rate = evaluateRate(_parameter, dateEx, currencyInst, targetCurrInst, isSale); final BigDecimal newAmount = oldRateAmount.divide(rate, BigDecimal.ROUND_HALF_UP); BigDecimal gainloss = BigDecimal.ZERO; if (!currencyInst.equals(targetCurrInst)) { gainloss = newAmount.subtract(oldAmount); tarCurInst = targetCurrInst; } else { gainloss = newAmount; } gainlossSum = gainlossSum.add(gainloss); } totalSum = totalSum.add(gainlossSum); final Map<String, String[]> map = validateInfo(_parameter, gainlossSum); final String[] accs = map.get("accs"); final String[] check = map.get("check"); if (checkAccounts(accs, 0, check).length() > 0) { if (gainlossSum.compareTo(BigDecimal.ZERO) != 0) { final String[] accOids = map.get("accountOids"); if (insert == null) { final String descr = DBProperties.getFormatedDBProperty( Recalculate.class.getName() + ".gainLoss4SimpleAccountTransDesc", dateTo.toDate()); insert = new Insert(CIAccounting.Transaction); insert.add(CIAccounting.Transaction.Description, descr); insert.add(CIAccounting.Transaction.Date, dateTo); insert.add(CIAccounting.Transaction.PeriodLink, _parameter.getInstance()); insert.add(CIAccounting.Transaction.Status, Status.find(CIAccounting.TransactionStatus.Open)); insert.execute(); } Insert insertPos = new Insert(CIAccounting.TransactionPositionDebit); insertPos.add(CIAccounting.TransactionPositionDebit.TransactionLink, insert.getInstance()); if (gainlossSum.signum() > 0) { insertPos.add(CIAccounting.TransactionPositionDebit.AccountLink, Instance.get(accOids[0])); } else { insertPos.add(CIAccounting.TransactionPositionDebit.AccountLink, instAcc); } insertPos.add(CIAccounting.TransactionPositionDebit.Amount, gainlossSum.abs().negate()); insertPos.add(CIAccounting.TransactionPositionDebit.RateAmount, BigDecimal.ZERO); insertPos.add(CIAccounting.TransactionPositionDebit.CurrencyLink, currencyInst); insertPos.add(CIAccounting.TransactionPositionDebit.RateCurrencyLink, tarCurInst); insertPos.add(CIAccounting.TransactionPositionDebit.Rate, new Object[] { BigDecimal.ONE, BigDecimal.ONE }); insertPos.execute(); insertPos = new Insert(CIAccounting.TransactionPositionCredit); insertPos.add(CIAccounting.TransactionPositionCredit.TransactionLink, insert.getInstance()); if (gainlossSum.signum() > 0) { insertPos.add(CIAccounting.TransactionPositionCredit.AccountLink, instAcc); } else { insertPos.add(CIAccounting.TransactionPositionCredit.AccountLink, Instance.get(accOids[0])); } insertPos.add(CIAccounting.TransactionPositionCredit.Amount, gainlossSum.abs()); insertPos.add(CIAccounting.TransactionPositionCredit.RateAmount, BigDecimal.ZERO); insertPos.add(CIAccounting.TransactionPositionCredit.CurrencyLink, currencyInst); insertPos.add(CIAccounting.TransactionPositionCredit.RateCurrencyLink, tarCurInst); insertPos.add(CIAccounting.TransactionPositionCredit.Rate, new Object[] { BigDecimal.ONE, BigDecimal.ONE }); insertPos.execute(); } } } } if (insert != null) { final Instance instance = insert.getInstance(); // create classifications final Classification classification1 = (Classification) CIAccounting.TransactionClass.getType(); final Insert relInsert1 = new Insert(classification1.getClassifyRelationType()); relInsert1.add(classification1.getRelLinkAttributeName(), instance); relInsert1.add(classification1.getRelTypeAttributeName(), classification1.getId()); relInsert1.execute(); final Insert classInsert1 = new Insert(classification1); classInsert1.add(classification1.getLinkAttributeName(), instance); classInsert1.execute(); final Classification classification = (Classification) CIAccounting.TransactionClassGainLoss.getType(); final Insert relInsert = new Insert(classification.getClassifyRelationType()); relInsert.add(classification.getRelLinkAttributeName(), instance); relInsert.add(classification.getRelTypeAttributeName(), classification.getId()); relInsert.execute(); final Insert classInsert = new Insert(classification); classInsert.add(classification.getLinkAttributeName(), instance); classInsert.add(CIAccounting.TransactionClassGainLoss.Amount, totalSum); classInsert.add(CIAccounting.TransactionClassGainLoss.RateAmount, totalSum); classInsert.add(CIAccounting.TransactionClassGainLoss.CurrencyLink, currencyInst); classInsert.add(CIAccounting.TransactionClassGainLoss.RateCurrencyLink, currencyInst); classInsert.add(CIAccounting.TransactionClassGainLoss.Rate, new Object[] { BigDecimal.ONE, BigDecimal.ONE }); classInsert.execute(); } // clean up Context.getThreadContext() .removeSessionAttribute(CIFormAccounting.Accounting_GainLoss4SimpleAccountForm.config2period.name); return new Return(); } /** * @param _parameter Parameter as passed by the eFaps API * @param _date date the rate must be evaluated for * @param _currentCurrencyInst instance of the currency the rate is wanted for * @param _targetCurrencyInst instance of the currency the rate is wanted for * @param _sale sales exchange rate or not * @return rate * @throws EFapsException on error */ protected BigDecimal evaluateRate(final Parameter _parameter, final DateTime _date, final Instance _currentCurrencyInst, final Instance _targetCurrencyInst, final boolean _sale) throws EFapsException { final Currency currency = new Currency() { @Override protected Type getType4ExchangeRate(final Parameter _parameter) { return CIAccounting.ERP_CurrencyRateAccounting.getType(); } }; final RateInfo[] rateInfos = currency.evaluateRateInfos(_parameter, _date, _currentCurrencyInst, _targetCurrencyInst); return _sale ? rateInfos[2].getSaleRate() : rateInfos[2].getRate(); } /** * Creates the gain loss4 document account. * * @param _parameter Parameter as passed by the eFaps API * @return the return * @throws EFapsException on error */ public Return createGainLoss4DocumentAccount(final Parameter _parameter) throws EFapsException { final Set<String> setAccounts = getAccounts4DocumentConfig(_parameter); final String[] oidsDoc = (String[]) Context.getThreadContext().getSessionAttribute( CIFormAccounting.Accounting_GainLoss4DocumentAccountForm.selectedDocuments.name); final DateTime dateTo = new DateTime(_parameter .getParameterValue(CIFormAccounting.Accounting_GainLoss4DocumentAccountForm.transactionDate.name)); for (final String oid : oidsDoc) { final Instance instDoc = Instance.get(oid); final QueryBuilder attrQuerBldr = new QueryBuilder(CIAccounting.Transaction2SalesDocument); attrQuerBldr.addWhereAttrEqValue(CIAccounting.Transaction2SalesDocument.ToLink, instDoc); final AttributeQuery attrQuery = attrQuerBldr .getAttributeQuery(CIAccounting.Transaction2SalesDocument.FromLink); // filter classification Document final QueryBuilder attrQueryBldr2 = new QueryBuilder(CIAccounting.Transaction); attrQueryBldr2.addWhereAttrEqValue(CIAccounting.Transaction.PeriodLink, _parameter.getInstance().getId()); attrQueryBldr2.addWhereAttrInQuery(CIAccounting.Transaction.ID, attrQuery); final AttributeQuery attrQuery2 = attrQuerBldr.getAttributeQuery(CIAccounting.Transaction.ID); final QueryBuilder queryBldr = new QueryBuilder(CIAccounting.TransactionPositionAbstract); queryBldr.addWhereAttrInQuery(CIAccounting.TransactionPositionAbstract.TransactionLink, attrQuery2); final MultiPrintQuery multi = queryBldr.getPrint(); multi.addAttribute(CIAccounting.TransactionPositionAbstract.Amount, CIAccounting.TransactionPositionAbstract.RateAmount, CIAccounting.TransactionPositionAbstract.CurrencyLink, CIAccounting.TransactionPositionAbstract.RateCurrencyLink); final SelectBuilder selAcc = new SelectBuilder() .linkto(CIAccounting.TransactionPositionAbstract.AccountLink).oid(); multi.addSelect(selAcc); multi.execute(); final Map<String, AccountInfo> map = new HashMap<>(); while (multi.next()) { final Instance accountInst = Instance.get(multi.<String>getSelect(selAcc)); if (setAccounts.contains(accountInst.getOid())) { final BigDecimal oldRateAmount = multi .<BigDecimal>getAttribute(CIAccounting.TransactionPositionAbstract.RateAmount); final BigDecimal oldAmount = multi .<BigDecimal>getAttribute(CIAccounting.TransactionPositionAbstract.Amount); final Instance targetCurrInst = Instance.get(CIERP.Currency.getType(), multi.<Long>getAttribute(CIAccounting.TransactionPositionAbstract.RateCurrencyLink)); final Instance currentInst = Instance.get(CIERP.Currency.getType(), multi.<Long>getAttribute(CIAccounting.TransactionPositionAbstract.CurrencyLink)); final PriceUtil priceUtil = new PriceUtil(); final BigDecimal[] rates = priceUtil.getRates(_parameter, targetCurrInst, currentInst); final BigDecimal rate = rates[2]; final BigDecimal newAmount = oldRateAmount.divide(rate, BigDecimal.ROUND_HALF_UP); BigDecimal gainloss = BigDecimal.ZERO; if (!currentInst.equals(targetCurrInst)) { gainloss = newAmount.subtract(oldAmount); } else { gainloss = newAmount; } if (map.containsKey(accountInst.getOid())) { final AccountInfo tarAcc = map.get(accountInst.getOid()); tarAcc.addAmount(gainloss); } else { final AccountInfo tarAcc = new AccountInfo(accountInst, gainloss); tarAcc.setAmountRate(gainloss); tarAcc.setCurrInstance(currentInst); map.put(accountInst.getOid(), tarAcc); } } } if (!map.isEmpty()) { Insert insert = null; CurrencyInst curr = null; BigDecimal gainlossSum = BigDecimal.ZERO; for (final Entry<String, AccountInfo> entry : map.entrySet()) { final AccountInfo tarAcc = entry.getValue(); final Instance instAcc = Instance.get(entry.getKey()); final BigDecimal gainloss = tarAcc.getAmount(); gainlossSum = gainlossSum.add(gainloss); final Instance currInstance = tarAcc.getCurrInstance(); curr = new CurrencyInst(currInstance); final Map<String, String[]> mapVal = validateInfo(_parameter, gainloss); final String[] accs = mapVal.get("accs"); final String[] check = mapVal.get("check"); if (checkAccounts(accs, 0, check).length() > 0) { if (gainloss.compareTo(BigDecimal.ZERO) != 0) { final String[] accOids = mapVal.get("accountOids"); if (insert == null) { final DateTimeFormatter formater = DateTimeFormat.mediumDate(); final String dateStr = dateTo .withChronology(Context.getThreadContext().getChronology()) .toString(formater.withLocale(Context.getThreadContext().getLocale())); final StringBuilder description = new StringBuilder(); description .append(DBProperties .getProperty("Accounting_DocumentAccountForm.TxnRecalculate.Label")) .append(" ").append(dateStr); insert = new Insert(CIAccounting.Transaction); insert.add(CIAccounting.Transaction.Description, description.toString()); insert.add(CIAccounting.Transaction.Date, dateTo); insert.add(CIAccounting.Transaction.PeriodLink, _parameter.getInstance().getId()); insert.add(CIAccounting.Transaction.Status, Status.find(CIAccounting.TransactionStatus.uuid, "Open").getId()); insert.execute(); } Insert insertPos = new Insert(CIAccounting.TransactionPositionCredit); insertPos.add(CIAccounting.TransactionPositionCredit.TransactionLink, insert.getId()); if (gainloss.signum() < 0) { insertPos.add(CIAccounting.TransactionPositionCredit.AccountLink, instAcc.getId()); } else { insertPos.add(CIAccounting.TransactionPositionCredit.AccountLink, Instance.get(accOids[0]).getId()); } insertPos.add(CIAccounting.TransactionPositionCredit.Amount, gainloss.abs()); insertPos.add(CIAccounting.TransactionPositionCredit.RateAmount, gainloss.abs()); insertPos.add(CIAccounting.TransactionPositionCredit.CurrencyLink, currInstance.getId()); insertPos.add(CIAccounting.TransactionPositionCredit.RateCurrencyLink, currInstance.getId()); insertPos.add(CIAccounting.TransactionPositionCredit.Rate, new Object[] { BigDecimal.ONE, BigDecimal.ONE }); insertPos.execute(); insertPos = new Insert(CIAccounting.TransactionPositionDebit); insertPos.add(CIAccounting.TransactionPositionDebit.TransactionLink, insert.getId()); if (gainloss.signum() < 0) { insertPos.add(CIAccounting.TransactionPositionDebit.AccountLink, Instance.get(accOids[0]).getId()); } else { insertPos.add(CIAccounting.TransactionPositionDebit.AccountLink, instAcc.getId()); } insertPos.add(CIAccounting.TransactionPositionDebit.Amount, gainloss.abs().negate()); insertPos.add(CIAccounting.TransactionPositionDebit.RateAmount, gainloss.abs().negate()); insertPos.add(CIAccounting.TransactionPositionDebit.CurrencyLink, currInstance.getId()); insertPos.add(CIAccounting.TransactionPositionDebit.RateCurrencyLink, currInstance.getId()); insertPos.add(CIAccounting.TransactionPositionDebit.Rate, new Object[] { BigDecimal.ONE, BigDecimal.ONE }); insertPos.execute(); } } } if (insert != null) { final Instance instance = insert.getInstance(); // create classifications final Classification classification1 = (Classification) CIAccounting.TransactionClass.getType(); final Insert relInsert1 = new Insert(classification1.getClassifyRelationType()); relInsert1.add(classification1.getRelLinkAttributeName(), instance.getId()); relInsert1.add(classification1.getRelTypeAttributeName(), classification1.getId()); relInsert1.execute(); final Insert classInsert1 = new Insert(classification1); classInsert1.add(classification1.getLinkAttributeName(), instance.getId()); classInsert1.execute(); final Classification classification = (Classification) CIAccounting.TransactionClassGainLoss .getType(); final Insert relInsert = new Insert(classification.getClassifyRelationType()); relInsert.add(classification.getRelLinkAttributeName(), instance.getId()); relInsert.add(classification.getRelTypeAttributeName(), classification.getId()); relInsert.execute(); final Insert classInsert = new Insert(classification); classInsert.add(classification.getLinkAttributeName(), instance.getId()); classInsert.add(CIAccounting.TransactionClassGainLoss.Amount, gainlossSum); classInsert.add(CIAccounting.TransactionClassGainLoss.RateAmount, gainlossSum); classInsert.add(CIAccounting.TransactionClassGainLoss.CurrencyLink, curr.getInstance().getId()); classInsert.add(CIAccounting.TransactionClassGainLoss.RateCurrencyLink, curr.getInstance().getId()); classInsert.add(CIAccounting.TransactionClassGainLoss.Rate, new Object[] { BigDecimal.ONE, BigDecimal.ONE }); classInsert.execute(); new Create().connectDocs2Transaction(_parameter, instance, instDoc); } } } return new Return(); } /** * Gets the accounts4 document config. * * @param _parameter Parameter as passed by the eFaps API * @return the accounts4 document config * @throws EFapsException on error */ protected Set<String> getAccounts4DocumentConfig(final Parameter _parameter) throws EFapsException { final Set<String> set = new HashSet<>(); final QueryBuilder attrQueryBldr = new QueryBuilder(CIAccounting.AccountConfigDocument2Period); final AttributeQuery attrQuery = attrQueryBldr .getAttributeQuery(CIAccounting.AccountConfigDocument2Period.FromLink); final QueryBuilder queryBldr = new QueryBuilder(CIAccounting.AccountAbstract); queryBldr.addWhereAttrInQuery(CIAccounting.AccountAbstract.ID, attrQuery); final InstanceQuery query = queryBldr.getQuery(); query.execute(); while (query.next()) { set.add(query.getCurrentValue().getOid()); } return set; } /** * The Class Accounting4DocSum. */ public class Accounting4DocSum extends AbstractDocumentSum { } }