| Server IP : 103.161.17.216 / Your IP : 216.73.216.1 Web Server : nginx/1.18.0 System : Linux tipsysaigoncharming 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 User : www-data ( 33) PHP Version : 7.4.3-4ubuntu2.29 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/app.houseland.info/application/controllers/admin/ |
Upload File : |
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Reports extends AdminController
{
/**
* Codeigniter Instance
* Expenses detailed report filters use $ci
* @var object
*/
private $ci;
public function __construct()
{
parent::__construct();
if (staff_cant('view', 'reports')) {
access_denied('reports');
}
$this->ci = &get_instance();
$this->load->model('reports_model');
}
/* No access on this url */
public function index()
{
redirect(admin_url());
}
/* See knowledge base article reports*/
public function knowledge_base_articles()
{
$this->load->model('knowledge_base_model');
$data['groups'] = $this->knowledge_base_model->get_kbg();
$data['title'] = _l('kb_reports');
$this->load->view('admin/reports/knowledge_base_articles', $data);
}
/*
public function tax_summary(){
$this->load->model('taxes_model');
$this->load->model('payments_model');
$this->load->model('invoices_model');
$data['taxes'] = $this->db->query("SELECT DISTINCT taxname,taxrate FROM ".db_prefix()."item_tax WHERE rel_type='invoice'")->result_array();
$this->load->view('admin/reports/tax_summary',$data);
}*/
/* Repoert leads conversions */
public function leads()
{
$type = 'leads';
if ($this->input->get('type')) {
$type = $type . '_' . $this->input->get('type');
$data['leads_staff_report'] = json_encode($this->reports_model->leads_staff_report());
}
$this->load->model('leads_model');
$data['statuses'] = $this->leads_model->get_status();
$data['leads_this_week_report'] = json_encode($this->reports_model->leads_this_week_report());
$data['leads_sources_report'] = json_encode($this->reports_model->leads_sources_report());
$this->load->view('admin/reports/' . $type, $data);
}
/* Sales reportts */
public function sales()
{
$data['mysqlVersion'] = $this->db->query('SELECT VERSION() as version')->row();
$data['sqlMode'] = $this->db->query('SELECT @@sql_mode as mode')->row();
if (is_using_multiple_currencies() || is_using_multiple_currencies(db_prefix() . 'creditnotes') || is_using_multiple_currencies(db_prefix() . 'estimates') || is_using_multiple_currencies(db_prefix() . 'proposals')) {
$this->load->model('currencies_model');
$data['currencies'] = $this->currencies_model->get();
}
$this->load->model('invoices_model');
$this->load->model('estimates_model');
$this->load->model('proposals_model');
$this->load->model('credit_notes_model');
$data['credit_notes_statuses'] = $this->credit_notes_model->get_statuses();
$data['invoice_statuses'] = $this->invoices_model->get_statuses();
$data['estimate_statuses'] = $this->estimates_model->get_statuses();
$data['payments_years'] = $this->reports_model->get_distinct_payments_years();
$data['estimates_sale_agents'] = $this->estimates_model->get_sale_agents();
$data['invoices_sale_agents'] = $this->invoices_model->get_sale_agents();
$data['proposals_sale_agents'] = $this->proposals_model->get_sale_agents();
$data['proposals_statuses'] = $this->proposals_model->get_statuses();
$data['invoice_taxes'] = $this->distinct_taxes('invoice');
$data['estimate_taxes'] = $this->distinct_taxes('estimate');
$data['proposal_taxes'] = $this->distinct_taxes('proposal');
$data['credit_note_taxes'] = $this->distinct_taxes('credit_note');
$data['title'] = _l('sales_reports');
$this->load->view('admin/reports/sales', $data);
}
/* Customer report */
public function customers_report()
{
if ($this->input->is_ajax_request()) {
$this->load->model('currencies_model');
$select = [
get_sql_select_client_company(),
'(SELECT COUNT(clientid) FROM ' . db_prefix() . 'invoices WHERE ' . db_prefix() . 'invoices.clientid = ' . db_prefix() . 'clients.userid AND status != 5)',
'(SELECT SUM(subtotal) - SUM(discount_total) FROM ' . db_prefix() . 'invoices WHERE ' . db_prefix() . 'invoices.clientid = ' . db_prefix() . 'clients.userid AND status != 5)',
'(SELECT SUM(total) FROM ' . db_prefix() . 'invoices WHERE ' . db_prefix() . 'invoices.clientid = ' . db_prefix() . 'clients.userid AND status != 5)',
];
$custom_date_select = $this->get_where_report_period();
if ($custom_date_select != '') {
$i = 0;
foreach ($select as $_select) {
if ($i !== 0) {
$_temp = substr($_select, 0, -1);
$_temp .= ' ' . $custom_date_select . ')';
$select[$i] = $_temp;
}
$i++;
}
}
$by_currency = $this->input->post('report_currency');
$currency = $this->currencies_model->get_base_currency();
if ($by_currency) {
$i = 0;
foreach ($select as $_select) {
if ($i !== 0) {
$_temp = substr($_select, 0, -1);
$_temp .= ' AND currency =' . $this->db->escape_str($by_currency) . ')';
$select[$i] = $_temp;
}
$i++;
}
$currency = $this->currencies_model->get($by_currency);
}
$aColumns = $select;
$sIndexColumn = 'userid';
$sTable = db_prefix() . 'clients';
$where = [];
$result = data_tables_init($aColumns, $sIndexColumn, $sTable, [], $where, [
'userid',
]);
$output = $result['output'];
$rResult = $result['rResult'];
$x = 0;
foreach ($rResult as $aRow) {
$row = [];
for ($i = 0; $i < count($aColumns); $i++) {
if (strpos($aColumns[$i], 'as') !== false && !isset($aRow[$aColumns[$i]])) {
$_data = $aRow[strafter($aColumns[$i], 'as ')];
} else {
$_data = $aRow[$aColumns[$i]];
}
if ($i == 0) {
$_data = '<a href="' . admin_url('clients/client/' . $aRow['userid']) . '" target="_blank">' . $aRow['company'] . '</a>';
} elseif ($aColumns[$i] == $select[2] || $aColumns[$i] == $select[3]) {
if ($_data == null) {
$_data = 0;
}
$_data = app_format_money($_data, $currency->name);
}
$row[] = $_data;
}
$output['aaData'][] = $row;
$x++;
}
echo json_encode($output);
die();
}
}
public function payments_received()
{
if ($this->input->is_ajax_request()) {
$this->load->model('currencies_model');
$this->load->model('payment_modes_model');
$payment_gateways = $this->payment_modes_model->get_payment_gateways(true);
$select = [
db_prefix() . 'invoicepaymentrecords.id',
db_prefix() . 'invoicepaymentrecords.date',
'invoiceid',
get_sql_select_client_company(),
'paymentmode',
'transactionid',
'note',
'amount',
];
$where = [
'AND status != 5',
];
$custom_date_select = $this->get_where_report_period(db_prefix() . 'invoicepaymentrecords.date');
if ($custom_date_select != '') {
array_push($where, $custom_date_select);
}
$by_currency = $this->input->post('report_currency');
if ($by_currency) {
$currency = $this->currencies_model->get($by_currency);
array_push($where, 'AND currency=' . $this->db->escape_str($by_currency));
} else {
$currency = $this->currencies_model->get_base_currency();
}
$aColumns = $select;
$sIndexColumn = 'id';
$sTable = db_prefix() . 'invoicepaymentrecords';
$join = [
'JOIN ' . db_prefix() . 'invoices ON ' . db_prefix() . 'invoices.id = ' . db_prefix() . 'invoicepaymentrecords.invoiceid',
'LEFT JOIN ' . db_prefix() . 'clients ON ' . db_prefix() . 'clients.userid = ' . db_prefix() . 'invoices.clientid',
'LEFT JOIN ' . db_prefix() . 'payment_modes ON ' . db_prefix() . 'payment_modes.id = ' . db_prefix() . 'invoicepaymentrecords.paymentmode',
];
$result = data_tables_init($aColumns, $sIndexColumn, $sTable, $join, $where, [
'number',
'clientid',
db_prefix() . 'payment_modes.name',
db_prefix() . 'payment_modes.id as paymentmodeid',
'paymentmethod',
'deleted_customer_name',
]);
$output = $result['output'];
$rResult = $result['rResult'];
$footer_data['total_amount'] = 0;
foreach ($rResult as $aRow) {
$row = [];
for ($i = 0; $i < count($aColumns); $i++) {
if (strpos($aColumns[$i], 'as') !== false && !isset($aRow[$aColumns[$i]])) {
$_data = $aRow[strafter($aColumns[$i], 'as ')];
} else {
$_data = $aRow[$aColumns[$i]];
}
if ($aColumns[$i] == 'note') {
$_data = process_text_content_for_display($aRow['note']);
} else if ($aColumns[$i] == 'paymentmode') {
$_data = $aRow['name'];
if (is_null($aRow['paymentmodeid'])) {
foreach ($payment_gateways as $gateway) {
if ($aRow['paymentmode'] == $gateway['id']) {
$_data = e($gateway['name']);
}
}
}
if (!empty($aRow['paymentmethod'])) {
$_data .= ' - ' . e($aRow['paymentmethod']);
}
} elseif ($aColumns[$i] == db_prefix() . 'invoicepaymentrecords.id') {
$_data = '<a href="' . admin_url('payments/payment/' . $_data) . '" target="_blank">' . e($_data) . '</a>';
} elseif ($aColumns[$i] == db_prefix() . 'invoicepaymentrecords.date') {
$_data = e(_d($_data));
} elseif ($aColumns[$i] == 'invoiceid') {
$_data = '<a href="' . admin_url('invoices/list_invoices/' . $aRow[$aColumns[$i]]) . '" target="_blank">' . e(format_invoice_number($aRow['invoiceid'])) . '</a>';
} elseif ($i == 3) {
if (empty($aRow['deleted_customer_name'])) {
$_data = '<a href="' . admin_url('clients/client/' . $aRow['clientid']) . '" target="_blank">' . e($aRow['company']) . '</a>';
} else {
$row[] = e($aRow['deleted_customer_name']);
}
} elseif ($aColumns[$i] == 'amount') {
$footer_data['total_amount'] += $_data;
$_data = e(app_format_money($_data, $currency->name));
}
$row[] = $_data;
}
$output['aaData'][] = $row;
}
$footer_data['total_amount'] = e(app_format_money($footer_data['total_amount'], $currency->name));
$output['sums'] = $footer_data;
echo json_encode($output);
die();
}
}
public function proposals_report()
{
if ($this->input->is_ajax_request()) {
$this->load->model('currencies_model');
$this->load->model('proposals_model');
$proposalsTaxes = $this->distinct_taxes('proposal');
$totalTaxesColumns = count($proposalsTaxes);
$select = [
'id',
'subject',
'proposal_to',
'date',
'open_till',
'subtotal',
'total',
'total_tax',
'discount_total',
'adjustment',
'status',
];
$proposalsTaxesSelect = array_reverse($proposalsTaxes);
foreach ($proposalsTaxesSelect as $key => $tax) {
array_splice($select, 8, 0, '(
SELECT CASE
WHEN discount_percent != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * discount_percent/100)),' . get_decimal_places() . ')
WHEN discount_total != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * (discount_total/subtotal*100) / 100)),' . get_decimal_places() . ')
ELSE ROUND(SUM(qty*rate/100*' . db_prefix() . 'item_tax.taxrate),' . get_decimal_places() . ')
END
FROM ' . db_prefix() . 'itemable
INNER JOIN ' . db_prefix() . 'item_tax ON ' . db_prefix() . 'item_tax.itemid=' . db_prefix() . 'itemable.id
WHERE ' . db_prefix() . 'itemable.rel_type="proposal" AND taxname="' . $tax['taxname'] . '" AND taxrate="' . $tax['taxrate'] . '" AND ' . db_prefix() . 'itemable.rel_id=' . db_prefix() . 'proposals.id) as total_tax_single_' . $key);
}
$where = [];
$custom_date_select = $this->get_where_report_period();
if ($custom_date_select != '') {
array_push($where, $custom_date_select);
}
if ($this->input->post('proposal_status')) {
$statuses = $this->input->post('proposal_status');
$_statuses = [];
if (is_array($statuses)) {
foreach ($statuses as $status) {
if ($status != '') {
array_push($_statuses, $this->db->escape_str($status));
}
}
}
if (count($_statuses) > 0) {
array_push($where, 'AND status IN (' . implode(', ', $_statuses) . ')');
}
}
if ($this->input->post('proposals_sale_agents')) {
$agents = $this->input->post('proposals_sale_agents');
$_agents = [];
if (is_array($agents)) {
foreach ($agents as $agent) {
if ($agent != '') {
array_push($_agents, $this->db->escape_str($agent));
}
}
}
if (count($_agents) > 0) {
array_push($where, 'AND assigned IN (' . implode(', ', $_agents) . ')');
}
}
$by_currency = $this->input->post('report_currency');
if ($by_currency) {
$currency = $this->currencies_model->get($by_currency);
array_push($where, 'AND currency=' . $this->db->escape_str($by_currency));
} else {
$currency = $this->currencies_model->get_base_currency();
}
$aColumns = $select;
$sIndexColumn = 'id';
$sTable = db_prefix() . 'proposals';
$join = [];
$result = data_tables_init($aColumns, $sIndexColumn, $sTable, $join, $where, [
'rel_id',
'rel_type',
'discount_percent',
]);
$output = $result['output'];
$rResult = $result['rResult'];
$footer_data = [
'total' => 0,
'subtotal' => 0,
'total_tax' => 0,
'discount_total' => 0,
'adjustment' => 0,
];
foreach ($proposalsTaxes as $key => $tax) {
$footer_data['total_tax_single_' . $key] = 0;
}
foreach ($rResult as $aRow) {
$row = [];
$row[] = '<a href="' . admin_url('proposals/list_proposals/' . $aRow['id']) . '" target="_blank">' . e(format_proposal_number($aRow['id'])) . '</a>';
$row[] = '<a href="' . admin_url('proposals/list_proposals/' . $aRow['id']) . '" target="_blank">' . e($aRow['subject']) . '</a>';
if ($aRow['rel_type'] == 'lead') {
$row[] = '<a href="#" onclick="init_lead(' . $aRow['rel_id'] . ');return false;" target="_blank" data-toggle="tooltip" data-title="' . _l('lead') . '">' . e($aRow['proposal_to']) . '</a>' . '<span class="hide">' . _l('lead') . '</span>';
} elseif ($aRow['rel_type'] == 'customer') {
$row[] = '<a href="' . admin_url('clients/client/' . $aRow['rel_id']) . '" target="_blank" data-toggle="tooltip" data-title="' . _l('client') . '">' . e($aRow['proposal_to']) . '</a>' . '<span class="hide">' . _l('client') . '</span>';
} else {
$row[] = '';
}
$row[] = e(_d($aRow['date']));
$row[] = e(_d($aRow['open_till']));
$row[] = e(app_format_money($aRow['subtotal'], $currency->name));
$footer_data['subtotal'] += $aRow['subtotal'];
$row[] = e(app_format_money($aRow['total'], $currency->name));
$footer_data['total'] += $aRow['total'];
$row[] = e(app_format_money($aRow['total_tax'], $currency->name));
$footer_data['total_tax'] += $aRow['total_tax'];
$t = $totalTaxesColumns - 1;
$i = 0;
foreach ($proposalsTaxes as $tax) {
$row[] = e(app_format_money(($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]), $currency->name));
$footer_data['total_tax_single_' . $i] += ($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]);
$t--;
$i++;
}
$row[] = e(app_format_money($aRow['discount_total'], $currency->name));
$footer_data['discount_total'] += $aRow['discount_total'];
$row[] = e(app_format_money($aRow['adjustment'], $currency->name));
$footer_data['adjustment'] += $aRow['adjustment'];
$row[] = format_proposal_status($aRow['status']);
$output['aaData'][] = $row;
}
foreach ($footer_data as $key => $total) {
$footer_data[$key] = e(app_format_money($total, $currency->name));
}
$output['sums'] = $footer_data;
echo json_encode($output);
die();
}
}
public function estimates_report()
{
if ($this->input->is_ajax_request()) {
$this->load->model('currencies_model');
$this->load->model('estimates_model');
$estimateTaxes = $this->distinct_taxes('estimate');
$totalTaxesColumns = count($estimateTaxes);
$select = [
'number',
get_sql_select_client_company(),
'invoiceid',
'YEAR(date) as year',
'date',
'expirydate',
'subtotal',
'total',
'total_tax',
'discount_total',
'adjustment',
'reference_no',
'status',
];
$estimatesTaxesSelect = array_reverse($estimateTaxes);
foreach ($estimatesTaxesSelect as $key => $tax) {
array_splice($select, 9, 0, '(
SELECT CASE
WHEN discount_percent != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * discount_percent/100)),' . get_decimal_places() . ')
WHEN discount_total != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * (discount_total/subtotal*100) / 100)),' . get_decimal_places() . ')
ELSE ROUND(SUM(qty*rate/100*' . db_prefix() . 'item_tax.taxrate),' . get_decimal_places() . ')
END
FROM ' . db_prefix() . 'itemable
INNER JOIN ' . db_prefix() . 'item_tax ON ' . db_prefix() . 'item_tax.itemid=' . db_prefix() . 'itemable.id
WHERE ' . db_prefix() . 'itemable.rel_type="estimate" AND taxname="' . $tax['taxname'] . '" AND taxrate="' . $tax['taxrate'] . '" AND ' . db_prefix() . 'itemable.rel_id=' . db_prefix() . 'estimates.id) as total_tax_single_' . $key);
}
$where = [];
$custom_date_select = $this->get_where_report_period();
if ($custom_date_select != '') {
array_push($where, $custom_date_select);
}
if ($this->input->post('estimate_status')) {
$statuses = $this->input->post('estimate_status');
$_statuses = [];
if (is_array($statuses)) {
foreach ($statuses as $status) {
if ($status != '') {
array_push($_statuses, $this->db->escape_str($status));
}
}
}
if (count($_statuses) > 0) {
array_push($where, 'AND status IN (' . implode(', ', $_statuses) . ')');
}
}
if ($this->input->post('sale_agent_estimates')) {
$agents = $this->input->post('sale_agent_estimates');
$_agents = [];
if (is_array($agents)) {
foreach ($agents as $agent) {
if ($agent != '') {
array_push($_agents, $this->db->escape_str($agent));
}
}
}
if (count($_agents) > 0) {
array_push($where, 'AND sale_agent IN (' . implode(', ', $_agents) . ')');
}
}
$by_currency = $this->input->post('report_currency');
if ($by_currency) {
$currency = $this->currencies_model->get($by_currency);
array_push($where, 'AND currency=' . $this->db->escape_str($by_currency));
} else {
$currency = $this->currencies_model->get_base_currency();
}
$aColumns = $select;
$sIndexColumn = 'id';
$sTable = db_prefix() . 'estimates';
$join = [
'LEFT JOIN ' . db_prefix() . 'clients ON ' . db_prefix() . 'clients.userid = ' . db_prefix() . 'estimates.clientid',
];
$result = data_tables_init($aColumns, $sIndexColumn, $sTable, $join, $where, [
'userid',
'clientid',
db_prefix() . 'estimates.id',
'discount_percent',
'deleted_customer_name',
]);
$output = $result['output'];
$rResult = $result['rResult'];
$footer_data = [
'total' => 0,
'subtotal' => 0,
'total_tax' => 0,
'discount_total' => 0,
'adjustment' => 0,
];
foreach ($estimateTaxes as $key => $tax) {
$footer_data['total_tax_single_' . $key] = 0;
}
foreach ($rResult as $aRow) {
$row = [];
$row[] = '<a href="' . admin_url('estimates/list_estimates/' . $aRow['id']) . '" target="_blank">' . e(format_estimate_number($aRow['id'])) . '</a>';
if (empty($aRow['deleted_customer_name'])) {
$row[] = '<a href="' . admin_url('clients/client/' . $aRow['userid']) . '" target="_blank">' . e($aRow['company']) . '</a>';
} else {
$row[] = e($aRow['deleted_customer_name']);
}
if ($aRow['invoiceid'] === null) {
$row[] = '';
} else {
$row[] = '<a href="' . admin_url('invoices/list_invoices/' . $aRow['invoiceid']) . '" target="_blank">' . e(format_invoice_number($aRow['invoiceid'])) . '</a>';
}
$row[] = $aRow['year'];
$row[] = e(_d($aRow['date']));
$row[] = e(_d($aRow['expirydate']));
$row[] = e(app_format_money($aRow['subtotal'], $currency->name));
$footer_data['subtotal'] += $aRow['subtotal'];
$row[] = e(app_format_money($aRow['total'], $currency->name));
$footer_data['total'] += $aRow['total'];
$row[] = e(app_format_money($aRow['total_tax'], $currency->name));
$footer_data['total_tax'] += $aRow['total_tax'];
$t = $totalTaxesColumns - 1;
$i = 0;
foreach ($estimateTaxes as $tax) {
$row[] = e(app_format_money(($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]), $currency->name));
$footer_data['total_tax_single_' . $i] += ($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]);
$t--;
$i++;
}
$row[] = e(app_format_money($aRow['discount_total'], $currency->name));
$footer_data['discount_total'] += $aRow['discount_total'];
$row[] = e(app_format_money($aRow['adjustment'], $currency->name));
$footer_data['adjustment'] += $aRow['adjustment'];
$row[] = e($aRow['reference_no']);
$row[] = format_estimate_status($aRow['status']);
$output['aaData'][] = $row;
}
foreach ($footer_data as $key => $total) {
$footer_data[$key] = e(app_format_money($total, $currency->name));
}
$output['sums'] = $footer_data;
echo json_encode($output);
die();
}
}
private function get_where_report_period($field = 'date')
{
$months_report = $this->input->post('report_months');
$custom_date_select = '';
if ($months_report != '') {
if (is_numeric($months_report)) {
// Last month
if ($months_report == '1') {
$beginMonth = date('Y-m-01', strtotime('first day of last month'));
$endMonth = date('Y-m-t', strtotime('last day of last month'));
} else {
$months_report = (int) $months_report;
$months_report--;
$beginMonth = date('Y-m-01', strtotime("-$months_report MONTH"));
$endMonth = date('Y-m-t');
}
$custom_date_select = 'AND (' . $field . ' BETWEEN "' . $beginMonth . '" AND "' . $endMonth . '")';
} elseif ($months_report == 'this_month') {
$custom_date_select = 'AND (' . $field . ' BETWEEN "' . date('Y-m-01') . '" AND "' . date('Y-m-t') . '")';
} elseif ($months_report == 'this_year') {
$custom_date_select = 'AND (' . $field . ' BETWEEN "' .
date('Y-m-d', strtotime(date('Y-01-01'))) .
'" AND "' .
date('Y-m-d', strtotime(date('Y-12-31'))) . '")';
} elseif ($months_report == 'last_year') {
$custom_date_select = 'AND (' . $field . ' BETWEEN "' .
date('Y-m-d', strtotime(date(date('Y', strtotime('last year')) . '-01-01'))) .
'" AND "' .
date('Y-m-d', strtotime(date(date('Y', strtotime('last year')) . '-12-31'))) . '")';
} elseif ($months_report == 'custom') {
$from_date = to_sql_date($this->input->post('report_from'));
$to_date = to_sql_date($this->input->post('report_to'));
if ($from_date == $to_date) {
$custom_date_select = 'AND ' . $field . ' = "' . $this->db->escape_str($from_date) . '"';
} else {
$custom_date_select = 'AND (' . $field . ' BETWEEN "' . $this->db->escape_str($from_date) . '" AND "' . $this->db->escape_str($to_date) . '")';
}
}
}
return $custom_date_select;
}
public function items()
{
if ($this->input->is_ajax_request()) {
$this->load->model('currencies_model');
$v = $this->db->query('SELECT VERSION() as version')->row();
// 5.6 mysql version don't have the ANY_VALUE function implemented.
if ($v && strpos($v->version, '5.7') !== false) {
$aColumns = [
'ANY_VALUE(description) as description',
'ANY_VALUE((SUM(' . db_prefix() . 'itemable.qty))) as quantity_sold',
'ANY_VALUE(SUM(rate*qty)) as rate',
'ANY_VALUE(AVG(rate*qty)) as avg_price',
];
} else {
$aColumns = [
'description as description',
'(SUM(' . db_prefix() . 'itemable.qty)) as quantity_sold',
'SUM(rate*qty) as rate',
'AVG(rate*qty) as avg_price',
];
}
$sIndexColumn = 'id';
$sTable = db_prefix() . 'itemable';
$join = ['JOIN ' . db_prefix() . 'invoices ON ' . db_prefix() . 'invoices.id = ' . db_prefix() . 'itemable.rel_id'];
$where = ['AND rel_type="invoice"', 'AND status != 5', 'AND status=2'];
$custom_date_select = $this->get_where_report_period();
if ($custom_date_select != '') {
array_push($where, $custom_date_select);
}
$by_currency = $this->input->post('report_currency');
if ($by_currency) {
$currency = $this->currencies_model->get($by_currency);
array_push($where, 'AND currency=' . $this->db->escape_str($by_currency));
} else {
$currency = $this->currencies_model->get_base_currency();
}
if ($this->input->post('sale_agent_items')) {
$agents = $this->input->post('sale_agent_items');
$_agents = [];
if (is_array($agents)) {
foreach ($agents as $agent) {
if ($agent != '') {
array_push($_agents, $this->db->escape_str($agent));
}
}
}
if (count($_agents) > 0) {
array_push($where, 'AND sale_agent IN (' . implode(', ', $_agents) . ')');
}
}
$result = data_tables_init($aColumns, $sIndexColumn, $sTable, $join, $where, [], 'GROUP by description');
$output = $result['output'];
$rResult = $result['rResult'];
$footer_data = [
'total_amount' => 0,
'total_qty' => 0,
];
foreach ($rResult as $aRow) {
$row = [];
$row[] = e($aRow['description']);
$row[] = $aRow['quantity_sold'];
$row[] = e(app_format_money($aRow['rate'], $currency->name));
$row[] = e(app_format_money($aRow['avg_price'], $currency->name));
$footer_data['total_amount'] += $aRow['rate'];
$footer_data['total_qty'] += $aRow['quantity_sold'];
$output['aaData'][] = $row;
}
$footer_data['total_amount'] = e(app_format_money($footer_data['total_amount'], $currency->name));
$output['sums'] = $footer_data;
echo json_encode($output);
die();
}
}
public function credit_notes()
{
if ($this->input->is_ajax_request()) {
$credit_note_taxes = $this->distinct_taxes('credit_note');
$totalTaxesColumns = count($credit_note_taxes);
$this->load->model('currencies_model');
$select = [
'number',
'date',
get_sql_select_client_company(),
'reference_no',
'subtotal',
'total',
'total_tax',
'discount_total',
'adjustment',
'(SELECT ' . db_prefix() . 'creditnotes.total - (
(SELECT COALESCE(SUM(amount),0) FROM ' . db_prefix() . 'credits WHERE ' . db_prefix() . 'credits.credit_id=' . db_prefix() . 'creditnotes.id)
+
(SELECT COALESCE(SUM(amount),0) FROM ' . db_prefix() . 'creditnote_refunds WHERE ' . db_prefix() . 'creditnote_refunds.credit_note_id=' . db_prefix() . 'creditnotes.id)
)
) as remaining_amount',
'(SELECT SUM(amount) FROM ' . db_prefix() . 'creditnote_refunds WHERE credit_note_id=' . db_prefix() . 'creditnotes.id) as refund_amount',
'status',
];
$where = [];
$credit_note_taxes_select = array_reverse($credit_note_taxes);
foreach ($credit_note_taxes_select as $key => $tax) {
array_splice($select, 5, 0, '(
SELECT CASE
WHEN discount_percent != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * discount_percent/100)),' . get_decimal_places() . ')
WHEN discount_total != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * (discount_total/subtotal*100) / 100)),' . get_decimal_places() . ')
ELSE ROUND(SUM(qty*rate/100*' . db_prefix() . 'item_tax.taxrate),' . get_decimal_places() . ')
END
FROM ' . db_prefix() . 'itemable
INNER JOIN ' . db_prefix() . 'item_tax ON ' . db_prefix() . 'item_tax.itemid=' . db_prefix() . 'itemable.id
WHERE ' . db_prefix() . 'itemable.rel_type="credit_note" AND taxname="' . $tax['taxname'] . '" AND taxrate="' . $tax['taxrate'] . '" AND ' . db_prefix() . 'itemable.rel_id=' . db_prefix() . 'creditnotes.id) as total_tax_single_' . $key);
}
$custom_date_select = $this->get_where_report_period();
if ($custom_date_select != '') {
array_push($where, $custom_date_select);
}
$by_currency = $this->input->post('report_currency');
if ($by_currency) {
$currency = $this->currencies_model->get($by_currency);
array_push($where, 'AND currency=' . $this->db->escape_str($by_currency));
} else {
$currency = $this->currencies_model->get_base_currency();
}
if ($this->input->post('credit_note_status')) {
$statuses = $this->input->post('credit_note_status');
$_statuses = [];
if (is_array($statuses)) {
foreach ($statuses as $status) {
if ($status != '') {
array_push($_statuses, $this->db->escape_str($status));
}
}
}
if (count($_statuses) > 0) {
array_push($where, 'AND status IN (' . implode(', ', $_statuses) . ')');
}
}
$aColumns = $select;
$sIndexColumn = 'id';
$sTable = db_prefix() . 'creditnotes';
$join = [
'LEFT JOIN ' . db_prefix() . 'clients ON ' . db_prefix() . 'clients.userid = ' . db_prefix() . 'creditnotes.clientid',
];
$result = data_tables_init($aColumns, $sIndexColumn, $sTable, $join, $where, [
'userid',
'clientid',
db_prefix() . 'creditnotes.id',
'discount_percent',
'deleted_customer_name',
]);
$output = $result['output'];
$rResult = $result['rResult'];
$footer_data = [
'total' => 0,
'subtotal' => 0,
'total_tax' => 0,
'discount_total' => 0,
'adjustment' => 0,
'remaining_amount' => 0,
'refund_amount' => 0,
];
foreach ($credit_note_taxes as $key => $tax) {
$footer_data['total_tax_single_' . $key] = 0;
}
foreach ($rResult as $aRow) {
$row = [];
$row[] = '<a href="' . admin_url('credit_notes/list_credit_notes/' . $aRow['id']) . '" target="_blank">' . e(format_credit_note_number($aRow['id'])) . '</a>';
$row[] = e(_d($aRow['date']));
if (empty($aRow['deleted_customer_name'])) {
$row[] = '<a href="' . admin_url('clients/client/' . $aRow['clientid']) . '">' . e($aRow['company']) . '</a>';
} else {
$row[] = e($aRow['deleted_customer_name']);
}
$row[] = e($aRow['reference_no']);
$row[] = e(app_format_money($aRow['subtotal'], $currency->name));
$footer_data['subtotal'] += $aRow['subtotal'];
$row[] = e(app_format_money($aRow['total'], $currency->name));
$footer_data['total'] += $aRow['total'];
$row[] = e(app_format_money($aRow['total_tax'], $currency->name));
$footer_data['total_tax'] += $aRow['total_tax'];
$t = $totalTaxesColumns - 1;
$i = 0;
foreach ($credit_note_taxes as $tax) {
$row[] = e(app_format_money(($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]), $currency->name));
$footer_data['total_tax_single_' . $i] += ($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]);
$t--;
$i++;
}
$row[] = e(app_format_money($aRow['discount_total'], $currency->name));
$footer_data['discount_total'] += $aRow['discount_total'];
$row[] = e(app_format_money($aRow['adjustment'], $currency->name));
$footer_data['adjustment'] += $aRow['adjustment'];
$row[] = e(app_format_money($aRow['remaining_amount'], $currency->name));
$footer_data['remaining_amount'] += $aRow['remaining_amount'];
$row[] = e(app_format_money($aRow['refund_amount'], $currency->name));
$footer_data['refund_amount'] += $aRow['refund_amount'];
$row[] = format_credit_note_status($aRow['status']);
$output['aaData'][] = $row;
}
foreach ($footer_data as $key => $total) {
$footer_data[$key] = e(app_format_money($total, $currency->name));
}
$output['sums'] = $footer_data;
echo json_encode($output);
die();
}
}
public function invoices_report()
{
if ($this->input->is_ajax_request()) {
$invoice_taxes = $this->distinct_taxes('invoice');
$totalTaxesColumns = count($invoice_taxes);
$this->load->model('currencies_model');
$this->load->model('invoices_model');
$select = [
'number',
get_sql_select_client_company(),
'YEAR(date) as year',
'date',
'duedate',
'subtotal',
'total',
'total_tax',
'discount_total',
'adjustment',
'(SELECT COALESCE(SUM(amount),0) FROM ' . db_prefix() . 'credits WHERE ' . db_prefix() . 'credits.invoice_id=' . db_prefix() . 'invoices.id) as credits_applied',
'(SELECT total - (SELECT COALESCE(SUM(amount),0) FROM ' . db_prefix() . 'invoicepaymentrecords WHERE invoiceid = ' . db_prefix() . 'invoices.id) - (SELECT COALESCE(SUM(amount),0) FROM ' . db_prefix() . 'credits WHERE ' . db_prefix() . 'credits.invoice_id=' . db_prefix() . 'invoices.id))',
'status',
];
$where = [
'AND status != 5',
];
$invoiceTaxesSelect = array_reverse($invoice_taxes);
foreach ($invoiceTaxesSelect as $key => $tax) {
array_splice($select, 8, 0, '(
SELECT CASE
WHEN discount_percent != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * discount_percent/100)),' . get_decimal_places() . ')
WHEN discount_total != 0 AND discount_type = "before_tax" THEN ROUND(SUM((qty*rate/100*' . db_prefix() . 'item_tax.taxrate) - (qty*rate/100*' . db_prefix() . 'item_tax.taxrate * (discount_total/subtotal*100) / 100)),' . get_decimal_places() . ')
ELSE ROUND(SUM(qty*rate/100*' . db_prefix() . 'item_tax.taxrate),' . get_decimal_places() . ')
END
FROM ' . db_prefix() . 'itemable
INNER JOIN ' . db_prefix() . 'item_tax ON ' . db_prefix() . 'item_tax.itemid=' . db_prefix() . 'itemable.id
WHERE ' . db_prefix() . 'itemable.rel_type="invoice" AND taxname="' . $tax['taxname'] . '" AND taxrate="' . $tax['taxrate'] . '" AND ' . db_prefix() . 'itemable.rel_id=' . db_prefix() . 'invoices.id) as total_tax_single_' . $key);
}
$custom_date_select = $this->get_where_report_period();
if ($custom_date_select != '') {
array_push($where, $custom_date_select);
}
if ($this->input->post('sale_agent_invoices')) {
$agents = $this->input->post('sale_agent_invoices');
$_agents = [];
if (is_array($agents)) {
foreach ($agents as $agent) {
if ($agent != '') {
array_push($_agents, $this->db->escape_str($agent));
}
}
}
if (count($_agents) > 0) {
array_push($where, 'AND sale_agent IN (' . implode(', ', $_agents) . ')');
}
}
$by_currency = $this->input->post('report_currency');
$totalPaymentsColumnIndex = (12 + $totalTaxesColumns - 1);
if ($by_currency) {
$_temp = substr($select[$totalPaymentsColumnIndex], 0, -2);
$_temp .= ' AND currency =' . $by_currency . ')) as amount_open';
$select[$totalPaymentsColumnIndex] = $_temp;
$currency = $this->currencies_model->get($by_currency);
array_push($where, 'AND currency=' . $this->db->escape_str($by_currency));
} else {
$currency = $this->currencies_model->get_base_currency();
$select[$totalPaymentsColumnIndex] = $select[$totalPaymentsColumnIndex] .= ' as amount_open';
}
if ($this->input->post('invoice_status')) {
$statuses = $this->input->post('invoice_status');
$_statuses = [];
if (is_array($statuses)) {
foreach ($statuses as $status) {
if ($status != '') {
array_push($_statuses, $this->db->escape_str($status));
}
}
}
if (count($_statuses) > 0) {
array_push($where, 'AND status IN (' . implode(', ', $_statuses) . ')');
}
}
$aColumns = $select;
$sIndexColumn = 'id';
$sTable = db_prefix() . 'invoices';
$join = [
'LEFT JOIN ' . db_prefix() . 'clients ON ' . db_prefix() . 'clients.userid = ' . db_prefix() . 'invoices.clientid',
];
$result = data_tables_init($aColumns, $sIndexColumn, $sTable, $join, $where, [
'userid',
'clientid',
db_prefix() . 'invoices.id',
'discount_percent',
'deleted_customer_name',
]);
$output = $result['output'];
$rResult = $result['rResult'];
$footer_data = [
'total' => 0,
'subtotal' => 0,
'total_tax' => 0,
'discount_total' => 0,
'adjustment' => 0,
'applied_credits' => 0,
'amount_open' => 0,
];
foreach ($invoice_taxes as $key => $tax) {
$footer_data['total_tax_single_' . $key] = 0;
}
foreach ($rResult as $aRow) {
$row = [];
$row[] = '<a href="' . admin_url('invoices/list_invoices/' . $aRow['id']) . '" target="_blank">' . e(format_invoice_number($aRow['id'])) . '</a>';
if (empty($aRow['deleted_customer_name'])) {
$row[] = '<a href="' . admin_url('clients/client/' . $aRow['userid']) . '" target="_blank">' . e($aRow['company']) . '</a>';
} else {
$row[] = e($aRow['deleted_customer_name']);
}
$row[] = $aRow['year'];
$row[] = e(_d($aRow['date']));
$row[] = e(_d($aRow['duedate']));
$row[] = e(app_format_money($aRow['subtotal'], $currency->name));
$footer_data['subtotal'] += $aRow['subtotal'];
$row[] = e(app_format_money($aRow['total'], $currency->name));
$footer_data['total'] += $aRow['total'];
$row[] = e(app_format_money($aRow['total_tax'], $currency->name));
$footer_data['total_tax'] += $aRow['total_tax'];
$t = $totalTaxesColumns - 1;
$i = 0;
foreach ($invoice_taxes as $tax) {
$row[] = e(app_format_money(($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]), $currency->name));
$footer_data['total_tax_single_' . $i] += ($aRow['total_tax_single_' . $t] == null ? 0 : $aRow['total_tax_single_' . $t]);
$t--;
$i++;
}
$row[] = e(app_format_money($aRow['discount_total'], $currency->name));
$footer_data['discount_total'] += $aRow['discount_total'];
$row[] = e(app_format_money($aRow['adjustment'], $currency->name));
$footer_data['adjustment'] += $aRow['adjustment'];
$row[] = e(app_format_money($aRow['credits_applied'], $currency->name));
$footer_data['applied_credits'] += $aRow['credits_applied'];
$amountOpen = $aRow['amount_open'];
$row[] = e(app_format_money($amountOpen, $currency->name));
$footer_data['amount_open'] += $amountOpen;
$row[] = format_invoice_status($aRow['status']);
$output['aaData'][] = $row;
}
foreach ($footer_data as $key => $total) {
$footer_data[$key] = e(app_format_money($total, $currency->name));
}
$output['sums'] = $footer_data;
echo json_encode($output);
die();
}
}
public function expenses($type = 'simple_report')
{
$this->load->model('currencies_model');
$data['base_currency'] = $this->currencies_model->get_base_currency();
$data['currencies'] = $this->currencies_model->get();
$data['title'] = _l('expenses_report');
if ($type != 'simple_report') {
$this->load->model('expenses_model');
$data['categories'] = $this->expenses_model->get_category();
$data['years'] = $this->expenses_model->get_expenses_years();
$data['table'] = App_table::find('expenses_detailed_report');
$this->load->model('payment_modes_model');
$data['payment_modes'] = $this->payment_modes_model->get('', [], true);
if ($this->input->is_ajax_request()) {
$data['table']->output([
'base_currency'=>$data['base_currency'],
'currencies'=>$data['currencies'],
]);
}
$this->load->view('admin/reports/expenses_detailed', $data);
} else {
if (!$this->input->get('year')) {
$data['current_year'] = date('Y');
} else {
$data['current_year'] = $this->input->get('year');
}
$data['export_not_supported'] = ($this->agent->browser() == 'Internet Explorer' || $this->agent->browser() == 'Spartan');
$this->load->model('expenses_model');
$data['chart_not_billable'] = json_encode($this->reports_model->get_stats_chart_data(_l('not_billable_expenses_by_categories'), [
'billable' => 0,
], [
'backgroundColor' => 'rgba(252,45,66,0.4)',
'borderColor' => '#fc2d42',
], $data['current_year']));
$data['chart_billable'] = json_encode($this->reports_model->get_stats_chart_data(_l('billable_expenses_by_categories'), [
'billable' => 1,
], [
'backgroundColor' => 'rgba(37,155,35,0.2)',
'borderColor' => '#84c529',
], $data['current_year']));
$data['expense_years'] = $this->expenses_model->get_expenses_years();
if (count($data['expense_years']) > 0) {
// Perhaps no expenses in new year?
if (!in_array_multidimensional($data['expense_years'], 'year', date('Y'))) {
array_unshift($data['expense_years'], ['year' => date('Y')]);
}
}
$data['categories'] = $this->expenses_model->get_category();
$this->load->view('admin/reports/expenses', $data);
}
}
public function expenses_vs_income($year = '')
{
$_expenses_years = [];
$_years = [];
$this->load->model('expenses_model');
$expenses_years = $this->expenses_model->get_expenses_years();
$payments_years = $this->reports_model->get_distinct_payments_years();
foreach ($expenses_years as $y) {
array_push($_years, $y['year']);
}
foreach ($payments_years as $y) {
array_push($_years, $y['year']);
}
$_years = array_map('unserialize', array_unique(array_map('serialize', $_years)));
if (!in_array(date('Y'), $_years)) {
$_years[] = date('Y');
}
rsort($_years, SORT_NUMERIC);
$data['report_year'] = $year == '' ? date('Y') : $year;
$data['years'] = $_years;
$data['chart_expenses_vs_income_values'] = json_encode($this->reports_model->get_expenses_vs_income_report($year));
$data['base_currency'] = get_base_currency();
$data['title'] = _l('als_expenses_vs_income');
$this->load->view('admin/reports/expenses_vs_income', $data);
}
/* Total income report / ajax chart*/
public function total_income_report()
{
echo json_encode($this->reports_model->total_income_report());
}
public function report_by_payment_modes()
{
echo json_encode($this->reports_model->report_by_payment_modes());
}
public function report_by_customer_groups()
{
echo json_encode($this->reports_model->report_by_customer_groups());
}
/* Leads conversion monthly report / ajax chart*/
public function leads_monthly_report($month)
{
echo json_encode($this->reports_model->leads_monthly_report($month));
}
private function distinct_taxes($rel_type)
{
return $this->db->query('SELECT DISTINCT taxname,taxrate FROM ' . db_prefix() . "item_tax WHERE rel_type='" . $rel_type . "' ORDER BY taxname ASC")->result_array();
}
}