public static function fillCache()
 {
     if (empty(self::$cache)) {
         $c = new oqc_ExternalContractCosts();
         $all = $c->get_list();
         $all = $all['list'];
         foreach ($all as $cost) {
             self::$cache[$cost->id] = $cost;
         }
     }
 }
<?php

if (!defined('sugarEntry')) {
    define('sugarEntry', true);
}
chdir('..');
require_once 'include/entryPoint.php';
require_once 'modules/oqc_ExternalContract/oqc_ExternalContract.php';
require_once 'modules/oqc_ExternalContractCosts/oqc_ExternalContractCosts.php';
$expenses = array();
$e = new oqc_ExternalContract();
$result = $e->get_list('', 'deleted=0');
$externalContracts = $result['list'];
foreach ($externalContracts as $externalContract) {
    $costIds = explode(' ', $externalContract->costs);
    $c = new oqc_ExternalContractCosts();
    foreach ($costIds as $id) {
        if ($c->retrieve($id)) {
            if (!array_key_exists($c->year, $expenses)) {
                $expenses[$c->year] = array();
            }
            $expenses[$c->year][$c->category] += $c->price;
        }
    }
}
$chartData = array();
foreach ($expenses as $year => $categories) {
    $chartData[] = array_merge(array('year' => $year), $categories);
}
$json = getJSONobj();
$encoded = $json->encode($chartData);
 private function saveCosts($isDuplicate)
 {
     $this->auditDeletedCosts();
     if (isset($_REQUEST['costIds']) && is_array($_REQUEST['costIds'])) {
         $costIds = array();
         $numberOfCosts = count($_REQUEST['costIds']);
         for ($i = 0; $i < $numberOfCosts; $i++) {
             $id = $_REQUEST['costIds'][$i];
             $price = $_REQUEST['costPrices'][$i];
             $desc = $_REQUEST['costDescriptions'][$i];
             $year = $_REQUEST['costYears'][$i];
             $category = $_REQUEST['costCategories'][$i];
             $paymentInterval = $_REQUEST['costPayment'][$i];
             $cost = new oqc_ExternalContractCosts();
             $beforeText = null;
             if (!$isDuplicate && $cost->retrieve($id)) {
                 if ($cost->price != $price || $cost->description != $desc || $cost->year != $year || $cost->category != $category || $cost->paymentinterval != $paymentInterval) {
                     $beforeText = $cost->as_plain_text();
                 }
             } else {
                 $beforeText = '<n/a>';
             }
             $cost = new oqc_ExternalContractCosts();
             if (!$isDuplicate && $cost->retrieve($id)) {
                 // the cost already exists (and this is no duplicate)
                 // update the cost instead of creating a new row in the table
                 $cost->price = $price;
                 $cost->year = $year;
                 $cost->category = $category;
                 $cost->description = $desc;
                 $cost->paymentinterval = $paymentInterval;
             } else {
                 $cost = new oqc_ExternalContractCosts($price, $desc, $category, $year, $paymentInterval);
             }
             $cost->save();
             $costIds[] = $cost->id;
             $this->saveDetailedCost($isDuplicate, $id, $cost);
             if (isset($beforeText)) {
                 $changes = array('field_name' => $cost->get_name(), 'data_type' => 'text', 'before' => $beforeText, 'after' => $cost->as_plain_text());
                 global $sugar_version;
                 if (floatval(substr($sugar_version, 0, 3)) > 6.3) {
                     $this->bean->db->save_audit_records($this->bean, $changes);
                 } else {
                     $this->bean->dbManager->helper->save_audit_records($this->bean, $changes);
                 }
             }
         }
         if ($numberOfCosts > 0) {
             $this->bean->costs = implode(' ', $costIds);
         } else {
             $this->bean->costs = '';
         }
     } else {
         $this->bean->costs = '';
     }
 }
 function get_exportable_fields_header($beans)
 {
     global $sugar_config;
     $lang = $sugar_config['default_language'];
     $mod_strings = return_module_language($lang, $this->module_dir);
     $basic_field_names = array();
     foreach ($this->basic_field_names as $field_name) {
         $basic_field_names[] = $mod_strings['LBL_' . strtoupper($field_name)];
     }
     $basic_field_names[] = $mod_strings['LBL_EXTERNALCONTRACTMATTER'];
     $years = array();
     // before iterating over external contract beans we fill the external contract costs cache to
     // speedup the getCostsArray() call
     oqc_ExternalContractCosts::fillCache();
     foreach ($beans as $bean) {
         // before you call this on all bean instances make sure you instantiated the cache containing
         // all EC-Costs collected with one get_list statement (instead of several retrieves..)
         $costs = $bean->getCostsArray(false);
         foreach ($costs as $cost) {
             if (!in_array($cost['year'], $years)) {
                 $years[] = $cost['year'];
             }
         }
     }
     sort($years);
     // add empty columns
     $additional_field_names = array();
     $startYear = false;
     // this should contain the proper start year
     foreach ($years as $year) {
         // set start year to the first year entry that is no garbage (e.g., empty / 0).
         // this is necessary because the years array sometimes contains empty strings at the beginning. these would then be interpreted as a startYear value of null.
         // if this bad start year value is used lateron, the number of columns cannot be calculated properly. this will result in >4000 columns in the csv file.
         if (FALSE === $startYear && $year > 0) {
             $startYear = $year;
         }
         $additional_field_names[] = $year;
         $additional_field_names[] = '';
     }
     return array(array_merge($basic_field_names, $additional_field_names), $startYear);
 }