| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| import org.ofbiz.accounting.util.UtilAccounting; |
| import org.ofbiz.base.util.UtilDateTime; |
| import org.ofbiz.base.util.UtilMisc; |
| import org.ofbiz.base.util.UtilProperties; |
| import org.ofbiz.entity.GenericValue; |
| import org.ofbiz.entity.condition.EntityCondition; |
| import org.ofbiz.entity.condition.EntityOperator; |
| import org.ofbiz.party.party.PartyWorker; |
| |
| import java.sql.Date; |
| import java.sql.Timestamp; |
| |
| import javolution.util.FastList; |
| import javolution.util.FastMap; |
| |
| if (!fromDate) { |
| return; |
| } |
| if (!thruDate) { |
| thruDate = UtilDateTime.nowTimestamp(); |
| } |
| if (!parameters.glFiscalTypeId) { |
| parameters.glFiscalTypeId = "ACTUAL"; |
| } |
| |
| uiLabelMap = UtilProperties.getResourceBundleMap("AccountingUiLabels", locale); |
| parametersFromDate = fromDate; |
| |
| // Setup the divisions for which the report is executed |
| List partyIds = PartyWorker.getAssociatedPartyIdsByRelationshipType(delegator, organizationPartyId, 'GROUP_ROLLUP'); |
| partyIds.add(organizationPartyId); |
| |
| // Get the group of account classes that will be used to position accounts in the proper section of the Cash Flow statement |
| GenericValue glAccountClass = delegator.findOne("GlAccountClass", UtilMisc.toMap("glAccountClassId", "CASH_EQUIVALENT"), true); |
| List glAccountClassIds = UtilAccounting.getDescendantGlAccountClassIds(glAccountClass); |
| |
| List cashFlowBalanceTotalList = []; |
| |
| // Find the last closed time period to get the fromDate for the transactions in the current period and the ending balances of the last closed period |
| Map lastClosedTimePeriodResult = dispatcher.runSync("findLastClosedDate", ["organizationPartyId":organizationPartyId, "findDate":new Date(parametersFromDate.getTime()),"userLogin":userLogin]); |
| Timestamp periodClosingFromDate = (Timestamp)lastClosedTimePeriodResult.lastClosedDate; |
| if (!periodClosingFromDate) { |
| return; |
| } |
| GenericValue lastClosedTimePeriod = (GenericValue)lastClosedTimePeriodResult.lastClosedTimePeriod; |
| // Get the opening balances of Cash Account |
| Map openingCashBalances = [:]; |
| if (lastClosedTimePeriod) { |
| List timePeriodAndExprs = FastList.newInstance(); |
| timePeriodAndExprs.add(EntityCondition.makeCondition("organizationPartyId", EntityOperator.IN, partyIds)); |
| timePeriodAndExprs.add(EntityCondition.makeCondition("glAccountClassId", EntityOperator.IN, glAccountClassIds)); |
| timePeriodAndExprs.add(EntityCondition.makeCondition("endingBalance", EntityOperator.NOT_EQUAL, BigDecimal.ZERO)); |
| timePeriodAndExprs.add(EntityCondition.makeCondition("customTimePeriodId", EntityOperator.EQUALS, lastClosedTimePeriod.customTimePeriodId)); |
| List lastTimePeriodHistories = delegator.findList("GlAccountAndHistory", EntityCondition.makeCondition(timePeriodAndExprs, EntityOperator.AND), null, null, null, false); |
| lastTimePeriodHistories.each { lastTimePeriodHistory -> |
| Map accountMap = ["glAccountId":lastTimePeriodHistory.glAccountId, "accountCode":lastTimePeriodHistory.accountCode, "accountName":lastTimePeriodHistory.accountName, "balance":lastTimePeriodHistory.getBigDecimal("endingBalance"), "D":lastTimePeriodHistory.getBigDecimal("postedDebits"), "C":lastTimePeriodHistory.getBigDecimal("postedCredits")]; |
| openingCashBalances.(lastTimePeriodHistory.glAccountId) = accountMap; |
| } |
| } |
| List mainAndExprs = FastList.newInstance(); |
| mainAndExprs.add(EntityCondition.makeCondition("organizationPartyId", EntityOperator.IN, partyIds)); |
| mainAndExprs.add(EntityCondition.makeCondition("isPosted", EntityOperator.EQUALS, "Y")); |
| mainAndExprs.add(EntityCondition.makeCondition("glFiscalTypeId", EntityOperator.EQUALS, parameters.glFiscalTypeId)); |
| //mainAndExprs.add(EntityCondition.makeCondition("acctgTransTypeId", EntityOperator.NOT_EQUAL, "PERIOD_CLOSING")); |
| mainAndExprs.add(EntityCondition.makeCondition("glAccountClassId", EntityOperator.IN, glAccountClassIds)); |
| |
| // All GlAccount's transactions (from last closing period to parameter's fromDate) |
| accountBalanceList = []; |
| transactionTotals = []; |
| balanceTotal = BigDecimal.ZERO; |
| List openingCashBalanceAndExprs = FastList.newInstance(mainAndExprs); |
| openingCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.GREATER_THAN_EQUAL_TO, periodClosingFromDate)); |
| openingCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.LESS_THAN, parametersFromDate)); |
| transactionTotals = delegator.findList("AcctgTransEntrySums", EntityCondition.makeCondition(openingCashBalanceAndExprs, EntityOperator.AND), UtilMisc.toSet("glAccountId", "accountName", "accountCode", "debitCreditFlag", "amount"), UtilMisc.toList("glAccountId"), null, false); |
| transactionTotalsMap = [:]; |
| transactionTotalsMap.putAll(openingCashBalances); |
| transactionTotals.each { transactionTotal -> |
| Map accountMap = (Map)transactionTotalsMap.get(transactionTotal.glAccountId); |
| if (!accountMap) { |
| accountMap = UtilMisc.makeMapWritable(transactionTotal); |
| accountMap.remove("debitCreditFlag"); |
| accountMap.remove("amount"); |
| accountMap.D = BigDecimal.ZERO; |
| accountMap.C = BigDecimal.ZERO; |
| accountMap.balance = BigDecimal.ZERO; |
| } |
| if (accountMap.debitCreditFlag && accountMap.amount) { |
| accountMap.remove("debitCreditFlag"); |
| accountMap.remove("amount"); |
| } |
| if (transactionTotal.debitCreditFlag == "C") { |
| accountMap.C = ((BigDecimal)accountMap.get("C")).add(transactionTotal.amount); |
| accountMap.balance = (accountMap.balance).subtract(transactionTotal.amount); |
| } else { |
| accountMap.D = ((BigDecimal)accountMap.get("D")).add(transactionTotal.amount); |
| accountMap.balance = (accountMap.balance).add(transactionTotal.amount); |
| } |
| |
| transactionTotalsMap.put(transactionTotal.glAccountId, accountMap); |
| } |
| glAccountIdList = []; |
| accountBalanceList = UtilMisc.sortMaps(transactionTotalsMap.values().asList(), UtilMisc.toList("accountCode")); |
| accountBalanceList.each { accountBalance -> |
| balanceTotal = balanceTotal.add(accountBalance.balance); |
| } |
| openingCashBalanceTotal = balanceTotal; |
| context.openingCashBalanceList = accountBalanceList; |
| cashFlowBalanceTotalList.add("totalName":"AccountingOpeningCashBalance", "balance":balanceTotal); |
| openingTransactionKeySet = transactionTotalsMap.keySet(); |
| |
| // PERIOD CASH BALANCE |
| // GlAccounts from parameter's fromDate to parameter's thruDate. |
| accountBalanceList = []; |
| transactionTotals = []; |
| balanceTotal = BigDecimal.ZERO; |
| List periodCashBalanceAndExprs = FastList.newInstance(mainAndExprs); |
| periodCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.GREATER_THAN_EQUAL_TO, parametersFromDate)); |
| periodCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.LESS_THAN, thruDate)); |
| transactionTotals = delegator.findList("AcctgTransEntrySums", EntityCondition.makeCondition(periodCashBalanceAndExprs, EntityOperator.AND), UtilMisc.toSet("glAccountId", "accountName", "accountCode", "debitCreditFlag", "amount"), UtilMisc.toList("glAccountId"), null, false); |
| if (transactionTotals) { |
| Map transactionTotalsMap = [:]; |
| balanceTotalCredit = BigDecimal.ZERO; |
| balanceTotalDebit = BigDecimal.ZERO; |
| transactionTotals.each { transactionTotal -> |
| Map accountMap = (Map)transactionTotalsMap.get(transactionTotal.glAccountId); |
| if (!accountMap) { |
| accountMap = UtilMisc.makeMapWritable(transactionTotal); |
| accountMap.remove("debitCreditFlag"); |
| accountMap.remove("amount"); |
| accountMap.D = BigDecimal.ZERO; |
| accountMap.C = BigDecimal.ZERO; |
| accountMap.balance = BigDecimal.ZERO; |
| } |
| UtilMisc.addToBigDecimalInMap(accountMap, transactionTotal.debitCreditFlag, transactionTotal.amount); |
| if ("D".equals(transactionTotal.debitCreditFlag)) { |
| balanceTotalDebit = balanceTotalDebit.add(transactionTotal.amount); |
| } else { |
| balanceTotalCredit = balanceTotalCredit.add(transactionTotal.amount); |
| } |
| BigDecimal debitAmount = (BigDecimal)accountMap.D; |
| BigDecimal creditAmount = (BigDecimal)accountMap.C; |
| BigDecimal balance = debitAmount.subtract(creditAmount); |
| accountMap.balance = balance; |
| transactionTotalsMap.(transactionTotal.glAccountId) = accountMap; |
| } |
| accountBalanceList = UtilMisc.sortMaps(transactionTotalsMap.values().asList(), UtilMisc.toList("accountCode")); |
| balanceTotal = balanceTotalDebit.subtract(balanceTotalCredit); |
| } |
| periodCashBalanceTotal = balanceTotal; |
| context.periodCashBalanceList = accountBalanceList; |
| context.periodCashBalanceList.add("accountName":uiLabelMap.AccountingTotalPeriodCashBalance, "balance":balanceTotal); |
| cashFlowBalanceTotalList.add("totalName":"AccountingPeriodCashBalance", "balance":balanceTotal); |
| |
| // CLOSING BALANCE |
| // GlAccounts from parameter's fromDate to parameter's thruDate. |
| accountBalanceList = []; |
| balanceTotal = BigDecimal.ZERO; |
| List transactionTotals = FastList.newInstance(); |
| transactionTotals.addAll(FastList.newInstance(context.openingCashBalanceList)); |
| transactionTotals.addAll(FastList.newInstance(context.periodCashBalanceList)); |
| transactionTotals = UtilMisc.sortMaps(transactionTotals, UtilMisc.toList("accountCode")); |
| closingTransactionKeySet = []; |
| if (transactionTotals) { |
| Map transactionTotalsMap = [:]; |
| balanceTotalCredit = BigDecimal.ZERO; |
| balanceTotalDebit = BigDecimal.ZERO; |
| transactionTotals.each { transactionTotal -> |
| if (transactionTotal.D != null) { |
| if (transactionTotalsMap.(transactionTotal.glAccountId)) { |
| totalDebitBalance = (transactionTotal.D).add(transactionTotalsMap.(transactionTotal.glAccountId).D); |
| totalCreditBalance = (transactionTotal.C).add(transactionTotalsMap.(transactionTotal.glAccountId).C); |
| if (transactionTotalsMap.(transactionTotal.glAccountId).D == 0 && transactionTotalsMap.(transactionTotal.glAccountId).C == 0) { |
| transactionTotalsMap.(transactionTotal.glAccountId).balance = (transactionTotal.balance).add(transactionTotalsMap.(transactionTotal.glAccountId).balance); |
| } else { |
| transactionTotalsMap.(transactionTotal.glAccountId).D = totalDebitBalance; |
| transactionTotalsMap.(transactionTotal.glAccountId).C = totalCreditBalance; |
| transactionTotalsMap.(transactionTotal.glAccountId).balance = totalDebitBalance.subtract(totalCreditBalance); |
| } |
| } else { |
| transactionTotalsMap.(transactionTotal.glAccountId) = FastMap.newInstance(transactionTotal); |
| } |
| accountBalanceList = UtilMisc.sortMaps(transactionTotalsMap.values().asList(), UtilMisc.toList("accountCode")); |
| } |
| } |
| closingTransactionKeySet = transactionTotalsMap.keySet(); |
| } |
| accountBalanceList.each { accountBalance -> |
| balanceTotal = balanceTotal.add(accountBalance.balance); |
| } |
| //closingCashBalanceTotal = balanceTotal; |
| context.closingCashBalanceList = accountBalanceList; |
| context.closingCashBalanceList.add("accountName":uiLabelMap.AccountingTotalClosingCashBalance, "balance":balanceTotal); |
| |
| // Get differences of glAccount in closing and opening list and then add difference to opening list. |
| if (closingTransactionKeySet) { |
| closingTransactionKeySet.removeAll(openingTransactionKeySet); |
| closingTransactionKeySet.each { closingTransactionKey -> |
| glAccount = delegator.findOne("GlAccount", UtilMisc.toMap("glAccountId", closingTransactionKey), true); |
| context.openingCashBalanceList.add(["glAccountId":glAccount.glAccountId, "accountName":glAccount.accountName, accountCode:glAccount.accountCode, balance:BigDecimal.ZERO, D:BigDecimal.ZERO, C:BigDecimal.ZERO]); |
| } |
| } |
| context.openingCashBalanceList.add(["accountName":uiLabelMap.AccountingTotalOpeningCashBalance, "balance":openingCashBalanceTotal]); |
| |
| // CASH FLOW STATEMENT ENDING BALANCE |
| // ENDING BALANCE = OPENING CASH BALANCE + PERIOD CASH BALANCE |
| endingCashBalanceTotal = openingCashBalanceTotal.add(periodCashBalanceTotal); |
| cashFlowBalanceTotalList.add("totalName":"AccountingEndingCashBalance", "balance":endingCashBalanceTotal); |
| context.cashFlowBalanceTotalList = cashFlowBalanceTotalList; |