private void addRuntimeStatistic(
      Integer billingProcessId, Integer language, BillingProcessRunDTOEx runDto) {
    for (Iterator iter = new BillingProcessDAS().getCountAndSum(billingProcessId);
        iter.hasNext(); ) {
      Object[] row = (Object[]) iter.next();

      BillingProcessRunTotalDTOEx totalRowDto = new BillingProcessRunTotalDTOEx();
      totalRowDto.setProcessRun(runDto);
      totalRowDto.setCurrency(new CurrencyDAS().find((Integer) row[2]));
      totalRowDto.setCurrencyName(totalRowDto.getCurrency().getDescription(language));
      totalRowDto.setId(-1);
      totalRowDto.setTotalInvoiced((BigDecimal) row[1]);
      totalRowDto.setTotalNotPaid(BigDecimal.ZERO);
      totalRowDto.setTotalPaid(BigDecimal.ZERO);

      // now go over the totals by payment method
      Hashtable totals = new Hashtable();
      for (Iterator itt =
              new BillingProcessDAS().getSuccessfulProcessCurrencyMethodAndSum(billingProcessId);
          itt.hasNext(); ) {
        Object[] payedRow = (Object[]) itt.next();
        if (payedRow[0].equals(totalRowDto.getCurrency().getId())) {
          PaymentMethodDTO paymentMethod = new PaymentMethodDAS().find((Integer) payedRow[1]);
          BigDecimal payed = (BigDecimal) payedRow[2];
          totals.put(paymentMethod.getDescription(language), payed);
          totalRowDto.setTotalPaid(totalRowDto.getTotalPaid().add(payed));
        }
      }
      totalRowDto.setPmTotals(totals);
      for (Iterator itt = new BillingProcessDAS().getFailedProcessCurrencyAndSum(billingProcessId);
          itt.hasNext(); ) {
        Object[] unpayedRow = (Object[]) itt.next();
        if (unpayedRow[0].equals(totalRowDto.getCurrency().getId())) {
          totalRowDto.setTotalNotPaid(
              totalRowDto.getTotalNotPaid().add((BigDecimal) unpayedRow[1]));
        }
      }

      runDto.setInvoicesGenerated(runDto.getInvoicesGenerated() + ((Long) row[0]).intValue());
      runDto.getTotals().add(totalRowDto);
    }
  }
  public BillingProcessDTOEx getDtoEx(Integer language) {
    BillingProcessDTOEx retValue = new BillingProcessDTOEx();

    retValue.setBillingDate(billingProcess.getBillingDate());
    retValue.setEntity(billingProcess.getEntity());
    retValue.setId(billingProcess.getId());
    retValue.setPeriodUnit(billingProcess.getPeriodUnit());
    retValue.setPeriodValue(billingProcess.getPeriodValue());
    retValue.setIsReview(billingProcess.getIsReview());

    // now add the runs and grand total
    BillingProcessRunDTOEx grandTotal = new BillingProcessRunDTOEx();
    int totalInvoices = 0;
    int runsCounter = 0;
    List<BillingProcessRunDTOEx> runs = new ArrayList<BillingProcessRunDTOEx>();
    // go throuhg every run
    for (Iterator it = billingProcess.getProcessRuns().iterator(); it.hasNext(); ) {
      ProcessRunDTO run = (ProcessRunDTO) it.next();
      BillingProcessRunBL runBL = new BillingProcessRunBL(run);
      BillingProcessRunDTOEx runDto = runBL.getDTO(language);
      runs.add(runDto);
      runsCounter++;

      // add statistic for InProgress run proccess in DTO
      if (run.getPaymentFinished() == null) {
        addRuntimeStatistic(run.getBillingProcess().getId(), language, runDto);
      }

      LOG.debug(
          "Run:" + run.getId() + " has " + run.getProcessRunTotals().size() + " total records");
      // go over the totals, since there's one per currency
      for (Iterator it2 = runDto.getTotals().iterator(); it2.hasNext(); ) {
        // the total to process
        BillingProcessRunTotalDTOEx totalDto = (BillingProcessRunTotalDTOEx) it2.next();

        BillingProcessRunTotalDTOEx sum = getTotal(totalDto.getCurrency(), grandTotal.getTotals());

        BigDecimal totalTmp = totalDto.getTotalInvoiced().add(sum.getTotalInvoiced());
        sum.setTotalInvoiced(totalTmp);

        totalTmp = totalDto.getTotalPaid().add(sum.getTotalPaid());
        sum.setTotalPaid(totalTmp);

        // can't add up the not paid, because many runs will try to
        // get the same invoices paid, so the not paid field gets
        // duplicated amounts.
        totalTmp = sum.getTotalInvoiced().subtract(sum.getTotalPaid());
        sum.setTotalNotPaid(totalTmp);

        // make sure this total has the currency name initialized
        if (sum.getCurrencyName() == null) {
          CurrencyBL currency = new CurrencyBL(sum.getCurrency().getId());
          sum.setCurrencyName(currency.getEntity().getDescription(language));
        }
        // add the payment method totals
        for (Enumeration en = totalDto.getPmTotals().keys(); en.hasMoreElements(); ) {
          String method = (String) en.nextElement();
          BigDecimal methodTotal = new BigDecimal(totalDto.getPmTotals().get(method).toString());

          if (sum.getPmTotals().containsKey(method)) {
            if (sum.getPmTotals().get(method) != null) {
              methodTotal =
                  methodTotal.add(
                      new BigDecimal(((Float) sum.getPmTotals().get(method)).toString()));
            }
          }
          sum.getPmTotals().put(method, new Float(methodTotal.floatValue()));
        }

        LOG.debug(
            "Added total to run dto. PMs in total:"
                + sum.getPmTotals().size()
                + " now grandTotal totals:"
                + grandTotal.getTotals().size());
      }
      totalInvoices += runDto.getInvoicesGenerated();
    }

    grandTotal.setInvoicesGenerated(new Integer(totalInvoices));

    retValue.setRetries(new Integer(runsCounter));
    retValue.setRuns(runs);
    retValue.setGrandTotal(grandTotal);
    retValue.setBillingDateEnd(getEndOfProcessPeriod(billingProcess));
    retValue.setOrdersProcessed(new Integer(billingProcess.getOrderProcesses().size()));

    return retValue;
  }