blob: b649489fb9f8a9b99d59a796644d57f5de28e030 [file] [log] [blame]
/*
* 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