| /* |
| * 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.apache.ofbiz.accounting.util.UtilAccounting |
| import org.apache.ofbiz.base.util.UtilDateTime |
| import org.apache.ofbiz.base.util.UtilMisc |
| import org.apache.ofbiz.base.util.UtilProperties |
| import org.apache.ofbiz.entity.GenericValue |
| import org.apache.ofbiz.entity.condition.EntityCondition |
| import org.apache.ofbiz.entity.condition.EntityOperator |
| import org.apache.ofbiz.party.party.PartyWorker |
| |
| import java.sql.Timestamp |
| |
| 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, parameters.get('ApplicationDecorator|organizationPartyId'), 'GROUP_ROLLUP') |
| partyIds.add(parameters.get('ApplicationDecorator|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 = from("GlAccountClass").where("glAccountClassId", "CASH_EQUIVALENT").cache(true).queryOne() |
| 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 = runService('findLastClosedDate', ["organizationPartyId":parameters.get('ApplicationDecorator|organizationPartyId'), "findDate": parametersFromDate,"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 = [] |
| 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 = from("GlAccountAndHistory").where(timePeriodAndExprs).queryList() |
| 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 = [] |
| 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("glAccountClassId", EntityOperator.IN, glAccountClassIds)) |
| |
| // All GlAccount's transactions (from last closing period to parameter's fromDate) |
| accountBalanceList = [] |
| transactionTotals = [] |
| balanceTotal = BigDecimal.ZERO |
| List openingCashBalanceAndExprs = mainAndExprs as LinkedList |
| openingCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.GREATER_THAN_EQUAL_TO, periodClosingFromDate)) |
| openingCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.LESS_THAN, parametersFromDate)) |
| transactionTotals = select("glAccountId", "accountName", "accountCode", "debitCreditFlag", "amount").from("AcctgTransEntrySums").where(openingCashBalanceAndExprs).orderBy("glAccountId").queryList() |
| 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 = mainAndExprs as LinkedList |
| periodCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.GREATER_THAN_EQUAL_TO, parametersFromDate)) |
| periodCashBalanceAndExprs.add(EntityCondition.makeCondition("transactionDate", EntityOperator.LESS_THAN, thruDate)) |
| transactionTotals = select("glAccountId", "accountName", "accountCode", "debitCreditFlag", "amount").from("AcctgTransEntrySums").where(periodCashBalanceAndExprs).orderBy("glAccountId").queryList() |
| 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 = [] |
| transactionTotals.addAll(new LinkedList(context.openingCashBalanceList)) |
| transactionTotals.addAll(new LinkedList(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) = transactionTotal |
| } |
| accountBalanceList = UtilMisc.sortMaps(transactionTotalsMap.values().asList(), UtilMisc.toList("accountCode")) |
| } |
| } |
| closingTransactionKeySet = transactionTotalsMap.keySet() |
| } |
| accountBalanceList.each { accountBalance -> |
| balanceTotal = balanceTotal.add(accountBalance.balance) |
| } |
| 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 = from("GlAccount").where("glAccountId", closingTransactionKey).cache(true).queryOne() |
| 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 |