query('RESET QUERY CACHE;'); $db->query('FLUSH QUERY CACHE'); // Initialize variables with defaults $account_type = ''; $saldo_type = ''; $and = ''; $type = ''; $data = array(); $sum = array(); $idToPdf = ''; if (!empty($_REQUEST['submit'])) { // Sanitize and validate inputs $account_type = isset($_REQUEST['account_type']) ? $db->quote($_REQUEST['account_type']) : ''; if ($account_type == 'a') { $account_type = ''; } $saldo_type = isset($_REQUEST['saldo_type']) ? $db->quote($_REQUEST['saldo_type']) : ''; $type2 = isset($_REQUEST['type2']) ? $db->quote($_REQUEST['type2']) : ''; $user_id = isset($_REQUEST['user_id']) ? $db->quote($_REQUEST['user_id']) : ''; // Build WHERE conditions safely $conditions = array("t.deleted='0'"); if ($saldo_type != '') { $conditions[] = "t.settled!='1'"; } if (!empty($type2)) { $conditions[] = "account_type2='" . $type2 . "'"; } if (!empty($user_id)) { $conditions[] = "a.assigned_user_id='" . $user_id . "'"; } // Build account type condition $account_condition = ''; if ($account_type != '') { $account_condition = " AND (a.account_type='rs' OR a.account_type = '" . $account_type . "')"; } // Optimized query - get all needed data in one go $query = "SELECT DISTINCT t.parent_id, a.index_dbf, a.name as account_name, a.currency_id, a.id as account_id FROM ecmtransactions as t INNER JOIN accounts AS a ON t.parent_id = a.id WHERE " . implode(' AND ', $conditions) . $account_condition . " ORDER BY a.index_dbf"; $clients = $db->query($query); // Cache currency objects to avoid repeated database calls $currency_cache = array(); while ($c = $db->fetchByAssoc($clients)) { // Skip invalid accounts if (empty($c['parent_id'])) continue; $row = array(); $row['id'] = $c['parent_id']; $row['name'] = $c['account_name']; $row['index'] = $c['index_dbf']; // Use cached currency data $currency_id = !empty($c['currency_id']) ? $c['currency_id'] : 'PLN'; if (!isset($currency_cache[$currency_id])) { $currency_obj = new Currency(); $currency_obj->retrieve($currency_id); $currency_cache[$currency_id] = $currency_obj->name; } $row['currency_id'] = $currency_cache[$currency_id]; // Get financial data (these functions need optimization too) $row['unsettled'] = getData($c['parent_id'], 0); $row['not_overdue'] = getData($c['parent_id'], 7); $row['overdue'] = getData($c['parent_id'], 1); $row['2'] = getData2($c['parent_id'], 2); $row['3'] = getData2($c['parent_id'], 3); $row['4'] = getData2($c['parent_id'], 4); $row['5'] = getData2($c['parent_id'], 5); $row['6'] = getData2($c['parent_id'], 6); $row['saldo'] = getData($c['parent_id'], 8); $row['today_saldo'] = 0; // Apply saldo filters if ($saldo_type == 'plus' && $row['saldo'] <= 0) continue; if ($saldo_type == 'minus' && $row['saldo'] >= 0) continue; if ($saldo_type == 'zero' && $row['saldo'] != 0) continue; if ($saldo_type == '' && $row['saldo'] == 0) continue; $idToPdf .= $row['id'] . ','; // Accumulate sums by currency if (!isset($sum[$currency_id])) { $sum[$currency_id] = array( 'unsettled' => 0, 'not_overdue' => 0, 'overdue' => 0, '2' => 0, '3' => 0, '4' => 0, '5' => 0, '6' => 0, 'saldo' => 0, 'today_saldo' => 0, 'currency_id' => $currency_cache[$currency_id] ); } $sum[$currency_id]['unsettled'] += $row['unsettled']; $sum[$currency_id]['not_overdue'] += $row['not_overdue']; $sum[$currency_id]['overdue'] += $row['overdue']; $sum[$currency_id]['2'] += $row['2']; $sum[$currency_id]['3'] += $row['3']; $sum[$currency_id]['4'] += $row['4']; $sum[$currency_id]['5'] += $row['5']; $sum[$currency_id]['6'] += $row['6']; $sum[$currency_id]['saldo'] += $row['saldo']; $sum[$currency_id]['today_saldo'] += $row['today_saldo']; $data[] = $row; } } // Get user list with single query $user_list = array(); $users_query = "SELECT id, first_name, last_name FROM users WHERE deleted=0"; $users_result = $db->query($users_query); while ($user_data = $db->fetchByAssoc($users_result)) { $user_list[$user_data['id']] = trim($user_data['first_name'] . ' ' . $user_data['last_name']); } // Initialize Smarty template $ss = new Sugar_Smarty(); global $mod_strings, $app_list_strings; $ss->assign("MOD", $mod_strings); $ss->assign("DATA", $data); $ss->assign("SUM", $sum); $ss->assign("SORT", array()); // Initialize empty sort array $ss->assign("account_type", $account_type); $app_list_strings['account_type_dom']['a'] = 'Wszystkie'; $ss->assign("account_type_list", $app_list_strings['account_type_dom']); $ss->assign("saldo_type", $saldo_type); $ss->assign("saldo_date_val", isset($_REQUEST['saldo_date_val']) ? $_REQUEST['saldo_date_val'] : ''); $ss->assign("idToPdf", rtrim($idToPdf, ',')); $ss->assign("type", isset($_REQUEST['type2']) ? $_REQUEST['type2'] : ''); $ss->assign("type2", $app_list_strings['account_type2_dom']); $ss->assign("user_id", isset($_REQUEST['user_id']) ? $_REQUEST['user_id'] : ''); $ss->assign("users", $user_list); echo $ss->display('modules/EcmPaymentStates/tpls/summary1.tpl'); // OPTIMIZED HELPER FUNCTIONS function getData($id, $expired) { static $cache = array(); $cache_key = $id . '_' . $expired; if (isset($cache[$cache_key])) { return $cache[$cache_key]; } $db = $GLOBALS['db']; $today = date('Y-m-d'); $settled_condition = "t.settled!='1' AND"; $date_condition = "1=1"; $is_saldo = false; switch ($expired) { case 0: $date_condition = "1=1"; break; case 1: $date_condition = "t.payment_date <= '$today'"; $is_saldo = true; break; case 7: $date_condition = "t.payment_date >= '$today'"; break; case 8: case 9: $date_condition = "t.payment_date <= '$today'"; $settled_condition = "1=1 AND"; $is_saldo = true; break; default: return getData2($id, $expired); } // Get type 1 transactions (MA) $query_ma = " SELECT SUM(t.value) AS sum FROM ecmtransactions AS t WHERE t.parent_id = '$id' AND t.deleted='0' AND $settled_condition t.type='1' AND $date_condition "; $result_ma = $db->query($query_ma); $ma_sum = 0; if ($row = $db->fetchByAssoc($result_ma)) { $ma_sum = floatval($row['sum']); } if (!$is_saldo) { $cache[$cache_key] = $ma_sum; return $ma_sum; } // Get type 0 transactions (WINIEN) for saldo calculation $query_winien = " SELECT SUM(t.value) AS sum FROM ecmtransactions AS t WHERE t.parent_id = '$id' AND t.deleted='0' AND $settled_condition t.type='0' AND $date_condition "; $result_winien = $db->query($query_winien); $winien_sum = 0; if ($row = $db->fetchByAssoc($result_winien)) { $winien_sum = floatval($row['sum']); } $result = $ma_sum - $winien_sum; // Special case for expired = 1 if ($expired == 1 && $result > 0) { $result = 0; } $cache[$cache_key] = $result; return $result; } function getData2($id, $expired, $dates = null) { static $cache = array(); $cache_key = $id . '_' . $expired . '_' . $dates; if (isset($cache[$cache_key])) { return $cache[$cache_key]; } $db = $GLOBALS['db']; // Prepare date conditions based on expired type $date_conditions = getDateConditions($expired, $dates); if ($date_conditions === false) { return 0; } $settled_condition = ($expired == 9) ? "" : "t.settled!='1' AND"; // Get type 0 transactions (WINIEN) $query_winien = " SELECT SUM(t.value) AS sum FROM ecmtransactions AS t WHERE t.parent_id = '$id' AND t.deleted='0' AND $settled_condition t.type='0' $date_conditions "; $result_winien = $db->query($query_winien); $winien_sum = 0; if ($row = $db->fetchByAssoc($result_winien)) { $winien_sum = floatval($row['sum']); } // Calculate settled amounts for type 0 $settled_winien = 0; $rel_query_winien = " SELECT r.value FROM ecmtransactions AS t LEFT JOIN ecmtransactions_rel AS r ON (r.ecmtransaction_a_id=t.id OR r.ecmtransaction_b_id=t.id) LEFT JOIN ecmtransactions AS t2 ON ( t2.id = CASE WHEN r.ecmtransaction_a_id = t.id THEN r.ecmtransaction_b_id ELSE r.ecmtransaction_a_id END ) WHERE t.parent_id = '$id' AND t.deleted='0' AND $settled_condition t.type='0' $date_conditions AND t2.deleted='0' "; if ($expired == 9 && $dates) { $target_date = date('Y-m-d', strtotime($dates)); $rel_query_winien .= " AND t2.payment_date <= '$target_date'"; } $rel_result_winien = $db->query($rel_query_winien); while ($rel_row = $db->fetchByAssoc($rel_result_winien)) { $settled_winien += floatval($rel_row['value']); } // Get type 1 transactions (MA) $query_ma = " SELECT SUM(t.value) AS sum FROM ecmtransactions AS t WHERE t.parent_id = '$id' AND t.deleted='0' AND $settled_condition t.type='1' $date_conditions "; $result_ma = $db->query($query_ma); $ma_sum = 0; if ($row = $db->fetchByAssoc($result_ma)) { $ma_sum = floatval($row['sum']); } // Calculate settled amounts for type 1 $settled_ma = 0; $rel_query_ma = " SELECT r.value FROM ecmtransactions AS t LEFT JOIN ecmtransactions_rel AS r ON (r.ecmtransaction_a_id=t.id OR r.ecmtransaction_b_id=t.id) LEFT JOIN ecmtransactions AS t2 ON ( t2.id = CASE WHEN r.ecmtransaction_a_id = t.id THEN r.ecmtransaction_b_id ELSE r.ecmtransaction_a_id END ) WHERE t.parent_id = '$id' AND t.deleted='0' AND $settled_condition t.type='1' $date_conditions AND t2.deleted='0' "; if ($expired == 9 && $dates) { $target_date = date('Y-m-d', strtotime($dates)); $rel_query_ma .= " AND t2.payment_date <= '$target_date'"; } $rel_result_ma = $db->query($rel_query_ma); while ($rel_row = $db->fetchByAssoc($rel_result_ma)) { $settled_ma += abs(floatval($rel_row['value'])); } $result_value = $settled_ma - $winien_sum + $ma_sum - $settled_winien; $cache[$cache_key] = $result_value; return $result_value; } function getDateConditions($expired, $dates = null) { $today = date('Y-m-d'); switch ($expired) { case 1: return "AND t.payment_date <= '$today'"; case 2: $date_from = date('Y-m-d', strtotime('-30 days')); return "AND t.payment_date >= '$date_from' AND t.payment_date < '$today'"; case 3: $date_to = date('Y-m-d', strtotime('-31 days')); $date_from = date('Y-m-d', strtotime('-60 days')); return "AND t.payment_date >= '$date_from' AND t.payment_date <= '$date_to'"; case 4: $date_to = date('Y-m-d', strtotime('-61 days')); $date_from = date('Y-m-d', strtotime('-90 days')); return "AND t.payment_date >= '$date_from' AND t.payment_date <= '$date_to'"; case 5: $date_to = date('Y-m-d', strtotime('-91 days')); $date_from = date('Y-m-d', strtotime('-180 days')); return "AND t.payment_date >= '$date_from' AND t.payment_date <= '$date_to'"; case 6: $date = date('Y-m-d', strtotime('-181 days')); return "AND t.payment_date <= '$date'"; case 9: $target_date = $dates ? date('Y-m-d', strtotime($dates)) : $today; return "AND t.payment_date <= '$target_date'"; default: return "AND 1=1"; } } // Comparison functions (compatible with PHP 5.6) function cmpUnsettled($a, $b) { if ($a['unsettled'] == $b['unsettled']) return 0; return ($a['unsettled'] < $b['unsettled']) ? -1 : 1; } function cmpUnsettledDesc($a, $b) { if ($a['unsettled'] == $b['unsettled']) return 0; return ($a['unsettled'] < $b['unsettled']) ? 1 : -1; } function cmpNotOverdue($a, $b) { if ($a['not_overdue'] == $b['not_overdue']) return 0; return ($a['not_overdue'] < $b['not_overdue']) ? -1 : 1; } function cmpNotOverdueDesc($a, $b) { if ($a['not_overdue'] == $b['not_overdue']) return 0; return ($a['not_overdue'] < $b['not_overdue']) ? 1 : -1; } function cmpOverdue($a, $b) { if ($a['overdue'] == $b['overdue']) return 0; return ($a['overdue'] < $b['overdue']) ? -1 : 1; } function cmpOverdueDesc($a, $b) { if ($a['overdue'] == $b['overdue']) return 0; return ($a['overdue'] < $b['overdue']) ? 1 : -1; } function cmpAccount($a, $b) { return strnatcmp($a['name'], $b['name']); } function cmpAccountDesc($a, $b) { return -strnatcmp($a['name'], $b['name']); } function cmpSaldo($a, $b) { if ($a['saldo'] == $b['saldo']) return 0; return ($a['saldo'] < $b['saldo']) ? -1 : 1; } function cmpSaldoDesc($a, $b) { if ($a['saldo'] == $b['saldo']) return 0; return ($a['saldo'] < $b['saldo']) ? 1 : -1; } function cmpTodaySaldo($a, $b) { if ($a['today_saldo'] == $b['today_saldo']) return 0; return ($a['today_saldo'] < $b['today_saldo']) ? -1 : 1; } function cmpTodaySaldoDesc($a, $b) { if ($a['today_saldo'] == $b['today_saldo']) return 0; return ($a['today_saldo'] < $b['today_saldo']) ? 1 : -1; } // Legacy functions (marked for removal - currently unused) function getSaldo($id) { /* Implementation removed - function appears unused */ } function unsettledFormatValue($settled, $val) { /* Implementation removed - function appears unused */ } function unsettledValue($settled, $val) { /* Implementation removed - function appears unused */ }