From e0701ea094c5bbc204ed74604b7cf84b59ca497d Mon Sep 17 00:00:00 2001 From: Pradesh Chanderpaul Date: Mon, 8 Oct 2018 15:22:21 +0200 Subject: [PATCH 1/7] New statement module code --- application/language/english/ip_lang.php | 9 + .../clients/views/partial_client_table.php | 5 + .../modules/invoices/models/Mdl_invoices.php | 22 + .../modules/payments/models/Mdl_payments.php | 22 + .../modules/statements/controllers/Ajax.php | 421 ++++++++++++++++++ .../statements/controllers/Statements.php | 365 +++++++++++++++ .../statements/models/Mdl_statement.php | 138 ++++++ .../modules/statements/views/index.php | 103 +++++ .../statements/views/partial_item_table.php | 112 +++++ .../views/statement_templates/pdf/.gitignore | 3 + .../statement_templates/pdf/InvoicePlane.php | 191 ++++++++ .../statement_templates/public/.gitignore | 3 + application/modules/statements/views/view.php | 222 +++++++++ 13 files changed, 1616 insertions(+) create mode 100644 application/modules/statements/controllers/Ajax.php create mode 100644 application/modules/statements/controllers/Statements.php create mode 100644 application/modules/statements/models/Mdl_statement.php create mode 100644 application/modules/statements/views/index.php create mode 100644 application/modules/statements/views/partial_item_table.php create mode 100644 application/modules/statements/views/statement_templates/pdf/.gitignore create mode 100644 application/modules/statements/views/statement_templates/pdf/InvoicePlane.php create mode 100644 application/modules/statements/views/statement_templates/public/.gitignore create mode 100644 application/modules/statements/views/view.php diff --git a/application/language/english/ip_lang.php b/application/language/english/ip_lang.php index 705638552a..6f70461aa2 100644 --- a/application/language/english/ip_lang.php +++ b/application/language/english/ip_lang.php @@ -260,6 +260,7 @@ 'invoice_items' => 'Invoice Items', 'invoice_logo' => 'Invoice Logo', 'invoice_not_found' => 'Invoice Not Found', + 'invoice_number' => 'Invoice Number', 'invoice_overview' => 'Invoice Overview', 'invoice_overview_period' => 'Invoice Overview Period', 'invoice_password' => 'PDF password (optional)', @@ -272,6 +273,7 @@ 'invoice_tax_rate' => 'Invoice Tax Rate', 'invoice_template' => 'Invoice Template', 'invoice_terms' => 'Invoice Terms', + 'invoice_total' => 'Invoice Total', 'invoiced' => 'Invoiced', 'invoiceplane_news' => 'InvoicePlane News', 'invoices' => 'Invoices', @@ -436,6 +438,7 @@ 'record_successfully_updated' => 'Record successfully updated', 'recurring' => 'Recurring', 'recurring_invoices' => 'Recurring Invoices', + 'reference' => 'Reference', 'reject' => 'Reject', 'reject_this_quote' => 'Reject This Quote', 'rejected' => 'Rejected', @@ -512,6 +515,11 @@ 'sql_file' => 'SQL File', 'start_date' => 'Start Date', 'state' => 'State', + 'statement' => 'Statement', + 'statement_date' => 'Statement Date', + 'statement_end_date' => 'Statement End Date', + 'statement_number' => 'Statement Number', + 'statement_start_date' => 'Statement Start Date', 'status' => 'Status', 'stop' => 'Stop', 'street_address' => 'Street Address', @@ -550,6 +558,7 @@ 'total_balance' => 'Total Balance', 'total_billed' => 'Total Billed', 'total_paid' => 'Total Paid', + 'transaction_type' => 'Transaction Type', 'try_again' => 'Try Again', 'type' => 'Type', 'unknown' => 'Unknown', diff --git a/application/modules/clients/views/partial_client_table.php b/application/modules/clients/views/partial_client_table.php index a82aec30cc..d278a206aa 100644 --- a/application/modules/clients/views/partial_client_table.php +++ b/application/modules/clients/views/partial_client_table.php @@ -56,6 +56,11 @@ +
  • + + + +
  • diff --git a/application/modules/invoices/models/Mdl_invoices.php b/application/modules/invoices/models/Mdl_invoices.php index 57d7d360ae..b35210e038 100644 --- a/application/modules/invoices/models/Mdl_invoices.php +++ b/application/modules/invoices/models/Mdl_invoices.php @@ -525,6 +525,28 @@ public function by_client($client_id) $this->filter_where('ip_invoices.client_id', $client_id); return $this; } + + /** + * Filter query in a date range. + * The filter can be open ended on one end by not supplied a value + * Dates must be in unixtime format + * + * @param time $start_date + * @param time $end_date + * @return Mdl_Invoices + */ + public function by_date_range($start_date = null, $end_date = null) + { + + if (!empty($start_date)) { + $this->filter_where("invoice_date_created >= '" . date('Y-m-d', $start_date) . "' "); + } + if (!empty($end_date)) { + $this->filter_where("invoice_date_created <= '" . date('Y-m-d', $end_date) . "' "); + } + + return $this; + } /** * @param $invoice_id diff --git a/application/modules/payments/models/Mdl_payments.php b/application/modules/payments/models/Mdl_payments.php index 4c8323d455..b04c1a3ac2 100755 --- a/application/modules/payments/models/Mdl_payments.php +++ b/application/modules/payments/models/Mdl_payments.php @@ -222,5 +222,27 @@ public function by_client($client_id) $this->filter_where('ip_clients.client_id', $client_id); return $this; } + + /** + * Filter query in a date range. + * The filter can be open ended on one end by not supplied a value + * Dates must be in unixtime format + * + * @param time $start_date + * @param time $end_date + * @return Mdl_Payments + */ + public function by_date_range($start_date = null, $end_date = null) + { + + if (!empty($start_date)) { + $this->filter_where("invoice_date_modified >= '" . date('Y-m-d', $start_date) . "' "); + } + if (!empty($end_date)) { + $this->filter_where("invoice_date_modified <= '" . date('Y-m-d', $end_date) . "' "); + } + + return $this; + } } diff --git a/application/modules/statements/controllers/Ajax.php b/application/modules/statements/controllers/Ajax.php new file mode 100644 index 0000000000..6b948ad213 --- /dev/null +++ b/application/modules/statements/controllers/Ajax.php @@ -0,0 +1,421 @@ +load->model('quotes/mdl_quote_items'); + $this->load->model('quotes/mdl_quotes'); + $this->load->model('units/mdl_units'); + + $quote_id = $this->input->post('quote_id'); + + $this->mdl_quotes->set_id($quote_id); + + if ($this->mdl_quotes->run_validation('validation_rules_save_quote')) { + $items = json_decode($this->input->post('items')); + + foreach ($items as $item) { + if ($item->item_name) { + $item->item_quantity = ($item->item_quantity ? standardize_amount($item->item_quantity) : floatval(0)); + $item->item_price = ($item->item_quantity ? standardize_amount($item->item_price) : floatval(0)); + $item->item_discount_amount = ($item->item_discount_amount) ? standardize_amount($item->item_discount_amount) : null; + $item->item_product_id = ($item->item_product_id ? $item->item_product_id : null); + $item->item_product_unit_id = ($item->item_product_unit_id ? $item->item_product_unit_id : null); + $item->item_product_unit = $this->mdl_units->get_name($item->item_product_unit_id, $item->item_quantity); + + $item_id = ($item->item_id) ?: null; + unset($item->item_id); + + $this->mdl_quote_items->save($item_id, $item); + } + } + + if ($this->input->post('quote_discount_amount') === '') { + $quote_discount_amount = floatval(0); + } else { + $quote_discount_amount = $this->input->post('quote_discount_amount'); + } + + if ($this->input->post('quote_discount_percent') === '') { + $quote_discount_percent = floatval(0); + } else { + $quote_discount_percent = $this->input->post('quote_discount_percent'); + } + + // Generate new quote number if needed + $quote_number = $this->input->post('quote_number'); + $quote_status_id = $this->input->post('quote_status_id'); + + if (empty($quote_number) && $quote_status_id != 1) { + $quote_group_id = $this->mdl_quotes->get_invoice_group_id($quote_id); + $quote_number = $this->mdl_quotes->get_quote_number($quote_group_id); + } + + $db_array = [ + 'quote_number' => $quote_number, + 'quote_date_created' => date_to_mysql($this->input->post('quote_date_created')), + 'quote_date_expires' => date_to_mysql($this->input->post('quote_date_expires')), + 'quote_status_id' => $quote_status_id, + 'quote_password' => $this->input->post('quote_password'), + 'notes' => $this->input->post('notes'), + 'quote_discount_amount' => standardize_amount($quote_discount_amount), + 'quote_discount_percent' => standardize_amount($quote_discount_percent), + ]; + + $this->mdl_quotes->save($quote_id, $db_array); + + // Recalculate for discounts + $this->load->model('quotes/mdl_quote_amounts'); + $this->mdl_quote_amounts->calculate($quote_id); + + $response = [ + 'success' => 1, + ]; + } else { + $this->load->helper('json_error'); + $response = [ + 'success' => 0, + 'validation_errors' => json_errors(), + ]; + } + + + // Save all custom fields + if ($this->input->post('custom')) { + $db_array = []; + + $values = []; + foreach ($this->input->post('custom') as $custom) { + if (preg_match("/^(.*)\[\]$/i", $custom['name'], $matches)) { + $values[$matches[1]][] = $custom['value']; + } else { + $values[$custom['name']] = $custom['value']; + } + } + + foreach ($values as $key => $value) { + preg_match("/^custom\[(.*?)\](?:\[\]|)$/", $key, $matches); + if ($matches) { + $db_array[$matches[1]] = $value; + } + } + $this->load->model('custom_fields/mdl_quote_custom'); + $result = $this->mdl_quote_custom->save_custom($quote_id, $db_array); + if ($result !== true) { + $response = [ + 'success' => 0, + 'validation_errors' => $result, + ]; + + echo json_encode($response); + exit; + } + } + + echo json_encode($response); + } + + public function save_quote_tax_rate() + { + $this->load->model('quotes/mdl_quote_tax_rates'); + + if ($this->mdl_quote_tax_rates->run_validation()) { + $this->mdl_quote_tax_rates->save(); + + $response = [ + 'success' => 1, + ]; + } else { + $response = [ + 'success' => 0, + 'validation_errors' => $this->mdl_quote_tax_rates->validation_errors, + ]; + } + + echo json_encode($response); + } + + public function create() + { + $this->load->model('quotes/mdl_quotes'); + + if ($this->mdl_quotes->run_validation()) { + $quote_id = $this->mdl_quotes->create(); + + $response = [ + 'success' => 1, + 'quote_id' => $quote_id, + ]; + } else { + $this->load->helper('json_error'); + $response = [ + 'success' => 0, + 'validation_errors' => json_errors(), + ]; + } + + echo json_encode($response); + } + + public function modal_change_client() + { + $this->load->module('layout'); + $this->load->model('clients/mdl_clients'); + + $data = [ + 'client_id' => $this->input->post('client_id'), + 'quote_id' => $this->input->post('quote_id'), + 'clients' => $this->mdl_clients->get_latest(), + ]; + + $this->layout->load_view('quotes/modal_change_client', $data); + } + + public function change_client() + { + $this->load->model('quotes/mdl_quotes'); + $this->load->model('clients/mdl_clients'); + + // Get the client ID + $client_id = $this->input->post('client_id'); + $client = $this->mdl_clients->where('ip_clients.client_id', $client_id) + ->get()->row(); + + if (!empty($client)) { + $quote_id = $this->input->post('quote_id'); + + $db_array = [ + 'client_id' => $client_id, + ]; + $this->db->where('quote_id', $quote_id); + $this->db->update('ip_quotes', $db_array); + + $response = [ + 'success' => 1, + 'quote_id' => $quote_id, + ]; + } else { + $this->load->helper('json_error'); + $response = [ + 'success' => 0, + 'validation_errors' => json_errors(), + ]; + } + + echo json_encode($response); + } + + public function get_item() + { + $this->load->model('quotes/mdl_quote_items'); + + $item = $this->mdl_quote_items->get_by_id($this->input->post('item_id')); + + echo json_encode($item); + } + + public function modal_create_quote() + { + $this->load->module('layout'); + $this->load->model('invoice_groups/mdl_invoice_groups'); + $this->load->model('tax_rates/mdl_tax_rates'); + $this->load->model('clients/mdl_clients'); + + $data = [ + 'invoice_groups' => $this->mdl_invoice_groups->get()->result(), + 'tax_rates' => $this->mdl_tax_rates->get()->result(), + 'client' => $this->mdl_clients->get_by_id($this->input->post('client_id')), + 'clients' => $this->mdl_clients->get_latest(), + ]; + + $this->layout->load_view('quotes/modal_create_quote', $data); + } + + public function modal_copy_quote() + { + $this->load->module('layout'); + + $this->load->model('quotes/mdl_quotes'); + $this->load->model('invoice_groups/mdl_invoice_groups'); + $this->load->model('tax_rates/mdl_tax_rates'); + $this->load->model('clients/mdl_clients'); + + $data = [ + 'invoice_groups' => $this->mdl_invoice_groups->get()->result(), + 'tax_rates' => $this->mdl_tax_rates->get()->result(), + 'quote_id' => $this->input->post('quote_id'), + 'quote' => $this->mdl_quotes->where('ip_quotes.quote_id', $this->input->post('quote_id'))->get()->row(), + 'client' => $this->mdl_clients->get_by_id($this->input->post('client_id')), + ]; + + $this->layout->load_view('quotes/modal_copy_quote', $data); + } + + public function copy_quote() + { + $this->load->model('quotes/mdl_quotes'); + $this->load->model('quotes/mdl_quote_items'); + $this->load->model('quotes/mdl_quote_tax_rates'); + + if ($this->mdl_quotes->run_validation()) { + $target_id = $this->mdl_quotes->save(); + $source_id = $this->input->post('quote_id'); + + $this->mdl_quotes->copy_quote($source_id, $target_id); + + $response = [ + 'success' => 1, + 'quote_id' => $target_id, + ]; + } else { + $this->load->helper('json_error'); + $response = [ + 'success' => 0, + 'validation_errors' => json_errors(), + ]; + } + + echo json_encode($response); + } + + public function modal_quote_to_invoice($quote_id) + { + $this->load->model('invoice_groups/mdl_invoice_groups'); + $this->load->model('quotes/mdl_quotes'); + + $data = [ + 'invoice_groups' => $this->mdl_invoice_groups->get()->result(), + 'quote_id' => $quote_id, + 'quote' => $this->mdl_quotes->where('ip_quotes.quote_id', $quote_id)->get()->row(), + ]; + + $this->load->view('quotes/modal_quote_to_invoice', $data); + } + + public function quote_to_invoice() + { + $this->load->model( + [ + 'invoices/mdl_invoices', + 'invoices/mdl_items', + 'quotes/mdl_quotes', + 'quotes/mdl_quote_items', + 'invoices/mdl_invoice_tax_rates', + 'quotes/mdl_quote_tax_rates', + ] + ); + + if ($this->mdl_invoices->run_validation()) { + // Get the quote + $quote = $this->mdl_quotes->get_by_id($this->input->post('quote_id')); + + $invoice_id = $this->mdl_invoices->create(null, false); + + // Update the discounts + $this->db->where('invoice_id', $invoice_id); + $this->db->set('invoice_discount_amount', $quote->quote_discount_amount); + $this->db->set('invoice_discount_percent', $quote->quote_discount_percent); + $this->db->update('ip_invoices'); + + // Save the invoice id to the quote + $this->db->where('quote_id', $this->input->post('quote_id')); + $this->db->set('invoice_id', $invoice_id); + $this->db->update('ip_quotes'); + + $quote_items = $this->mdl_quote_items->where('quote_id', $this->input->post('quote_id'))->get()->result(); + + foreach ($quote_items as $quote_item) { + $db_array = [ + 'invoice_id' => $invoice_id, + 'item_tax_rate_id' => $quote_item->item_tax_rate_id, + 'item_product_id' => $quote_item->item_product_id, + 'item_name' => $quote_item->item_name, + 'item_description' => $quote_item->item_description, + 'item_quantity' => $quote_item->item_quantity, + 'item_price' => $quote_item->item_price, + 'item_product_unit_id' => $quote_item->item_product_unit_id, + 'item_product_unit' => $quote_item->item_product_unit, + 'item_discount_amount' => $quote_item->item_discount_amount, + 'item_order' => $quote_item->item_order, + ]; + + $this->mdl_items->save(null, $db_array); + } + + $quote_tax_rates = $this->mdl_quote_tax_rates->where('quote_id', $this->input->post('quote_id')) + ->get() + ->result(); + + foreach ($quote_tax_rates as $quote_tax_rate) { + $db_array = [ + 'invoice_id' => $invoice_id, + 'tax_rate_id' => $quote_tax_rate->tax_rate_id, + 'include_item_tax' => $quote_tax_rate->include_item_tax, + 'invoice_tax_rate_amount' => $quote_tax_rate->quote_tax_rate_amount, + ]; + + $this->mdl_invoice_tax_rates->save(null, $db_array); + } + + $response = [ + 'success' => 1, + 'invoice_id' => $invoice_id, + ]; + } else { + $this->load->helper('json_error'); + $response = [ + 'success' => 0, + 'validation_errors' => json_errors(), + ]; + } + + echo json_encode($response); + } + + /** + * @param $quote_id + */ + public function delete_item($quote_id) + { + $success = 0; + $item_id = $this->input->post('item_id'); + $this->load->model('mdl_quotes'); + + // Only continue if the invoice exists or no item id was provided + if ($this->mdl_quotes->get_by_id($quote_id) || empty($item_id)) { + + // Delete invoice item + $this->load->model('mdl_quote_items'); + $item = $this->mdl_quote_items->delete($item_id); + + // Check if deletion was successful + if ($item) { + $success = 1; + } + + } + + // Return the response + echo json_encode([ + 'success' => $success, + ]); + } + +} diff --git a/application/modules/statements/controllers/Statements.php b/application/modules/statements/controllers/Statements.php new file mode 100644 index 0000000000..44838002a9 --- /dev/null +++ b/application/modules/statements/controllers/Statements.php @@ -0,0 +1,365 @@ +load->model('mdl_quotes'); + $this->load->model('clients/mdl_clients'); + + } + + public function index($client_id) + { + $this->view($client_id); + } + + /** + * @param $client_id + * + */ + public function view($client_id) + { + + $this->load->model('custom_fields/mdl_client_custom'); + + /* + * Load the client + */ + $client = $this->mdl_clients + ->where('ip_clients.client_id', $client_id) + ->get()->row(); + + if (!$client) { + show_404(); + } + + $custom_fields = $this->mdl_client_custom->get_by_client($client_id)->result(); + + $this->mdl_client_custom->prep_form($client_id); + + if($this->input->method() === 'post') + { + + // We should use the form value if supplied, otherwise the hidden field sdate + $statement_start_date = strtotime($this->input->post('sdate')); + $statement_end_date = strtotime($this->input->post('edate')); + + $statement_number = $this->input->post('statement_number'); + $statement_date = $this->input->post('statement_date_created'); + $notes = $this->input->post('notes'); + + } else { + + $statement_start_date = null; + $statement_end_date = null; + + $statement_number = null; + $statement_date = null; + $notes = null; + + } + + $statement = $this->build_statement($client_id, $statement_start_date, $statement_end_date, $statement_date, $statement_number); + + + // TODO: Send statement number + + $this->layout->set( + array( + + 'client' => $client, + 'statement_start_date' => $statement->getStatement_start_date(), + 'statement_end_date' => $statement->getStatement_end_date(), + 'statement_date' => $statement->getStatement_date(), + 'custom_fields' => $custom_fields, + 'statement_transactions' => $statement->getStatement_transactions(), + 'opening_balance' => $statement->getOpening_balance(), + 'client_total_balance' => $statement->getStatement_balance(), + 'statement_number' => $statement->getStatement_number(), + + ) + ); + + $this->layout->buffer( + array( + array('content', 'statements/view') + ) + ); + + $this->layout->render(); + + } + + /** + * @param client_total_balance + * @param transaction + */ + private function build_statement($client_id, $statement_start_date = null, $statement_end_date = null, $statement_date = null, $statement_number = null) + { + + $this->load->model('mdl_statement'); + + $this->load->model('invoices/mdl_invoices'); + $this->load->model('payments/mdl_payments'); + + if (!empty($statement_number)){ + + $this->mdl_statement->setStatement_number($statement_number); + + } else { + $this->mdl_statement->setStatement_number( 'STM-' . $client_id . '-' . date('ymd')); + } + + /* + * Load the opening balance + */ + // $statement_start_date = strtotime("-1 month"); + if (empty($statement_start_date)) { + $statement_start_date = null; + } + if (empty($statement_end_date)) { + $statement_end_date = strtotime("-6 month"); + } + + + $this->mdl_statement->setStatement_date( (!empty($statement_date)) ? $statement_date : date('Y-m-d')); + + +// $this->mdl_statement->setStatement_start_date($statement_start_date); +// $this->mdl_statement->setStatement_end_date($statement_end_date); + + $client_invoices = $this->mdl_invoices->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); + $client_payments = $this->mdl_payments->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); + + $client_invoice_total = 0; + foreach ($client_invoices as $invoice_entry) { + $client_invoice_total += $invoice_entry->invoice_total; + } + + $client_payment_total = 0; + foreach ($client_payments as $payment_entry) { + $client_payment_total += $payment_entry->payment_amount; + } + + $client_opening_balance = $client_invoice_total - $client_payment_total; + + $this->mdl_statement->setOpening_balance($client_opening_balance); + + + // $statement_start_date = strtotime("-1 month"); + $statement_start_date = strtotime("-6 month"); + $statement_end_date = time(); + + $this->mdl_statement->setStatement_start_date(date('Y-m-d', $statement_start_date)); + $this->mdl_statement->setStatement_end_date(date('Y-m-d', $statement_end_date)); + + /* + * NOTE: These two calls brings back all invoices and payments over the + * ...date range, and we manually sum up the totals + */ + + $client_invoices = $this->mdl_invoices->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); + $client_payments = $this->mdl_payments->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); + + + $statement_transactions = array(); + $client_total_balance = $client_opening_balance; + foreach ($client_invoices as $invoice_entry) { + + $transaction = [ + 'transaction_type' => self::TRANSACTION_TYPE_INVOICE, + 'transaction_date' => $invoice_entry->invoice_date_created, + 'transaction_amount' => $invoice_entry->invoice_total, + + 'invoice_id' => $invoice_entry->invoice_id, + 'client_id' => $invoice_entry->client_id, + 'user_company' => $invoice_entry->user_company, + 'invoice_amount_id' => $invoice_entry->invoice_amount_id, + 'invoice_item_subtotal' => $invoice_entry->invoice_item_subtotal, + 'invoice_item_tax_total' => $invoice_entry->invoice_item_tax_total, + 'invoice_total' => $invoice_entry->invoice_total, + 'invoice_sign' => $invoice_entry->invoice_sign, + 'invoice_status_id' => $invoice_entry->invoice_status_id, + 'invoice_date_created' => $invoice_entry->invoice_date_created, + 'invoice_time_created' => $invoice_entry->invoice_time_created, + 'invoice_number' => $invoice_entry->invoice_number, + ]; + + $client_total_balance += $invoice_entry->invoice_total; + + $statement_transactions[] = $transaction; + + } + + foreach ($client_payments as $payment_entry) { + + $transaction = [ + 'transaction_type' => self::TRANSACTION_TYPE_PAYMENT, + 'transaction_date' => $payment_entry->payment_date, + 'transaction_amount' => $payment_entry->payment_amount, + + + 'invoice_id' => $payment_entry->invoice_id, + 'client_id' => $payment_entry->client_id, + 'invoice_date_created' => $payment_entry->invoice_date_created, + 'invoice_item_subtotal' => $payment_entry->invoice_item_subtotal, + 'invoice_item_tax_total' => $payment_entry->invoice_item_tax_total, + 'invoice_total' => $payment_entry->invoice_total, + 'invoice_sign' => $payment_entry->invoice_sign, + 'invoice_number' => $payment_entry->invoice_number, + 'payment_id' => $payment_entry->payment_id, + 'payment_method_id' => $payment_entry->payment_method_id, + 'payment_method_name' => $payment_entry->payment_method_name, + 'payment_date' => $payment_entry->payment_date, + 'payment_amount' => $payment_entry->payment_amount, + + ]; + + $statement_transactions[] = $transaction; + + $client_total_balance -= $payment_entry->payment_amount; + + } + + usort($statement_transactions, array($this, "compare_statement_dates")); + + $this->mdl_statement->setStatement_transactions($statement_transactions); + + $this->mdl_statement->setStatement_balance($client_total_balance); + + + return $this->mdl_statement; + + } + + + + + /** + */ + public function generate_pdf() + { + + $client_id = $this->input->post('cid'); + $statement_number = $this->input->post('statement_number'); + + // We should use the form value if supplied, otherwise the hidden field sdate + $statement_start_date = strtotime($this->input->post('sdate')); + $statement_end_date = strtotime($this->input->post('edate')); + + $statement_date = $this->input->post('statement_date_created'); + $notes = $this->input->post('notes'); + + + $this->generate_statement_pdf($client_id, $statement_number, $statement_start_date, $statement_end_date, $statement_date, $notes); + } + + /** + * Generate the PDF for the statement + * + * @param $quote_id + * @param bool $stream + * @param null $quote_template + * + * @return string + * @throws \Mpdf\MpdfException + */ + function generate_statement_pdf($client_id, $statement_number, $statement_start_date, $statement_end_date, $statement_date, $notes) + { + + + $this->load->model('custom_fields/mdl_client_custom'); + + /* + * Load the client + */ + $client = $this->mdl_clients + ->where('ip_clients.client_id', $client_id) + ->get()->row(); + + if (!$client) { + show_404(); + } + + $custom_fields = $this->mdl_client_custom->get_by_client($client_id)->result(); + + $this->mdl_client_custom->prep_form($client_id); + + $statement = $this->build_statement($client_id, $statement_start_date, $statement_end_date); + + // Override language with system language + set_language($client->client_language); + + $statement_template = "InvoicePlane"; + if (!$statement_template) { + $statement_template = $this->mdl_settings->setting('pdf_statement_template'); + } + + $data = array( + 'client' => $client, + 'statement' => $statement, + 'notes' => $notes, + // 'custom_fields' => $custom_fields, + ); + + $html = $this->load->view('statement_templates/pdf/' . $statement_template, $data, true); + + $this->load->helper('mpdf'); + + $pdf_password = null; + $stream = true; + return pdf_create($html, trans('statement') . '_' . str_replace(array('\\', '/'), '_', $statement->GetStatement_number()), $stream, $pdf_password); + } + + + /** + * Compare 2 dates + * + * NOTE: I am not sure if $this is the correct scope for this function. + * + * @param string $a The first date in string format + * @param string $b The second date in string format + * @return number + * 0 is the dates are the same + * 1 if date A > date B + * -1 if date A < date B + */ + private function compare_statement_dates($a, $b) + { + $timeA = strtotime($a['transaction_date']); + $timeB = strtotime($b['transaction_date']); + + if($timeA == $timeB) { + return 0; + } + + return $timeA < $timeB ? -1 : 1; + } + +} diff --git a/application/modules/statements/models/Mdl_statement.php b/application/modules/statements/models/Mdl_statement.php new file mode 100644 index 0000000000..e8942b1dad --- /dev/null +++ b/application/modules/statements/models/Mdl_statement.php @@ -0,0 +1,138 @@ +statement_number; + } + + /** + * @return mixed + */ + public function getStatement_transactions() + { + return $this->statement_transactions; + } + + /** + * @return mixed + */ + public function getStatement_start_date() + { + return $this->statement_start_date; + } + + /** + * @return mixed + */ + public function getStatement_end_date() + { + return $this->statement_end_date; + } + + /** + * @return mixed + */ + public function getStatement_date() + { + return $this->statement_date; + } + + /** + * @return mixed + */ + public function getOpening_balance() + { + return $this->opening_balance; + } + + /** + * @return mixed + */ + public function getStatement_balance() + { + return $this->statement_balance; + } + + /** + * @param mixed $statement_number + */ + public function setStatement_number($statement_number) + { + $this->statement_number = $statement_number; + } + + /** + * @param mixed $statement_transactions + */ + public function setStatement_transactions($statement_transactions) + { + $this->statement_transactions = $statement_transactions; + } + + /** + * @param mixed $statement_start_date + */ + public function setStatement_start_date($statement_start_date) + { + $this->statement_start_date = $statement_start_date; + } + + /** + * @param mixed $statement_end_date + */ + public function setStatement_end_date($statement_end_date) + { + $this->statement_end_date = $statement_end_date; + } + + /** + * @param mixed $statement_date + */ + public function setStatement_date($statement_date) + { + $this->statement_date = $statement_date; + } + + /** + * @param mixed $opening_balance + */ + public function setOpening_balance($opening_balance) + { + $this->opening_balance = $opening_balance; + } + + /** + * @param mixed $statement_balance + */ + public function setStatement_balance($statement_balance) + { + $this->statement_balance = $statement_balance; + } + + public function __construct() + { + parent::__construct(); + } + + + +} \ No newline at end of file diff --git a/application/modules/statements/views/index.php b/application/modules/statements/views/index.php new file mode 100644 index 0000000000..d71c1d11e3 --- /dev/null +++ b/application/modules/statements/views/index.php @@ -0,0 +1,103 @@ +
    + +

    + +
    + + + + +
    + +
    + uri->segment(3)), 'mdl_quotes'); ?> +
    + + + +
    + + + +
    + +
    + layout->load_view('quotes/partial_quote_table', array('quotes' => $quotes)); ?> +
    + +
    diff --git a/application/modules/statements/views/partial_item_table.php b/application/modules/statements/views/partial_item_table.php new file mode 100644 index 0000000000..1fe983d3c2 --- /dev/null +++ b/application/modules/statements/views/partial_item_table.php @@ -0,0 +1,112 @@ + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + + + + + + + +
    +
    +
    + +
    + + +
    + + + +
    + + + + + +
    +
    + +
    diff --git a/application/modules/statements/views/statement_templates/pdf/.gitignore b/application/modules/statements/views/statement_templates/pdf/.gitignore new file mode 100644 index 0000000000..193ab4cca8 --- /dev/null +++ b/application/modules/statements/views/statement_templates/pdf/.gitignore @@ -0,0 +1,3 @@ +* +!InvoicePlane.php +!.gitignore diff --git a/application/modules/statements/views/statement_templates/pdf/InvoicePlane.php b/application/modules/statements/views/statement_templates/pdf/InvoicePlane.php new file mode 100644 index 0000000000..117cfd23f1 --- /dev/null +++ b/application/modules/statements/views/statement_templates/pdf/InvoicePlane.php @@ -0,0 +1,191 @@ + + + + + + <?php _trans('statement') . $statement->getStatement_number(); ?> + + + + +
    + + + +
    +
    + client_name); ?> +
    + client_vat_id) { + echo '
    ' . trans('vat_id_short') . ': ' . $client->client_vat_id . '
    '; + } + if ($client->client_tax_code) { + echo '
    ' . trans('tax_code_short') . ': ' . $client->client_tax_code . '
    '; + } + if ($client->client_address_1) { + echo '
    ' . htmlsc($client->client_address_1) . '
    '; + } + if ($client->client_address_2) { + echo '
    ' . htmlsc($client->client_address_2) . '
    '; + } + if ($client->client_city || $client->client_state || $client->client_zip) { + echo '
    '; + if ($client->client_city) { + echo htmlsc($client->client_city) . ' '; + } + if ($client->client_state) { + echo htmlsc($client->client_state) . ' '; + } + if ($client->client_zip) { + echo htmlsc($client->client_zip); + } + echo '
    '; + } + if ($client->client_state) { + echo '
    ' . htmlsc($client->client_state) . '
    '; + } + if ($client->client_country) { + echo '
    ' . get_country_name(trans('cldr'), $client->client_country) . '
    '; + } + + echo '
    '; + + if ($client->client_phone) { + echo '
    ' . trans('phone_abbr') . ': ' . htmlsc($client->client_phone) . '
    '; + } ?> + +
    + +
    + +
    + +
    + + + + + + + + + + + + + + +
    getStatement_date(), true); ?>
    getStatement_start_date(), true); ?>
    getStatement_end_date(), true); ?>
    +
    + +

    getStatement_number(); ?>

    + + + + + + + + + + + + + + + + getOpening_balance())) { + ?> + + + + + + + + + + + + + GetStatement_transactions() as $transaction) { + + + if ($transaction['transaction_type'] == Statements::TRANSACTION_TYPE_INVOICE) { + $balance += $transaction['transaction_amount']; + } else { + $balance -= $transaction['transaction_amount']; + } + ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + GetStatement_start_date(); ?> + + + + + + + + getOpening_balance()); ?> +
    + + + + + + + + + +
     
    getStatement_balance()); ?>
     
    + +
    + + + + + diff --git a/application/modules/statements/views/statement_templates/public/.gitignore b/application/modules/statements/views/statement_templates/public/.gitignore new file mode 100644 index 0000000000..8a8e758a39 --- /dev/null +++ b/application/modules/statements/views/statement_templates/public/.gitignore @@ -0,0 +1,3 @@ +* +!InvoicePlane_Web.php +!.gitignore diff --git a/application/modules/statements/views/view.php b/application/modules/statements/views/view.php new file mode 100644 index 0000000000..26422315bb --- /dev/null +++ b/application/modules/statements/views/view.php @@ -0,0 +1,222 @@ +controller->view_data["custom_values"]; + +// print_r($quote); +?> + + +
    +

    + +

    + +
    +
    + + + + +
    + +
    + +
    + +
    + layout->load_view('layout/alerts'); ?> +
    + + + + + +
    +
    + +
    +
    + +

    + + + +

    +
    +
    + layout->load_view('clients/partial_client_address', ['client' => $client]); ?> +
    + client_phone || $client->client_email) : ?> +
    + + client_phone): ?> +
    + :  + client_phone); ?> +
    + + client_email): ?> +
    + :  + client_email); ?> +
    + + +
    + +

    + +
    +
    +
    + +
    + +
    + + +
    +
    + +
    + + + + +
    +
    + + + + custom_field_location != 1) { + continue; + } ?> + mdl_quotes, $custom_field, $cv); ?> + + +
    +
    + +
    + +
    + + + + +
    +
    +
    + + +
    + +
    +
    + +
    + +
    + +
    +
    +
    +
    + +
    + + layout->load_view('statements/partial_item_table'); ?> + +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +

    + +
    +
    + +
    +
    +
    From fa8b1a247f3439cda4e5ed50869804c4ae58e25b Mon Sep 17 00:00:00 2001 From: Pradesh Chanderpaul Date: Mon, 8 Oct 2018 16:13:11 +0200 Subject: [PATCH 2/7] Set aefault start time to now - 1 month --- application/modules/statements/controllers/Statements.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/application/modules/statements/controllers/Statements.php b/application/modules/statements/controllers/Statements.php index 44838002a9..11c415d54f 100644 --- a/application/modules/statements/controllers/Statements.php +++ b/application/modules/statements/controllers/Statements.php @@ -139,12 +139,11 @@ private function build_statement($client_id, $statement_start_date = null, $stat /* * Load the opening balance */ - // $statement_start_date = strtotime("-1 month"); if (empty($statement_start_date)) { $statement_start_date = null; } if (empty($statement_end_date)) { - $statement_end_date = strtotime("-6 month"); + $statement_end_date = strtotime("-1 month"); } @@ -171,9 +170,7 @@ private function build_statement($client_id, $statement_start_date = null, $stat $this->mdl_statement->setOpening_balance($client_opening_balance); - - // $statement_start_date = strtotime("-1 month"); - $statement_start_date = strtotime("-6 month"); + $statement_start_date = strtotime("-1 month"); $statement_end_date = time(); $this->mdl_statement->setStatement_start_date(date('Y-m-d', $statement_start_date)); From b79d54f0b9347bb895c31f0d96cb244230741205 Mon Sep 17 00:00:00 2001 From: Pradesh Chanderpaul Date: Tue, 9 Oct 2018 10:04:26 +0200 Subject: [PATCH 3/7] Fix for date overwrite with user values --- .../statements/controllers/Statements.php | 68 ++++++++++++------- application/modules/statements/views/view.php | 39 ++++++----- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/application/modules/statements/controllers/Statements.php b/application/modules/statements/controllers/Statements.php index 11c415d54f..08667305ff 100644 --- a/application/modules/statements/controllers/Statements.php +++ b/application/modules/statements/controllers/Statements.php @@ -66,12 +66,15 @@ public function view($client_id) if($this->input->method() === 'post') { - // We should use the form value if supplied, otherwise the hidden field sdate - $statement_start_date = strtotime($this->input->post('sdate')); + if (!empty($this->input->post('statement_start_date'))) { + $statement_start_date = strtotime($this->input->post('statement_start_date')); + } else { + $statement_start_date = strtotime($this->input->post('sdate')); + } $statement_end_date = strtotime($this->input->post('edate')); + $statement_date = strtotime($this->input->post('statement_date_created')); $statement_number = $this->input->post('statement_number'); - $statement_date = $this->input->post('statement_date_created'); $notes = $this->input->post('notes'); } else { @@ -88,8 +91,6 @@ public function view($client_id) $statement = $this->build_statement($client_id, $statement_start_date, $statement_end_date, $statement_date, $statement_number); - // TODO: Send statement number - $this->layout->set( array( @@ -128,33 +129,53 @@ private function build_statement($client_id, $statement_start_date = null, $stat $this->load->model('invoices/mdl_invoices'); $this->load->model('payments/mdl_payments'); - if (!empty($statement_number)){ - $this->mdl_statement->setStatement_number($statement_number); + /* + * Use the user supplied start date, or set the start date to a month ago + */ + if (empty($statement_start_date)) { + $statement_start_date = strtotime("-1 month"); + } - } else { - $this->mdl_statement->setStatement_number( 'STM-' . $client_id . '-' . date('ymd')); + /* + * Use the user supplied end date, or draw the statement up to now + */ + if (empty($statement_end_date)) { + $statement_end_date = time(); } /* - * Load the opening balance + * Use the user supplied statament date, or use the current date */ - if (empty($statement_start_date)) { - $statement_start_date = null; + if (empty($statement_date)) { + $statement_date = time(); } - if (empty($statement_end_date)) { - $statement_end_date = strtotime("-1 month"); + + /* + * Create the statement number based on the client id and date, or overwrite it with the user value. + */ + if (!empty($statement_number)) { + $this->mdl_statement->setStatement_number($statement_number); + } else { + $this->mdl_statement->setStatement_number( 'STM-' . $client_id . '-' . date('ymd')); } + /* + * Set the statement date to now, or overwrite it with the user value. + */ + $this->mdl_statement->setStatement_date(date('Y-m-d', $statement_date)); - $this->mdl_statement->setStatement_date( (!empty($statement_date)) ? $statement_date : date('Y-m-d')); + /* + * Calculate the opening statement as from the start of the user account to the start of the statement period + */ + $opening_balance_start_date = null; + $opening_balance_end_date = $statement_start_date; -// $this->mdl_statement->setStatement_start_date($statement_start_date); -// $this->mdl_statement->setStatement_end_date($statement_end_date); - $client_invoices = $this->mdl_invoices->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); - $client_payments = $this->mdl_payments->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); + $client_invoices = $this->mdl_invoices->by_client($client_id)->by_date_range($opening_balance_start_date, $opening_balance_end_date)->get()->result(); + $client_payments = $this->mdl_payments->by_client($client_id)->by_date_range($opening_balance_start_date, $opening_balance_end_date)->get()->result(); + $client_invoice_total = 0; foreach ($client_invoices as $invoice_entry) { @@ -170,8 +191,6 @@ private function build_statement($client_id, $statement_start_date = null, $stat $this->mdl_statement->setOpening_balance($client_opening_balance); - $statement_start_date = strtotime("-1 month"); - $statement_end_date = time(); $this->mdl_statement->setStatement_start_date(date('Y-m-d', $statement_start_date)); $this->mdl_statement->setStatement_end_date(date('Y-m-d', $statement_end_date)); @@ -266,8 +285,11 @@ public function generate_pdf() $client_id = $this->input->post('cid'); $statement_number = $this->input->post('statement_number'); - // We should use the form value if supplied, otherwise the hidden field sdate - $statement_start_date = strtotime($this->input->post('sdate')); + if (!empty($this->input->post('statement_start_date'))) { + $statement_start_date = strtotime($this->input->post('statement_start_date')); + } else { + $statement_start_date = strtotime($this->input->post('sdate')); + } $statement_end_date = strtotime($this->input->post('edate')); $statement_date = $this->input->post('statement_date_created'); diff --git a/application/modules/statements/views/view.php b/application/modules/statements/views/view.php index 26422315bb..a8d88cb3fc 100644 --- a/application/modules/statements/views/view.php +++ b/application/modules/statements/views/view.php @@ -131,20 +131,16 @@ value ="" placeholder="statement number" > -
    -
    - - - + + + + - + layout->load_view('statements/partial_item_table'); ?> -
    +
    -
    -
    +
    +
    -
    -
    +
    +
    -
    - -
    -
    +
    + +
    +
    -

    +
    +
    +
    -
    -
    +
    +
    -
    - + + From 43822c654fc32db8de5c56afe88df9225b86796a Mon Sep 17 00:00:00 2001 From: Pradesh Chanderpaul Date: Sun, 11 Nov 2018 07:30:23 +0200 Subject: [PATCH 6/7] Code formatting change due to review comments --- application/helpers/pdf_helper.php | 10 +- .../modules/invoices/models/Mdl_invoices.php | 5 +- .../modules/payments/models/Mdl_payments.php | 5 +- .../statements/controllers/Statements.php | 10 +- .../statements/models/Mdl_statement.php | 19 +- application/modules/statements/views/view.php | 215 +++++++++--------- 6 files changed, 123 insertions(+), 141 deletions(-) diff --git a/application/helpers/pdf_helper.php b/application/helpers/pdf_helper.php index d0f2a90934..3e26018206 100644 --- a/application/helpers/pdf_helper.php +++ b/application/helpers/pdf_helper.php @@ -264,8 +264,6 @@ function generate_quote_pdf($quote_id, $stream = true, $quote_template = null) * * @param Mdl_Clients $client * @param Mdl_Statement $statement - - * @param $notes * * @return string @@ -273,7 +271,6 @@ function generate_quote_pdf($quote_id, $stream = true, $quote_template = null) */ function generate_statement_pdf($client, $statement, $notes) { - $CI = &get_instance(); // Override language with system language @@ -285,9 +282,9 @@ function generate_statement_pdf($client, $statement, $notes) } $data = array( - 'client' => $client, - 'statement' => $statement, - 'notes' => $notes, + 'client' => $client, + 'statement' => $statement, + 'notes' => $notes, ); $html = $CI->load->view('statement_templates/pdf/' . $statement_template, $data, true); @@ -296,5 +293,6 @@ function generate_statement_pdf($client, $statement, $notes) $pdf_password = null; $stream = true; + return pdf_create($html, trans('statement') . '_' . str_replace(array('\\', '/'), '_', $statement->GetStatement_number()), $stream, $pdf_password); } diff --git a/application/modules/invoices/models/Mdl_invoices.php b/application/modules/invoices/models/Mdl_invoices.php index b35210e038..29eaf08688 100644 --- a/application/modules/invoices/models/Mdl_invoices.php +++ b/application/modules/invoices/models/Mdl_invoices.php @@ -525,19 +525,18 @@ public function by_client($client_id) $this->filter_where('ip_invoices.client_id', $client_id); return $this; } - + /** * Filter query in a date range. * The filter can be open ended on one end by not supplied a value * Dates must be in unixtime format - * + * * @param time $start_date * @param time $end_date * @return Mdl_Invoices */ public function by_date_range($start_date = null, $end_date = null) { - if (!empty($start_date)) { $this->filter_where("invoice_date_created >= '" . date('Y-m-d', $start_date) . "' "); } diff --git a/application/modules/payments/models/Mdl_payments.php b/application/modules/payments/models/Mdl_payments.php index b04c1a3ac2..cb70fdfcbc 100755 --- a/application/modules/payments/models/Mdl_payments.php +++ b/application/modules/payments/models/Mdl_payments.php @@ -222,7 +222,7 @@ public function by_client($client_id) $this->filter_where('ip_clients.client_id', $client_id); return $this; } - + /** * Filter query in a date range. * The filter can be open ended on one end by not supplied a value @@ -234,14 +234,13 @@ public function by_client($client_id) */ public function by_date_range($start_date = null, $end_date = null) { - if (!empty($start_date)) { $this->filter_where("invoice_date_modified >= '" . date('Y-m-d', $start_date) . "' "); } if (!empty($end_date)) { $this->filter_where("invoice_date_modified <= '" . date('Y-m-d', $end_date) . "' "); } - + return $this; } diff --git a/application/modules/statements/controllers/Statements.php b/application/modules/statements/controllers/Statements.php index 286dcecda4..223dacd475 100644 --- a/application/modules/statements/controllers/Statements.php +++ b/application/modules/statements/controllers/Statements.php @@ -17,7 +17,6 @@ */ class Statements extends Admin_Controller { - const TRANSACTION_TYPE_INVOICE = 1; const TRANSACTION_TYPE_CREDIT_NOTE = 2; const TRANSACTION_TYPE_PAYMENT = 3; @@ -30,7 +29,6 @@ public function __construct() parent::__construct(); $this->load->model('clients/mdl_clients'); - } public function index($client_id) @@ -44,7 +42,6 @@ public function index($client_id) */ public function view($client_id) { - $this->load->model('custom_fields/mdl_client_custom'); /* @@ -89,7 +86,6 @@ public function view($client_id) $statement = $this->build_statement($client_id, $statement_start_date, $statement_end_date, $statement_date, $statement_number); - $this->layout->set( array( @@ -129,7 +125,6 @@ public function view($client_id) */ private function build_statement($client_id, $statement_start_date = null, $statement_end_date = null, $statement_date = null, $statement_number = null) { - $this->load->model('mdl_statement'); $this->load->model('invoices/mdl_invoices'); @@ -275,7 +270,6 @@ private function build_statement($client_id, $statement_start_date = null, $stat $this->mdl_statement->setStatement_balance($client_total_balance); - return $this->mdl_statement; } @@ -287,8 +281,8 @@ private function build_statement($client_id, $statement_start_date = null, $stat */ public function generate_pdf() { - $this->load->model('clients/mdl_clients'); + $this->load->helper('country'); $client_id = $this->input->post('cid'); $statement_number = $this->input->post('statement_number'); @@ -303,7 +297,6 @@ public function generate_pdf() $statement_date = strtotime($this->input->post('statement_date_created')); $notes = $this->input->post('notes'); - /* * Load the client */ @@ -317,7 +310,6 @@ public function generate_pdf() $statement = $this->build_statement($client->client_id, $statement_start_date, $statement_end_date); - $this->load->helper('pdf'); generate_statement_pdf($client, $statement, $notes); diff --git a/application/modules/statements/models/Mdl_statement.php b/application/modules/statements/models/Mdl_statement.php index 91903dab58..ba9a7b958c 100644 --- a/application/modules/statements/models/Mdl_statement.php +++ b/application/modules/statements/models/Mdl_statement.php @@ -16,9 +16,8 @@ * (Currently) a non-persistent store of a current client statement request * */ -class Mdl_Statement extends CI_Model { - - +class Mdl_Statement extends CI_Model +{ private $statement_transactions; private $statement_start_date; @@ -32,6 +31,10 @@ class Mdl_Statement extends CI_Model { private $statement_number; + public function __construct() + { + parent::__construct(); + } /** * @return mixed @@ -144,12 +147,4 @@ public function setStatement_balance($statement_balance) { $this->statement_balance = $statement_balance; } - - public function __construct() - { - parent::__construct(); - } - - - -} \ No newline at end of file +} diff --git a/application/modules/statements/views/view.php b/application/modules/statements/views/view.php index e1259859a4..3228aafcf2 100644 --- a/application/modules/statements/views/view.php +++ b/application/modules/statements/views/view.php @@ -3,9 +3,8 @@ * @var Client client */ ?> -
    -

    +

    @@ -16,26 +15,26 @@ layout->load_view('layout/alerts'); ?>
    - - - + + + - +
    -
    - -
    -
    - -

    - - - -

    -
    -
    - layout->load_view('clients/partial_client_address', ['client' => $client]); ?> -
    +
    + +
    +
    + +

    + + + +

    +
    +
    + layout->load_view('clients/partial_client_address', ['client' => $client]); ?> +
    client_phone || $client->client_email) : ?>
    @@ -54,120 +53,120 @@
    -
    -
    -
    +
    +
    +
    -
    -
    -
    +
    +
    +
    -
    +
    -
    -
    -
    -
    - -
    +
    +
    + +
    -
    -
    +
    +
    -
    -
    +
    + + +
    +
    + + + +
    +
    + +
    + +
    -
    -
    -
    -
    +
    +
    +
    +
    -
    +
    layout->load_view('statements/partial_item_table'); ?>
    -
    -
    +
    +
    -
    -
    +
    +
    -
    - -
    -
    +
    + +
    +
    -
    -
    -
    +
    +
    +
    -
    -
    +
    +
    -
    - +
    +
    From ec0d44ec160b0adaa620b9ac478af514269cebaf Mon Sep 17 00:00:00 2001 From: Pradesh Chanderpaul Date: Mon, 10 Jun 2019 23:21:59 +0200 Subject: [PATCH 7/7] Fix date formats and date calculations;fix for payment calculation --- .../modules/invoices/models/Mdl_invoices.php | 4 +- .../modules/payments/models/Mdl_payments.php | 4 +- .../modules/statements/controllers/Ajax.php | 421 ------------------ .../statements/controllers/Statements.php | 56 ++- .../statements/views/partial_item_table.php | 2 +- .../statement_templates/pdf/InvoicePlane.php | 8 +- application/modules/statements/views/view.php | 4 +- 7 files changed, 55 insertions(+), 444 deletions(-) delete mode 100644 application/modules/statements/controllers/Ajax.php diff --git a/application/modules/invoices/models/Mdl_invoices.php b/application/modules/invoices/models/Mdl_invoices.php index 29eaf08688..739c3bc36e 100644 --- a/application/modules/invoices/models/Mdl_invoices.php +++ b/application/modules/invoices/models/Mdl_invoices.php @@ -538,10 +538,10 @@ public function by_client($client_id) public function by_date_range($start_date = null, $end_date = null) { if (!empty($start_date)) { - $this->filter_where("invoice_date_created >= '" . date('Y-m-d', $start_date) . "' "); + $this->filter_where("invoice_date_created >= '" . $start_date . "' "); } if (!empty($end_date)) { - $this->filter_where("invoice_date_created <= '" . date('Y-m-d', $end_date) . "' "); + $this->filter_where("invoice_date_created <= '" . $end_date . "' "); } return $this; diff --git a/application/modules/payments/models/Mdl_payments.php b/application/modules/payments/models/Mdl_payments.php index cb70fdfcbc..76f5aff46e 100755 --- a/application/modules/payments/models/Mdl_payments.php +++ b/application/modules/payments/models/Mdl_payments.php @@ -235,10 +235,10 @@ public function by_client($client_id) public function by_date_range($start_date = null, $end_date = null) { if (!empty($start_date)) { - $this->filter_where("invoice_date_modified >= '" . date('Y-m-d', $start_date) . "' "); + $this->filter_where("payment_date >= '" . $start_date . "' "); } if (!empty($end_date)) { - $this->filter_where("invoice_date_modified <= '" . date('Y-m-d', $end_date) . "' "); + $this->filter_where("payment_date <= '" . $end_date . "' "); } return $this; diff --git a/application/modules/statements/controllers/Ajax.php b/application/modules/statements/controllers/Ajax.php deleted file mode 100644 index 6b948ad213..0000000000 --- a/application/modules/statements/controllers/Ajax.php +++ /dev/null @@ -1,421 +0,0 @@ -load->model('quotes/mdl_quote_items'); - $this->load->model('quotes/mdl_quotes'); - $this->load->model('units/mdl_units'); - - $quote_id = $this->input->post('quote_id'); - - $this->mdl_quotes->set_id($quote_id); - - if ($this->mdl_quotes->run_validation('validation_rules_save_quote')) { - $items = json_decode($this->input->post('items')); - - foreach ($items as $item) { - if ($item->item_name) { - $item->item_quantity = ($item->item_quantity ? standardize_amount($item->item_quantity) : floatval(0)); - $item->item_price = ($item->item_quantity ? standardize_amount($item->item_price) : floatval(0)); - $item->item_discount_amount = ($item->item_discount_amount) ? standardize_amount($item->item_discount_amount) : null; - $item->item_product_id = ($item->item_product_id ? $item->item_product_id : null); - $item->item_product_unit_id = ($item->item_product_unit_id ? $item->item_product_unit_id : null); - $item->item_product_unit = $this->mdl_units->get_name($item->item_product_unit_id, $item->item_quantity); - - $item_id = ($item->item_id) ?: null; - unset($item->item_id); - - $this->mdl_quote_items->save($item_id, $item); - } - } - - if ($this->input->post('quote_discount_amount') === '') { - $quote_discount_amount = floatval(0); - } else { - $quote_discount_amount = $this->input->post('quote_discount_amount'); - } - - if ($this->input->post('quote_discount_percent') === '') { - $quote_discount_percent = floatval(0); - } else { - $quote_discount_percent = $this->input->post('quote_discount_percent'); - } - - // Generate new quote number if needed - $quote_number = $this->input->post('quote_number'); - $quote_status_id = $this->input->post('quote_status_id'); - - if (empty($quote_number) && $quote_status_id != 1) { - $quote_group_id = $this->mdl_quotes->get_invoice_group_id($quote_id); - $quote_number = $this->mdl_quotes->get_quote_number($quote_group_id); - } - - $db_array = [ - 'quote_number' => $quote_number, - 'quote_date_created' => date_to_mysql($this->input->post('quote_date_created')), - 'quote_date_expires' => date_to_mysql($this->input->post('quote_date_expires')), - 'quote_status_id' => $quote_status_id, - 'quote_password' => $this->input->post('quote_password'), - 'notes' => $this->input->post('notes'), - 'quote_discount_amount' => standardize_amount($quote_discount_amount), - 'quote_discount_percent' => standardize_amount($quote_discount_percent), - ]; - - $this->mdl_quotes->save($quote_id, $db_array); - - // Recalculate for discounts - $this->load->model('quotes/mdl_quote_amounts'); - $this->mdl_quote_amounts->calculate($quote_id); - - $response = [ - 'success' => 1, - ]; - } else { - $this->load->helper('json_error'); - $response = [ - 'success' => 0, - 'validation_errors' => json_errors(), - ]; - } - - - // Save all custom fields - if ($this->input->post('custom')) { - $db_array = []; - - $values = []; - foreach ($this->input->post('custom') as $custom) { - if (preg_match("/^(.*)\[\]$/i", $custom['name'], $matches)) { - $values[$matches[1]][] = $custom['value']; - } else { - $values[$custom['name']] = $custom['value']; - } - } - - foreach ($values as $key => $value) { - preg_match("/^custom\[(.*?)\](?:\[\]|)$/", $key, $matches); - if ($matches) { - $db_array[$matches[1]] = $value; - } - } - $this->load->model('custom_fields/mdl_quote_custom'); - $result = $this->mdl_quote_custom->save_custom($quote_id, $db_array); - if ($result !== true) { - $response = [ - 'success' => 0, - 'validation_errors' => $result, - ]; - - echo json_encode($response); - exit; - } - } - - echo json_encode($response); - } - - public function save_quote_tax_rate() - { - $this->load->model('quotes/mdl_quote_tax_rates'); - - if ($this->mdl_quote_tax_rates->run_validation()) { - $this->mdl_quote_tax_rates->save(); - - $response = [ - 'success' => 1, - ]; - } else { - $response = [ - 'success' => 0, - 'validation_errors' => $this->mdl_quote_tax_rates->validation_errors, - ]; - } - - echo json_encode($response); - } - - public function create() - { - $this->load->model('quotes/mdl_quotes'); - - if ($this->mdl_quotes->run_validation()) { - $quote_id = $this->mdl_quotes->create(); - - $response = [ - 'success' => 1, - 'quote_id' => $quote_id, - ]; - } else { - $this->load->helper('json_error'); - $response = [ - 'success' => 0, - 'validation_errors' => json_errors(), - ]; - } - - echo json_encode($response); - } - - public function modal_change_client() - { - $this->load->module('layout'); - $this->load->model('clients/mdl_clients'); - - $data = [ - 'client_id' => $this->input->post('client_id'), - 'quote_id' => $this->input->post('quote_id'), - 'clients' => $this->mdl_clients->get_latest(), - ]; - - $this->layout->load_view('quotes/modal_change_client', $data); - } - - public function change_client() - { - $this->load->model('quotes/mdl_quotes'); - $this->load->model('clients/mdl_clients'); - - // Get the client ID - $client_id = $this->input->post('client_id'); - $client = $this->mdl_clients->where('ip_clients.client_id', $client_id) - ->get()->row(); - - if (!empty($client)) { - $quote_id = $this->input->post('quote_id'); - - $db_array = [ - 'client_id' => $client_id, - ]; - $this->db->where('quote_id', $quote_id); - $this->db->update('ip_quotes', $db_array); - - $response = [ - 'success' => 1, - 'quote_id' => $quote_id, - ]; - } else { - $this->load->helper('json_error'); - $response = [ - 'success' => 0, - 'validation_errors' => json_errors(), - ]; - } - - echo json_encode($response); - } - - public function get_item() - { - $this->load->model('quotes/mdl_quote_items'); - - $item = $this->mdl_quote_items->get_by_id($this->input->post('item_id')); - - echo json_encode($item); - } - - public function modal_create_quote() - { - $this->load->module('layout'); - $this->load->model('invoice_groups/mdl_invoice_groups'); - $this->load->model('tax_rates/mdl_tax_rates'); - $this->load->model('clients/mdl_clients'); - - $data = [ - 'invoice_groups' => $this->mdl_invoice_groups->get()->result(), - 'tax_rates' => $this->mdl_tax_rates->get()->result(), - 'client' => $this->mdl_clients->get_by_id($this->input->post('client_id')), - 'clients' => $this->mdl_clients->get_latest(), - ]; - - $this->layout->load_view('quotes/modal_create_quote', $data); - } - - public function modal_copy_quote() - { - $this->load->module('layout'); - - $this->load->model('quotes/mdl_quotes'); - $this->load->model('invoice_groups/mdl_invoice_groups'); - $this->load->model('tax_rates/mdl_tax_rates'); - $this->load->model('clients/mdl_clients'); - - $data = [ - 'invoice_groups' => $this->mdl_invoice_groups->get()->result(), - 'tax_rates' => $this->mdl_tax_rates->get()->result(), - 'quote_id' => $this->input->post('quote_id'), - 'quote' => $this->mdl_quotes->where('ip_quotes.quote_id', $this->input->post('quote_id'))->get()->row(), - 'client' => $this->mdl_clients->get_by_id($this->input->post('client_id')), - ]; - - $this->layout->load_view('quotes/modal_copy_quote', $data); - } - - public function copy_quote() - { - $this->load->model('quotes/mdl_quotes'); - $this->load->model('quotes/mdl_quote_items'); - $this->load->model('quotes/mdl_quote_tax_rates'); - - if ($this->mdl_quotes->run_validation()) { - $target_id = $this->mdl_quotes->save(); - $source_id = $this->input->post('quote_id'); - - $this->mdl_quotes->copy_quote($source_id, $target_id); - - $response = [ - 'success' => 1, - 'quote_id' => $target_id, - ]; - } else { - $this->load->helper('json_error'); - $response = [ - 'success' => 0, - 'validation_errors' => json_errors(), - ]; - } - - echo json_encode($response); - } - - public function modal_quote_to_invoice($quote_id) - { - $this->load->model('invoice_groups/mdl_invoice_groups'); - $this->load->model('quotes/mdl_quotes'); - - $data = [ - 'invoice_groups' => $this->mdl_invoice_groups->get()->result(), - 'quote_id' => $quote_id, - 'quote' => $this->mdl_quotes->where('ip_quotes.quote_id', $quote_id)->get()->row(), - ]; - - $this->load->view('quotes/modal_quote_to_invoice', $data); - } - - public function quote_to_invoice() - { - $this->load->model( - [ - 'invoices/mdl_invoices', - 'invoices/mdl_items', - 'quotes/mdl_quotes', - 'quotes/mdl_quote_items', - 'invoices/mdl_invoice_tax_rates', - 'quotes/mdl_quote_tax_rates', - ] - ); - - if ($this->mdl_invoices->run_validation()) { - // Get the quote - $quote = $this->mdl_quotes->get_by_id($this->input->post('quote_id')); - - $invoice_id = $this->mdl_invoices->create(null, false); - - // Update the discounts - $this->db->where('invoice_id', $invoice_id); - $this->db->set('invoice_discount_amount', $quote->quote_discount_amount); - $this->db->set('invoice_discount_percent', $quote->quote_discount_percent); - $this->db->update('ip_invoices'); - - // Save the invoice id to the quote - $this->db->where('quote_id', $this->input->post('quote_id')); - $this->db->set('invoice_id', $invoice_id); - $this->db->update('ip_quotes'); - - $quote_items = $this->mdl_quote_items->where('quote_id', $this->input->post('quote_id'))->get()->result(); - - foreach ($quote_items as $quote_item) { - $db_array = [ - 'invoice_id' => $invoice_id, - 'item_tax_rate_id' => $quote_item->item_tax_rate_id, - 'item_product_id' => $quote_item->item_product_id, - 'item_name' => $quote_item->item_name, - 'item_description' => $quote_item->item_description, - 'item_quantity' => $quote_item->item_quantity, - 'item_price' => $quote_item->item_price, - 'item_product_unit_id' => $quote_item->item_product_unit_id, - 'item_product_unit' => $quote_item->item_product_unit, - 'item_discount_amount' => $quote_item->item_discount_amount, - 'item_order' => $quote_item->item_order, - ]; - - $this->mdl_items->save(null, $db_array); - } - - $quote_tax_rates = $this->mdl_quote_tax_rates->where('quote_id', $this->input->post('quote_id')) - ->get() - ->result(); - - foreach ($quote_tax_rates as $quote_tax_rate) { - $db_array = [ - 'invoice_id' => $invoice_id, - 'tax_rate_id' => $quote_tax_rate->tax_rate_id, - 'include_item_tax' => $quote_tax_rate->include_item_tax, - 'invoice_tax_rate_amount' => $quote_tax_rate->quote_tax_rate_amount, - ]; - - $this->mdl_invoice_tax_rates->save(null, $db_array); - } - - $response = [ - 'success' => 1, - 'invoice_id' => $invoice_id, - ]; - } else { - $this->load->helper('json_error'); - $response = [ - 'success' => 0, - 'validation_errors' => json_errors(), - ]; - } - - echo json_encode($response); - } - - /** - * @param $quote_id - */ - public function delete_item($quote_id) - { - $success = 0; - $item_id = $this->input->post('item_id'); - $this->load->model('mdl_quotes'); - - // Only continue if the invoice exists or no item id was provided - if ($this->mdl_quotes->get_by_id($quote_id) || empty($item_id)) { - - // Delete invoice item - $this->load->model('mdl_quote_items'); - $item = $this->mdl_quote_items->delete($item_id); - - // Check if deletion was successful - if ($item) { - $success = 1; - } - - } - - // Return the response - echo json_encode([ - 'success' => $success, - ]); - } - -} diff --git a/application/modules/statements/controllers/Statements.php b/application/modules/statements/controllers/Statements.php index 223dacd475..aace9bf558 100644 --- a/application/modules/statements/controllers/Statements.php +++ b/application/modules/statements/controllers/Statements.php @@ -63,13 +63,21 @@ public function view($client_id) { if (!empty($this->input->post('statement_start_date'))) { - $statement_start_date = strtotime($this->input->post('statement_start_date')); + // BUG : strtotime is not recognising the date format d M,Y" and changing the date + // $statement_start_date = strtotime($this->input->post('statement_start_date')); + $date_time = date_create_from_format("d M,Y", $this->input->post('statement_start_date')); + $statement_start_date = $date_time->getTimestamp(); + } else { $statement_start_date = strtotime($this->input->post('sdate')); } - $statement_end_date = strtotime($this->input->post('edate')); + $statement_end_date = $this->input->post('edate'); + + // BUG : strtotime is not recognising the date format d M,Y" and changing the date + // $statement_date = strtotime($this->input->post('statement_date_created')); + $date_time = date_create_from_format("d M,Y", $this->input->post('statement_date_created')); + $statement_date = $date_time->getTimestamp(); - $statement_date = strtotime($this->input->post('statement_date_created')); $statement_number = $this->input->post('statement_number'); $notes = $this->input->post('notes'); @@ -164,7 +172,7 @@ private function build_statement($client_id, $statement_start_date = null, $stat /* * Set the statement date to now, or overwrite it with the user value. */ - $this->mdl_statement->setStatement_date(date('Y-m-d', $statement_date)); + $this->mdl_statement->setStatement_date($statement_date); /* @@ -174,8 +182,16 @@ private function build_statement($client_id, $statement_start_date = null, $stat $opening_balance_end_date = $statement_start_date; - $client_invoices = $this->mdl_invoices->by_client($client_id)->by_date_range($opening_balance_start_date, $opening_balance_end_date)->get()->result(); - $client_payments = $this->mdl_payments->by_client($client_id)->by_date_range($opening_balance_start_date, $opening_balance_end_date)->get()->result(); + $client_invoices = $this->mdl_invoices + ->by_client($client_id) + ->by_date_range(date('Y-m-d', $opening_balance_start_date), date('Y-m-d', $opening_balance_end_date)) + ->get() + ->result(); + $client_payments = $this->mdl_payments + ->by_client($client_id) + ->by_date_range(date('Y-m-d', $opening_balance_start_date), date('Y-m-d', $opening_balance_end_date)) + ->get() + ->result(); $client_invoice_total = 0; @@ -193,16 +209,24 @@ private function build_statement($client_id, $statement_start_date = null, $stat $this->mdl_statement->setOpening_balance($client_opening_balance); - $this->mdl_statement->setStatement_start_date(date('Y-m-d', $statement_start_date)); - $this->mdl_statement->setStatement_end_date(date('Y-m-d', $statement_end_date)); + $this->mdl_statement->setStatement_start_date($statement_start_date); + $this->mdl_statement->setStatement_end_date($statement_end_date); /* * NOTE: These two calls brings back all invoices and payments over the * ...date range, and we manually sum up the totals */ - $client_invoices = $this->mdl_invoices->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); - $client_payments = $this->mdl_payments->by_client($client_id)->by_date_range($statement_start_date, $statement_end_date)->get()->result(); + $client_invoices = $this->mdl_invoices + ->by_client($client_id) + ->by_date_range(date('Y-m-d', $statement_start_date), date('Y-m-d', $statement_end_date)) + ->get() + ->result(); + $client_payments = $this->mdl_payments + ->by_client($client_id) + ->by_date_range(date('Y-m-d', $statement_start_date), date('Y-m-d', $statement_end_date)) + ->get() + ->result(); $statement_transactions = array(); @@ -288,13 +312,21 @@ public function generate_pdf() $statement_number = $this->input->post('statement_number'); if (!empty($this->input->post('statement_start_date'))) { - $statement_start_date = strtotime($this->input->post('statement_start_date')); + //$statement_start_date = strtotime($this->input->post('statement_start_date')); + $date_time = date_create_from_format("d M,Y", $this->input->post('statement_start_date')); + $statement_start_date = $date_time->getTimestamp(); + } else { $statement_start_date = strtotime($this->input->post('sdate')); } $statement_end_date = strtotime($this->input->post('edate')); - $statement_date = strtotime($this->input->post('statement_date_created')); + // BUG : strtotime is not recognising the date format d M,Y" and changing the date + // $statement_date = strtotime($this->input->post('statement_date_created')); + $date_time = date_create_from_format("d M,Y", $this->input->post('statement_date_created')); + $statement_date = $date_time->getTimestamp(); + + $notes = $this->input->post('notes'); /* diff --git a/application/modules/statements/views/partial_item_table.php b/application/modules/statements/views/partial_item_table.php index f14def243e..5ee19def80 100644 --- a/application/modules/statements/views/partial_item_table.php +++ b/application/modules/statements/views/partial_item_table.php @@ -26,7 +26,7 @@ - + diff --git a/application/modules/statements/views/statement_templates/pdf/InvoicePlane.php b/application/modules/statements/views/statement_templates/pdf/InvoicePlane.php index 117cfd23f1..1a52ca7f2b 100644 --- a/application/modules/statements/views/statement_templates/pdf/InvoicePlane.php +++ b/application/modules/statements/views/statement_templates/pdf/InvoicePlane.php @@ -71,15 +71,15 @@ - + - + - +
    getStatement_date(), true); ?>getStatement_date()); ?>
    getStatement_start_date(), true); ?>getStatement_start_date()); ?>
    getStatement_end_date(), true); ?>getStatement_end_date()); ?>
    @@ -107,7 +107,7 @@ - GetStatement_start_date(); ?> + GetStatement_start_date(); ?> diff --git a/application/modules/statements/views/view.php b/application/modules/statements/views/view.php index 3228aafcf2..17bfcc2a19 100644 --- a/application/modules/statements/views/view.php +++ b/application/modules/statements/views/view.php @@ -101,7 +101,7 @@ class="form-control input-sm" value="">
    + value="" /> @@ -116,7 +116,7 @@ class="fa fa-calendar fa-fw">